Developer forums (C::B DEVELOPMENT STRICTLY!) > CodeCompletion redesign

New code completion remarks/issues

<< < (44/54) > >>

blueshake:

--- Quote from: oBFusCATed on November 02, 2009, 10:24:46 am ---Hm, Olly having both in the tooltip can be quite helpful.
If for example the tooltip looks like this:

global int variableA
local int variableA

or
int ::variableA
int variableA
int my_namespace::variableA


--- End quote ---


Patch for doing this.

--- Code: ---Index: src/plugins/codecompletion/parser/token.cpp
===================================================================
--- src/plugins/codecompletion/parser/token.cpp (revision 5894)
+++ src/plugins/codecompletion/parser/token.cpp (working copy)
@@ -136,6 +136,10 @@
 wxString Token::DisplayName() const
 {
     wxString result;
+    if (m_IsTemp)
+        result << _T("local ");
+    else
+        result << _T("global ");
     if      (m_TokenKind == tkClass)
         return result << _T("class ")     << m_Name << _T(" {...}");
     else if (m_TokenKind == tkNamespace)

--- End code ---
see the screen shot.

jaxon:
Sorry, but it seems for me, that we need only variable used by compiler in current context to be shown in the tooltip. And yes, as ollydbg said, it should be faster.

ollydbg:
Hi, all, I personally agree with jaxon.

I have debug the code whole day :(, and finally find that this is a bug in the code below:


--- Code: ---bool NativeParser::ParseLocalBlock(cbEditor* ed, int caretPos)
{
    if (!ed)
        return false;

    Parser* parser = FindParserFromEditor(ed);
    if (!parser)
        return false;

    if (!parser->Done())
        return false;

    if (s_DebugSmartSense)
        Manager::Get()->GetLogManager()->DebugLog(_T("Parse local block"));

    int blockStart = FindCurrentFunctionStart(ed, 0, 0, caretPos);
    if (blockStart != -1)
    {
        ++blockStart; // skip {
        int blockEnd = caretPos == -1 ? ed->GetControl()->GetCurrentPos() : caretPos;
        if (blockEnd < 0 || blockEnd > ed->GetControl()->GetLength())
            return false;

        if (blockStart >= blockEnd)
            blockStart = blockEnd;

        wxString buffer = ed->GetControl()->GetTextRange(blockStart, blockEnd);
        buffer.Trim();
        if (!buffer.IsEmpty() && !parser->ParseBuffer(buffer, false, false, true))
        {
            if (s_DebugSmartSense)
                Manager::Get()->GetLogManager()->DebugLog(_T("ERROR parsing block:\n") + buffer);
        }
        else
        {
            if (s_DebugSmartSense)
            {
                #if wxCHECK_VERSION(2, 9, 0)
                Manager::Get()->GetLogManager()->DebugLog(F(_T("Block:\n%s"), buffer.wx_str()));
                #else
                Manager::Get()->GetLogManager()->DebugLog(F(_T("Block:\n%s"), buffer.c_str()));
                #endif
                Manager::Get()->GetLogManager()->DebugLog(_T("Local tokens:"));
                for (size_t i = 0; i < parser->GetTokens()->size(); ++i)
                {
                    Token* t = parser->GetTokens()->at(i);
                    if (t && t->m_IsTemp)
                        Manager::Get()->GetLogManager()->DebugLog(_T(" + ") + t->DisplayName());
                }
            }
            return true;
        }
    }
    else
    {
        if (s_DebugSmartSense)
            Manager::Get()->GetLogManager()->DebugLog(_T("Could not determine current block start..."));
    }
    return false;
}

--- End code ---

for example, at this time( see my example code), the LocalBlock is the function body of main to the current caret:


--- Code: ---int variableA;
    variableA = 1;

--- End code ---

After parsing the buffer, the parser mistakenly added the local variableA to the global namespace.. I think the correct way should be :
set the the local variableA's parent as Token "main" (not the global namespace).

Also, there is another issue in these code:

nativeparser.cpp line 1597:


--- Code: ---    // always add scope -1 (i.e. global namespace)
    search_scope->insert(-1);

    // find all other matches
    std::queue<ParserComponent> components;
    BreakUpComponents(parser, actual, components);

    m_LastAISearchWasGlobal = components.size() <= 1;
    if (!components.empty())
        m_LastAIGlobalSearch = components.front().component;

    // actually find all matches in selected namespaces
    for (TokenIdxSet::iterator it = search_scope->begin(); it != search_scope->end(); ++it)
    {
        if (s_DebugSmartSense)
        {
            Token* scopeToken = tree->at(*it);
            #if wxCHECK_VERSION(2, 9, 0)
            Manager::Get()->GetLogManager()->DebugLog(F(_T("Parent scope: '%s' (%d)"), scopeToken ? scopeToken->m_Name.wx_str() : _T("Global namespace"), *it));
            #else
            Manager::Get()->GetLogManager()->DebugLog(F(_T("Parent scope: '%s' (%d)"), scopeToken ? scopeToken->m_Name.c_str() : _T("Global namespace"), *it));
            #endif
        }
        FindAIMatches(parser, components, result, *it, noPartialMatch, caseSensitive, true, 0xffff, search_scope);
    }

    cached_editor = editor;
    if (result.size() || (m_EditorEndWord - m_EditorStartWord))
        cached_editor_start_word = m_EditorStartWord;
    cached_search = actual;
    cached_results_count = result.size();

    return result.size();
}

--- End code ---


In the code above, the "global namespace" is added by default. I don't think is is necessary, I personally use this method

1, check the result.size() at the end of AI()
2, if the result.size is zero, we should add the global namespace, and do the FindAIMatches() in the global namespace.

In this way, if the token is already found in the local context or matches as a class members, we don't need to use global namespace search.

By the way, the AI() function( and the related functions to do the show the tips) code is really hard to read!!!, that's irradiated me so much!!! :(, I think we should refactor it, especially change the variable names.

MortenMacFly:

--- Quote from: oBFusCATed on November 02, 2009, 10:24:46 am ---Hm, Olly having both in the tooltip can be quite helpful.

--- End quote ---
Definitely. Look: Naming a local variable like a global one is bad style. Surely you might forget this sometimes but if the tooltip reminds you accordingly this is just helpful. So please don't strip this (really useful) information. Not even for the sake of speed.
I agree (however) with displayinf this with a "global/local" prefix.

ollydbg:
Hi, all, here, I announce this patch of the code completion plugin.

Some time, when you are debugging, both the GDB value tips and CC's tips window will pop up, and overlayed. That's very annoying. The currently method try to close the tip window, when the new tip will be shown, the GDB's tip always shown later, so, GDB's tip always force the CC's tip to close, and win the battle. :D


Edit1
Sorry, When adding the patch, my computer hangs. So, here is the patch:


--- Code: ---Index: codecompletion.cpp
===================================================================
--- codecompletion.cpp (revision 5908)
+++ codecompletion.cpp (working copy)
@@ -112,25 +112,26 @@
 // just because we don't know other plugins' used identifiers,
 // we use wxNewId() to generate a guaranteed unique ID ;), instead of enum
 // (don't forget that, especially in a plugin)
-int idMenuCodeComplete = wxNewId();
-int idMenuShowCallTip = wxNewId();
-int idMenuGotoFunction = wxNewId();
-int idMenuGotoPrevFunction = wxNewId();
-int idMenuGotoNextFunction = wxNewId();
-int idMenuGotoDeclaration = wxNewId();
-int idMenuGotoImplementation = wxNewId();
-int idMenuOpenIncludeFile = wxNewId();
-int idViewClassBrowser = wxNewId();
-int idEditorSubMenu = wxNewId();
-int idClassMethod = wxNewId();
+int idMenuCodeComplete          = wxNewId();
+int idMenuShowCallTip           = wxNewId();
+int idMenuGotoFunction          = wxNewId();
+int idMenuGotoPrevFunction      = wxNewId();
+int idMenuGotoNextFunction      = wxNewId();
+int idMenuGotoDeclaration       = wxNewId();
+int idMenuGotoImplementation    = wxNewId();
+int idMenuOpenIncludeFile       = wxNewId();
+int idViewClassBrowser          = wxNewId();
+int idEditorSubMenu             = wxNewId();
+int idClassMethod               = wxNewId();
 int idUnimplementedClassMethods = wxNewId();
-int idGotoDeclaration = wxNewId();
-int idGotoImplementation = wxNewId();
-int idOpenIncludeFile = wxNewId();
-int idStartParsingProjects = wxNewId();
-int idCodeCompleteTimer = wxNewId();
-int idFunctionsParsingTimer = wxNewId();
+int idGotoDeclaration           = wxNewId();
+int idGotoImplementation        = wxNewId();
+int idOpenIncludeFile           = wxNewId();
+int idStartParsingProjects      = wxNewId();
+int idCodeCompleteTimer         = wxNewId();
+int idFunctionsParsingTimer     = wxNewId();
 
+
 // milliseconds
 #define EDITOR_AND_LINE_INTERVAL 150
 
@@ -193,8 +194,14 @@
 
     if (!cfg->Exists(_T("token_replacements")))
     {
-        // first run; add default replacements
+        // first run; add default replacements string
         Tokenizer::SetReplacementString(_T("_GLIBCXX_STD"), _T("std"));
+        Tokenizer::SetReplacementString(_T("_GLIBCXX_BEGIN_NESTED_NAMESPACE"), _T("+namespace"));
+        Tokenizer::SetReplacementString(_T("_GLIBCXX_END_NESTED_NAMESPACE"), _T("}"));
+        Tokenizer::SetReplacementString(_T("_GLIBCXX_BEGIN_NAMESPACE"), _T("+namespace"));
+        Tokenizer::SetReplacementString(_T("_GLIBCXX_END_NAMESPACE_TR1"), _T("}"));
+        Tokenizer::SetReplacementString(_T("_GLIBCXX_BEGIN_NAMESPACE_TR1"), _T("-namespace tr1 {"));
+
     }
     else
         cfg->Read(_T("token_replacements"), &repl);
@@ -522,9 +529,10 @@
     if (!IsAttached() || !m_InitDone)
         return -1;
 
-    ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("code_completion"));
+    ConfigManager* cfg   = Manager::Get()->GetConfigManager(_T("code_completion"));
     EditorManager* edMan = Manager::Get()->GetEditorManager();
-    cbEditor* ed = edMan->GetBuiltinActiveEditor();
+    cbEditor* ed         = edMan->GetBuiltinActiveEditor();
+
     if (!ed)
         return -3;
 
@@ -554,7 +562,8 @@
             ed->GetControl()->ClearRegisteredImages();
 
             bool caseSens = parser ? parser->Options().caseSensitive : false;
-            wxArrayString items; items.Alloc(result.size());
+            wxArrayString items;
+            items.Alloc(result.size());
             int pos   = ed->GetControl()->GetCurrentPos();
             int start = ed->GetControl()->WordStartPosition(pos, true);
             wxArrayInt already_registered;
@@ -748,6 +757,8 @@
     return dirs;
 }
 
+// Do the code completion when we enter:
+// #include "| or #include <|
 void CodeCompletion::CodeCompleteIncludes()
 {
     if (!IsAttached() || !m_InitDone)
@@ -758,20 +769,22 @@
         return;
 
     EditorManager* edMan = Manager::Get()->GetEditorManager();
-    cbEditor* ed = edMan->GetBuiltinActiveEditor();
+    cbEditor* ed         = edMan->GetBuiltinActiveEditor();
+
     if (!ed)
         return;
 
-    Parser* parser = m_NativeParser.FindParserFromActiveEditor();
+    Parser* parser      = m_NativeParser.FindParserFromActiveEditor();
     const bool caseSens = parser ? parser->Options().caseSensitive : false;
 
     FileType ft = FileTypeOf(ed->GetShortName());
     if ( ft != ftHeader && ft != ftSource) // only parse source/header files
         return;
 
-    int pos = ed->GetControl()->GetCurrentPos();
+    int pos          = ed->GetControl()->GetCurrentPos();
     int lineStartPos = ed->GetControl()->PositionFromLine(ed->GetControl()->GetCurrentLine());
-    wxString line = ed->GetControl()->GetLine(ed->GetControl()->GetCurrentLine());
+    wxString line    = ed->GetControl()->GetLine(ed->GetControl()->GetCurrentLine());
+
     //Manager::Get()->GetLogManager()->DebugLog("#include cc for \"%s\"", line.c_str());
     line.Trim();
     if (line.IsEmpty() || !TestIncludeLine(line))
@@ -784,6 +797,7 @@
         return;
     ++quote_pos;
 
+    // now, we are after the quote prompt
     wxString filename = line.substr(quote_pos, pos - lineStartPos - quote_pos);
     filename.Replace(_T("\\"), _T("/"), true);
 
@@ -823,6 +837,7 @@
         }
     }
 
+    // popup the auto completion window
     if (files.GetCount() != 0)
     {
         files.Sort();
@@ -872,11 +887,12 @@
         // else, out of range
     }
 
-    int start = 0;
-    int end = 0;
-    int count = 0;
-    int commas = m_NativeParser.GetCallTipCommas(); // how many commas has the user typed so far?
+    int start           = 0;
+    int end             = 0;
+    int count           = 0;
+    int commas          = m_NativeParser.GetCallTipCommas(); // how many commas has the user typed so far?
     wxArrayString items = m_NativeParser.GetCallTips(maxCalltipLineSizeInChars);
+
     std::set< wxString, std::less<wxString> > unique_tips; // check against this before inserting a new tip in the list
     wxString definition;
     for (unsigned int i = 0; i < items.GetCount(); ++i)
@@ -923,8 +939,11 @@
     }
 
     wxString filename = ed->GetFilename();
+
+    // open the insert class dialog
     InsertClassMethodDlg dlg(Manager::Get()->GetAppWindow(), parser, filename);
     PlaceWindow(&dlg);
+
     if (dlg.ShowModal() == wxID_OK)
     {
         int pos = ed->GetControl()->GetCurrentPos();
@@ -1565,6 +1584,30 @@
         if (!Manager::Get()->GetConfigManager(_T("code_completion"))->ReadBool(_T("eval_tooltip"), true))
             return;
 
+
+        // Check the debugger is running...at this time, don't show cc tips
+        bool debuggerRunning = false;
+        PluginsArray arr = Manager::Get()->GetPluginManager()->GetOffersFor(ptDebugger);
+        if (arr.GetCount())
+        {
+            for(size_t i=0;i<arr.GetCount();i++)
+            {
+                cbDebuggerPlugin* debugger = (cbDebuggerPlugin*)arr[i];
+                if (!debugger)
+                    continue; //kinda scary if this isn't a debugger? perhaps this should be a logged error??
+                if (debugger->IsRunning())
+                {
+                    debuggerRunning=true;
+                    break;
+                }
+            }
+        }
+        if(debuggerRunning)
+        {
+            Manager::Get()->GetLogManager()->DebugLog(F(_T("debugger is running, skip.CC tips..")));
+            return;
+        }
+
         EditorBase* base = event.GetEditor();
         cbEditor* ed = base && base->IsBuiltinEditor() ? static_cast<cbEditor*>(base) : 0;
         if (!ed || ed->IsContextMenuOpened())


--- End code ---

I just check if any debugger plugin was running, then, CC's tip should not been shown.

Edit2

I just use the aligner plugin to format some code.


Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version