bool TranslationUnitManager::CreateCompilationDatabase(cbProject* proj)
{
   wxJSONValue root;
   auto count = proj->GetFilesCount();

   for (int i = 0; i < count ; ++i)
   {
       ProjectFile* projFile = proj->GetFile(i);
       auto targetNames = projFile->GetBuildTargets();
       if (targetNames.IsEmpty())
           continue;
       auto target = proj->GetBuildTarget(targetNames[0]);

       auto* compiler = CompilerFactory::GetCompiler(target->GetCompilerID());

       wxJSONValue currNode;
       currNode["directory"] = wxString(".");
       //Compilation database cannot read windows style slashes
       wxString filePath = projFile->file.GetFullPath();
       currNode["file"] = UnixFilename(filePath,wxPATH_UNIX);

       CommandLineGenerator dc(compiler, proj);
       wxString commandLine;
       wxArrayString commandArray = dc.GetCompileFileCommand(target,projFile);
       for (const auto& z : commandArray)
       {
          commandLine.Append(z);
       }

       if (commandLine.IsEmpty())
           continue;

       currNode["command"] = UnixFilename(commandLine,wxPATH_UNIX);
       root.Append(currNode);
    }
    wxJSONWriter writer;
    wxFileOutputStream outFile("compile_commands.json");
    writer.Write(root,outFile);
    return true;
}
Example #2
0
// Don't call this function from within the scope of:
//      ClangPlugin::OnEditorHook
//      ClangPlugin::OnTimer
int ClangPlugin::UpdateCompileCommand(cbEditor* ed)
{
    wxString compileCommand;
    ProjectFile* pf = ed->GetProjectFile();

    m_UpdateCompileCommand++;
    if ( m_UpdateCompileCommand > 1 )
    {
        // Re-entry is not allowed
        m_UpdateCompileCommand--;
        return 0;
    }

    ProjectBuildTarget* target = nullptr;
    Compiler* comp = nullptr;
    if (pf && pf->GetParentProject() && !pf->GetBuildTargets().IsEmpty())
    {
        target = pf->GetParentProject()->GetBuildTarget(pf->GetBuildTargets()[0]);
        comp = CompilerFactory::GetCompiler(target->GetCompilerID());
    }
    cbProject* proj = (pf ? pf->GetParentProject() : nullptr);
    if ( (!comp) && proj)
        comp = CompilerFactory::GetCompiler(proj->GetCompilerID());
    if (!comp)
    {
        cbProject* tmpPrj = Manager::Get()->GetProjectManager()->GetActiveProject();
        if (tmpPrj)
            comp = CompilerFactory::GetCompiler(tmpPrj->GetCompilerID());
    }
    if (!comp)
        comp = CompilerFactory::GetDefaultCompiler();

    if (pf && (!pf->GetBuildTargets().IsEmpty()) )
    {
        target = pf->GetParentProject()->GetBuildTarget(pf->GetBuildTargets()[0]);

        if (pf->GetUseCustomBuildCommand(target->GetCompilerID() ))
            compileCommand = pf->GetCustomBuildCommand(target->GetCompilerID()).AfterFirst(wxT(' '));

    }

    if (compileCommand.IsEmpty())
        compileCommand = wxT("$options $includes");
    CompilerCommandGenerator* gen = comp->GetCommandGenerator(proj);
    if (gen)
        gen->GenerateCommandLine(compileCommand, target, pf, ed->GetFilename(),
                g_InvalidStr, g_InvalidStr, g_InvalidStr );
    delete gen;

    wxStringTokenizer tokenizer(compileCommand);
    compileCommand.Empty();
    wxString pathStr;
    while (tokenizer.HasMoreTokens())
    {
        wxString flag = tokenizer.GetNextToken();
        // make all include paths absolute, so clang does not choke if Code::Blocks switches directories
        if (flag.StartsWith(wxT("-I"), &pathStr))
        {
            wxFileName path(pathStr);
            if (path.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE))
                flag = wxT("-I") + path.GetFullPath();
        }
        compileCommand += flag + wxT(" ");
    }
    compileCommand += GetCompilerInclDirs(comp->GetID());

    m_UpdateCompileCommand--;

    if (compileCommand != m_CompileCommand)
    {
        m_CompileCommand = compileCommand;
        return 1;
    }
    return 0;
}
Example #3
0
void ClangPlugin::OnTimer(wxTimerEvent& event)
{
    if (!IsAttached())
        return;
    const int evId = event.GetId();
    if (evId == idEdOpenTimer)
    {
        cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
        if (!ed || !IsProviderFor(ed))
            return;
        else if (m_Proxy.GetTranslationUnitId(ed->GetFilename()) != wxNOT_FOUND)
        {
            m_DiagnosticTimer.Start(DIAGNOSTIC_DELAY, wxTIMER_ONE_SHOT);
            return;
        }
        wxString compileCommand;
        ProjectFile* pf = ed->GetProjectFile();
        ProjectBuildTarget* target = nullptr;
        Compiler* comp = nullptr;
        if (pf && pf->GetParentProject() && !pf->GetBuildTargets().IsEmpty() )
        {
            target = pf->GetParentProject()->GetBuildTarget(pf->GetBuildTargets()[0]);
            comp = CompilerFactory::GetCompiler(target->GetCompilerID());
            if (pf->GetUseCustomBuildCommand(target->GetCompilerID()))
            {
                compileCommand = pf->GetCustomBuildCommand(target->GetCompilerID()).AfterFirst(wxT(' '));
            }
        }
        if (compileCommand.IsEmpty())
            compileCommand = wxT("$options $includes");
        cbProject* proj = (pf ? pf->GetParentProject() : nullptr);
        if (!comp && proj)
            comp = CompilerFactory::GetCompiler(proj->GetCompilerID());
        if (!comp)
        {
            cbProject* tmpPrj = Manager::Get()->GetProjectManager()->GetActiveProject();
            if (tmpPrj)
                comp = CompilerFactory::GetCompiler(tmpPrj->GetCompilerID());
        }
        if (!comp)
            comp = CompilerFactory::GetDefaultCompiler();
        comp->GetCommandGenerator(proj)->GenerateCommandLine(compileCommand, target, pf, ed->GetFilename(),
                                                             g_InvalidStr, g_InvalidStr, g_InvalidStr );
        wxStringTokenizer tokenizer(compileCommand);
        compileCommand.Empty();
        wxString pathStr;
        while (tokenizer.HasMoreTokens())
        {
            wxString flag = tokenizer.GetNextToken();
            // make all include paths absolute, so clang does not choke if Code::Blocks switches directories
            if (flag.StartsWith(wxT("-I"), &pathStr))
            {
                wxFileName path(pathStr);
                if (path.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE))
                    flag = wxT("-I") + path.GetFullPath();
            }
            compileCommand += flag + wxT(" ");
        }
        compileCommand += GetCompilerInclDirs(comp->GetID());
        if (FileTypeOf(ed->GetFilename()) == ftHeader) // try to find the associated source
        {
            const wxString& source = GetSourceOf(ed);
            if (!source.IsEmpty())
            {
                m_Proxy.CreateTranslationUnit(source, compileCommand);
                if (m_Proxy.GetTranslationUnitId(ed->GetFilename()) != wxNOT_FOUND)
                    return; // got it
            }
        }
        m_Proxy.CreateTranslationUnit(ed->GetFilename(), compileCommand);
        m_DiagnosticTimer.Start(DIAGNOSTIC_DELAY, wxTIMER_ONE_SHOT);
    }
    else if (evId == idReparseTimer)
    {
        EditorManager* edMgr = Manager::Get()->GetEditorManager();
        cbEditor* ed = edMgr->GetBuiltinActiveEditor();
        if (!ed)
            return;
        if (ed != m_pLastEditor)
        {
            m_TranslUnitId = m_Proxy.GetTranslationUnitId(ed->GetFilename());
            m_pLastEditor = ed;
        }
        if (m_TranslUnitId == wxNOT_FOUND)
            return;
        std::map<wxString, wxString> unsavedFiles;
        for (int i = 0; i < edMgr->GetEditorsCount(); ++i)
        {
            ed = edMgr->GetBuiltinEditor(i);
            if (ed && ed->GetModified())
                unsavedFiles.insert(std::make_pair(ed->GetFilename(), ed->GetControl()->GetText()));
        }
        m_Proxy.Reparse(m_TranslUnitId, unsavedFiles);
        DiagnoseEd(m_pLastEditor, dlMinimal);
    }
    else if (evId == idDiagnosticTimer)
    {
        cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
        if (!ed)
            return;
        if (ed != m_pLastEditor)
        {
            m_TranslUnitId = m_Proxy.GetTranslationUnitId(ed->GetFilename());
            m_pLastEditor = ed;
        }
        if (m_TranslUnitId == wxNOT_FOUND)
            return;
        DiagnoseEd(ed, dlFull);
    }
    else
        event.Skip();
}