Ejemplo n.º 1
0
void ClangCodeCompletion::HighlightOccurrences(cbEditor* ed)
{
    ClTranslUnitId translId = GetCurrentTranslationUnitId();
    cbStyledTextCtrl* stc = ed->GetControl();
    int pos = stc->GetCurrentPos();
    const wxChar ch = stc->GetCharAt(pos);
    if (pos > 0
            && (wxIsspace(ch) || (ch != wxT('_') && wxIspunct(ch)))
            && !wxIsspace(stc->GetCharAt(pos - 1)))
    {
        --pos;
    }

    // chosen a high value for indicator, hoping not to interfere with the indicators used by some lexers
    // if they get updated from deprecated old style indicators someday.
    const int theIndicator = 16;
    stc->SetIndicatorCurrent(theIndicator);

    // Set Styling:
    // clear all style indications set in a previous run (is also done once after text gets unselected)
    stc->IndicatorClearRange(0, stc->GetLength());

    if (stc->GetTextRange(pos - 1, pos + 1).Strip().IsEmpty())
        return;

    // TODO: use independent key
    wxColour highlightColour(Manager::Get()->GetColourManager()->GetColour(wxT("editor_highlight_occurrence")));

    stc->IndicatorSetStyle(theIndicator, wxSCI_INDIC_HIGHLIGHT);
    stc->IndicatorSetForeground(theIndicator, highlightColour);
    stc->IndicatorSetUnder(theIndicator, true);

    const int line = stc->LineFromPosition(pos);
    ClTokenPosition loc(line + 1, pos - stc->PositionFromLine(line) + 1);

    std::vector< std::pair<int, int> > occurrences;
    m_pClangPlugin->GetOccurrencesOf( translId,  ed->GetFilename(), loc, 100, occurrences );

    for (std::vector< std::pair<int, int> >::const_iterator tkn = occurrences.begin();
            tkn != occurrences.end(); ++tkn)
    {
        stc->IndicatorFillRange(tkn->first, tkn->second);
    }
}
Ejemplo n.º 2
0
void ClangCodeCompletion::OnTimer(wxTimerEvent& event)
{
    if (!IsAttached())
    {
        return;
    }
    const int evId = event.GetId();
    cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
    if (!ed)
    {
        return;
    }

    if (evId == idReparseTimer) // m_ReparseTimer
    {
        //wxCommandEvent evt(cbEVT_COMMAND_REPARSE, idReparse);
        //AddPendingEvent(evt);
        m_pClangPlugin->RequestReparse( GetCurrentTranslationUnitId(), ed->GetFilename() );

    }
    else if (evId == idHighlightTimer)
    {
        //if (m_TranslUnitId == wxNOT_FOUND)
        //{
        //    return;
        //}
        HighlightOccurrences(ed);
    }
    else if (evId == idDiagnosticTimer)
    {
        //wxCommandEvent evt(cbEVT_COMMAND_DIAGNOSEED, idDiagnoseEd);
        //AddPendingEvent(evt);
    }
    else
    {
        event.Skip();
    }
}
Ejemplo n.º 3
0
void ClangDiagnostics::OnDiagnostics( ClangEvent& event )
{
    ClDiagnosticLevel diagLv = dlFull; // TODO
    bool update = false;
    EditorManager* edMgr = Manager::Get()->GetEditorManager();
    cbEditor* ed = edMgr->GetBuiltinActiveEditor();
    if (!ed)
    {
        std::cout<<"No editor..."<<std::endl;
        return;
    }
    if( event.GetTranslationUnitId() != GetCurrentTranslationUnitId() )
    {
        // Switched translation unit before event delivered
        return;
    }
    if( (diagLv == dlFull)&&(event.GetLocation().line != 0)&&(event.GetLocation().column != 0) )
    {
        update = true;
    }
    const std::vector<ClDiagnostic>& diagnostics = event.GetDiagnosticResults();
    cbStyledTextCtrl* stc = ed->GetControl();
    int firstVisibleLine = stc->GetFirstVisibleLine();
    if ((diagLv == dlFull)&&(!update) )
        stc->AnnotationClearAll();
    const int warningIndicator = 0; // predefined
    const int errorIndicator = 15; // hopefully we do not clash with someone else...
    stc->SetIndicatorCurrent(warningIndicator);
    if ( !update )
        stc->IndicatorClearRange(0, stc->GetLength());
    stc->IndicatorSetStyle(errorIndicator, wxSCI_INDIC_SQUIGGLE);
    stc->IndicatorSetForeground(errorIndicator, *wxRED);
    stc->SetIndicatorCurrent(errorIndicator);
    if ( !update )
        stc->IndicatorClearRange(0, stc->GetLength());
    const wxString& filename = ed->GetFilename();
    if ( (diagLv == dlFull)&&(update) )
    {
        int line = event.GetLocation().line-1;
        stc->AnnotationClearLine(line);
    }
    for ( std::vector<ClDiagnostic>::const_iterator dgItr = diagnostics.begin();
            dgItr != diagnostics.end(); ++dgItr )
    {
        //Manager::Get()->GetLogManager()->Log(dgItr->file + wxT(" ") + dgItr->message + F(wxT(" %d, %d"), dgItr->range.first, dgItr->range.second));
        if (dgItr->file != filename)
            continue;
        if (diagLv == dlFull)
        {
            if( (!update) || ((int)dgItr->line == (int)event.GetLocation().line) )
            {
                wxString str = stc->AnnotationGetText(dgItr->line - 1);
                if (!str.IsEmpty())
                    str += wxT('\n');
                stc->AnnotationSetText(dgItr->line - 1, str + dgItr->message);
                stc->AnnotationSetStyle(dgItr->line - 1, 50);
            }
        }
        int pos = stc->PositionFromLine(dgItr->line - 1) + dgItr->range.first - 1;
        int range = dgItr->range.second - dgItr->range.first;
        if (range == 0)
        {
            range = stc->WordEndPosition(pos, true) - pos;
            if (range == 0)
            {
                pos = stc->WordStartPosition(pos, true);
                range = stc->WordEndPosition(pos, true) - pos;
            }
        }
        if (dgItr->severity == sError)
            stc->SetIndicatorCurrent(errorIndicator);
        else if (  dgItr != diagnostics.begin()
                && dgItr->line == (dgItr - 1)->line
                && dgItr->range.first <= (dgItr - 1)->range.second )
        {
            continue; // do not overwrite the last indicator
        }
        else
            stc->SetIndicatorCurrent(warningIndicator);
        stc->IndicatorFillRange(pos, range);
    }
    if ( diagLv == dlFull )
    {
        stc->AnnotationSetVisible(wxSCI_ANNOTATION_BOXED);
        stc->ScrollToLine(firstVisibleLine);
    }
}
Ejemplo n.º 4
0
std::vector<cbCodeCompletionPlugin::CCToken> ClangCodeCompletion::GetAutocompList(bool isAuto, cbEditor* ed, int& tknStart, int& tknEnd)
{
#ifdef CLANGPLUGIN_TRACE_FUNCTIONS
    fprintf(stdout,"%s isAuto=%d\n", __PRETTY_FUNCTION__,(int)isAuto);
#endif
    std::vector<cbCodeCompletionPlugin::CCToken> tokens;

    int CCOutstanding = m_CCOutstanding;
    if ((CCOutstanding > 0)&&(m_CCOutstandingPos != ed->GetControl()->GetCurrentPos()))
    {
        CCOutstanding = 0;
    }

    m_CCOutstanding = 0;
    ClTranslUnitId translUnitId = m_TranslUnitId;
    if( translUnitId != GetCurrentTranslationUnitId() )
        return tokens;
    if (translUnitId == wxNOT_FOUND)
    {
        Manager::Get()->GetLogManager()->LogWarning(wxT("ClangLib: m_TranslUnitId == wxNOT_FOUND, "
                "cannot complete in file ") + ed->GetFilename());
        return tokens;
    }

    cbStyledTextCtrl* stc = ed->GetControl();
    const int style = stc->GetStyleAt(tknEnd);
    const wxChar curChar = stc->GetCharAt(tknEnd - 1);
    if (isAuto) // filter illogical cases of auto-launch
    {
        if ((curChar == wxT(':') // scope operator
                && stc->GetCharAt(tknEnd - 2) != wxT(':') )
                || ( curChar == wxT('>') // '->'
                        && stc->GetCharAt(tknEnd - 2) != wxT('-') )
                || ( wxString(wxT("<\"/")).Find(curChar) != wxNOT_FOUND // #include directive (TODO: enumerate completable include files)
                        && !stc->IsPreprocessor(style)))
        {
            return tokens;
        }
    }

    const int line = stc->LineFromPosition(tknStart);
/*
    std::map<wxString, wxString> unsavedFiles;
    EditorManager* edMgr = Manager::Get()->GetEditorManager();
    for (int i = 0; i < edMgr->GetEditorsCount(); ++i)
    {
        cbEditor* editor = edMgr->GetBuiltinEditor(i);
        if (editor && editor->GetModified())
            unsavedFiles.insert(std::make_pair(editor->GetFilename(), editor->GetControl()->GetText()));
    }
*/
    const int lnStart = stc->PositionFromLine(line);
    int column = tknStart - lnStart;
    for (; column > 0; --column)
    {
        if (!wxIsspace(stc->GetCharAt(lnStart + column - 1))
                || (column != 1 && !wxIsspace(stc->GetCharAt(lnStart + column - 2))))
        {
            break;
        }
    }

    const wxString& prefix = stc->GetTextRange(tknStart, tknEnd).Lower();
    bool includeCtors = true; // sometimes we get a lot of these
    for (int i = tknStart - 1; i > 0; --i)
    {
        wxChar chr = stc->GetCharAt(i);
        if (!wxIsspace(chr))
        {
            if (chr == wxT(';') || chr == wxT('}')) // last non-whitespace character
                includeCtors = false; // filter out ctors (they are unlikely to be wanted in this situation)
            break;
        }
    }

    std::vector<ClToken> tknResults;
    if ((CCOutstanding == 0)||(m_CCOutstandingResults.size()==0))
    {
        ClTokenPosition loc(line+1, column+1);
        //ClangProxy::CodeCompleteAtJob job( cbEVT_CLANG_SYNCTASK_FINISHED, idClangCodeCompleteTask, isAuto, ed->GetFilename(), loc, m_TranslUnitId, unsavedFiles);
        //m_Proxy.AppendPendingJob(job);
        unsigned long timeout = 40;
        if( !isAuto )
        {
            timeout = 500;
        }
        if( wxCOND_TIMEOUT == m_pClangPlugin->GetCodeCompletionAt(translUnitId, ed->GetFilename(), loc, timeout, tknResults))
        {
            if (wxGetLocalTime() - m_CCOutstandingLastMessageTime > 10)
            {
                //InfoWindow::Display(_("Code completion"), _("Busy parsing the document"), 1000);
                m_CCOutstandingLastMessageTime = wxGetLocalTime();
            }
            //std::cout<<"Timeout waiting for code completion"<<std::endl;
            m_CCOutstanding++;
            m_CCOutstandingPos = ed->GetControl()->GetCurrentPos();
            m_CCOutstandingResults.clear();
            return tokens;
        }
    }
    else
    {
        tknResults = m_CCOutstandingResults;
    }

    //m_Proxy.CodeCompleteAt(isAuto, ed->GetFilename(), line + 1, column + 1,
    //        m_TranslUnitId, unsavedFiles, tknResults);
    if (prefix.Length() > 3) // larger context, match the prefix at any point in the token
    {
        for (std::vector<ClToken>::const_iterator tknIt = tknResults.begin();
                tknIt != tknResults.end(); ++tknIt)
        {
            if (tknIt->name.Lower().Find(prefix) != wxNOT_FOUND && (includeCtors || tknIt->category != tcCtorPublic))
                tokens.push_back(cbCodeCompletionPlugin::CCToken(tknIt->id, tknIt->name, tknIt->name, tknIt->weight, tknIt->category));
        }
    }
    else if (prefix.IsEmpty())
    {
        for (std::vector<ClToken>::const_iterator tknIt = tknResults.begin();
                tknIt != tknResults.end(); ++tknIt)
        {
            // it is rather unlikely for an operator to be the desired completion
            if (!tknIt->name.StartsWith(wxT("operator")) && (includeCtors || tknIt->category != tcCtorPublic))
                tokens.push_back(cbCodeCompletionPlugin::CCToken(tknIt->id, tknIt->name, tknIt->name, tknIt->weight, tknIt->category));
        }
    }
    else // smaller context, only allow matches of the prefix at the beginning of the token
    {
        for (std::vector<ClToken>::const_iterator tknIt = tknResults.begin();
                tknIt != tknResults.end(); ++tknIt)
        {
            if (tknIt->name.Lower().StartsWith(prefix) && (includeCtors || tknIt->category != tcCtorPublic))
                tokens.push_back(cbCodeCompletionPlugin::CCToken(tknIt->id, tknIt->name, tknIt->name, tknIt->weight, tknIt->category));
        }
    }

    if (!tokens.empty())
    {
        if (prefix.IsEmpty() && tokens.size() > 1500) // reduce to give only top matches
        {
            std::partial_sort(tokens.begin(), tokens.begin() + 1000, tokens.end(), PrioritySorter());
            tokens.erase(tokens.begin() + 1000, tokens.end());
        }
        const int imgCount = m_pClangPlugin->GetImageList(translUnitId).GetImageCount();
        for (int i = 0; i < imgCount; ++i)
            stc->RegisterImage(i, m_pClangPlugin->GetImageList(translUnitId).GetBitmap(i));
        bool isPP = stc->GetLine(line).Strip(wxString::leading).StartsWith(wxT("#"));
        std::set<int> usedWeights;
        for (std::vector<cbCodeCompletionPlugin::CCToken>::iterator tknIt = tokens.begin();
                tknIt != tokens.end(); ++tknIt)
        {
            wxStringVec keywords = m_pClangPlugin->GetKeywords(translUnitId);
            usedWeights.insert(tknIt->weight);
            switch (tknIt->category)
            {
            case tcNone:
                if (isPP)
                    tknIt->category = tcMacroDef;
                else if (std::binary_search(keywords.begin(), keywords.end(), GetActualName(tknIt->name)))
                    tknIt->category = tcLangKeyword;
                break;

            case tcClass:
            case tcCtorPublic:
            case tcDtorPublic:
            case tcFuncPublic:
            case tcVarPublic:
            case tcEnum:
            case tcTypedef:
                // TODO
                //m_Proxy.RefineTokenType(m_TranslUnitId, tknIt->id, tknIt->category);
                break;

            default:
                break;
            }
        }
        // Clang sometimes gives many weight values, which can make completion more difficult
        // because results are less alphabetical. Use a compression map on the lower priority
        // values (higher numbers) to reduce the total number of weights used.
        if (usedWeights.size() > 3)
        {
            std::vector<int> weightsVec(usedWeights.begin(), usedWeights.end());
            std::map<int, int> weightCompr;
            weightCompr[weightsVec[0]] = weightsVec[0];
            weightCompr[weightsVec[1]] = weightsVec[1];
            int factor = (weightsVec.size() > 7 ? 3 : 2);
            for (size_t i = 2; i < weightsVec.size(); ++i)
                weightCompr[weightsVec[i]] = weightsVec[(i - 2) / factor + 2];
            for (std::vector<cbCodeCompletionPlugin::CCToken>::iterator tknIt = tokens.begin();
                    tknIt != tokens.end(); ++tknIt)
            {
                tknIt->weight = weightCompr[tknIt->weight];
            }
        }
    }

    std::cout<<"CodeCompletion finished"<<std::endl;
    return tokens;
}
Ejemplo n.º 5
0
void ClangDiagnostics::OnDiagnosticsUpdated(ClangEvent& event)
{
    event.Skip();
    if (!IsAttached())
        return;

    ClDiagnosticLevel diagLv = dlFull; // TODO
    bool update = false;
    EditorManager* edMgr = Manager::Get()->GetEditorManager();
    cbEditor* ed = edMgr->GetBuiltinActiveEditor();
    if (!ed)
        return;

    if (event.GetTranslationUnitId() != GetCurrentTranslationUnitId())
    {
        CCLogger::Get()->DebugLog( wxT("OnDiagnostics: tu ID mismatch") );
        // Switched translation unit before event delivered
        return;
    }

    const std::vector<ClDiagnostic>& diagnostics = event.GetDiagnosticResults();
    if ( (diagLv == dlFull)&&(event.GetLocation().line != 0) && (event.GetLocation().column != 0) )
    {
        CCLogger::Get()->DebugLog( wxT("OnDiagnostics: Doing partial update") );
        update = true;
    }
    else
    {
        CCLogger::Get()->DebugLog( wxT("OnDiagnostics: Doing full update") );
        m_Diagnostics = diagnostics;
    }

    cbStyledTextCtrl* stc = ed->GetControl();

    int firstVisibleLine = stc->GetFirstVisibleLine();

    const int warningIndicator = 0; // predefined
    const int errorIndicator = 15; // hopefully we do not clash with someone else...
    stc->SetIndicatorCurrent(warningIndicator);
    if (!update)
        stc->IndicatorClearRange(0, stc->GetLength());
    stc->IndicatorSetStyle(errorIndicator, wxSCI_INDIC_SQUIGGLE);
    stc->IndicatorSetForeground(errorIndicator, *wxRED);
    stc->SetIndicatorCurrent(errorIndicator);
    if (!update)
        stc->IndicatorClearRange(0, stc->GetLength());

    const wxString& filename = ed->GetFilename();
    if (!m_bShowInline)
        stc->AnnotationClearAll();
    else if ((diagLv == dlFull) && update)
    {
        int line = event.GetLocation().line-1;
        stc->AnnotationClearLine(line);
    }
    else
        stc->AnnotationClearAll();

    int lastLine = 0;
    for (std::vector<ClDiagnostic>::const_iterator dgItr = diagnostics.begin();
         dgItr != diagnostics.end(); ++dgItr)
    {
        Manager::Get()->GetLogManager()->Log(dgItr->file + wxT(" ") + dgItr->message + F(wxT(" %d, %d"), dgItr->range.first, dgItr->range.second));
        if (dgItr->file != filename)
        {
            CCLogger::Get()->Log(wxT("WARNING: Filename mismatch in diagnostics !!"));
            continue;
        }
        if (update)
        {
            m_Diagnostics.push_back( *dgItr );
        }
        if (diagLv == dlFull)
        {
            if (update && (lastLine != (dgItr->line - 1)))
            {
                stc->AnnotationClearLine(dgItr->line - 1);
            }
            if (m_bShowInline)
            {
                wxString str = stc->AnnotationGetText(dgItr->line - 1);
                if (!str.IsEmpty())
                    str += wxT('\n');
                if (!str.Contains(dgItr->message))
                {
                    switch (dgItr->severity)
                    {
                    case sWarning:
                        if (m_bShowWarning)
                        {
                            stc->AnnotationSetText(dgItr->line - 1, str + dgItr->message);
                            stc->AnnotationSetStyle(dgItr->line - 1, 51);
                        }
                        break;
                    case sError:
                        if (m_bShowError)
                        {
                            stc->AnnotationSetText(dgItr->line - 1, str + dgItr->message);
                            stc->AnnotationSetStyle(dgItr->line - 1, 52);
                        }
                        break;
                    case sNote:
                        break;
                    }
                }
            }
        }
        int pos = stc->PositionFromLine(dgItr->line - 1) + dgItr->range.first - 1;
        int range = dgItr->range.second - dgItr->range.first;
        if (range == 0)
        {
            range = stc->WordEndPosition(pos, true) - pos;
            if (range == 0)
            {
                pos = stc->WordStartPosition(pos, true);
                range = stc->WordEndPosition(pos, true) - pos;
            }
        }
        if (dgItr->severity == sError)
            stc->SetIndicatorCurrent(errorIndicator);
        else if (   dgItr != diagnostics.begin()
                 && dgItr->line == (dgItr - 1)->line
                 && dgItr->range.first <= (dgItr - 1)->range.second )
        {
            continue; // do not overwrite the last indicator
        }
        else
            stc->SetIndicatorCurrent(warningIndicator);
        stc->IndicatorFillRange(pos, range);
        lastLine = dgItr->line - 1;
    }
    if (diagLv == dlFull)
    {
        stc->AnnotationSetVisible(wxSCI_ANNOTATION_BOXED);
        stc->ScrollLines(firstVisibleLine - stc->GetFirstVisibleLine());
    }
}