News:

Accounts with zero posts and zero activity during the last months will be deleted periodically to fight SPAM!

Main Menu

New code completion remarks/issues

Started by killerbot, September 15, 2009, 12:24:28 PM

Previous topic - Next topic

ollydbg

#45
Quote from: blueshake on September 25, 2009, 07:43:57 AM
@ollydbg
I comment wxArrayString GetIncludeDirs(cbProject &project)
and void CodeCompletion::CodeCompleteIncludes() function implementation.Then the cc works in the latest cc.
And I test the codes in codecompletion.cpp without any comment in svn 5731.Everything work perfectly.


I have noticed that there's no difference in the parserthread::SkipBlock() function in the neally two month.

but I found some code changes in the tokenizer.cpp in function SkipToChar from rev 5434->5783.


bool Tokenizer::SkipToChar(const wxChar& ch)
{
   // skip everything until we find ch
   while(true)
   {
       while (CurrentChar() != ch && MoveToNextChar())  // don't check EOF when MoveToNextChar already does
           ;

       if (IsEOF())
           return false;

       if (PreviousChar() != '\\')
           break;
       else
       {
           // check for "\\"
           if (((m_TokenIndex - 2) >= 0) && ((m_TokenIndex - 2) >= m_BufferLen) && (m_Buffer.GetChar(m_TokenIndex - 2) == '\\'))
               break;
       }
       MoveToNextChar();
   }
   return true;
}


Why we need to check this :


           // check for "\\"
           if (((m_TokenIndex - 2) >= 0) && ((m_TokenIndex - 2) >= m_BufferLen) && (m_Buffer.GetChar(m_TokenIndex - 2) == '\\'))



((m_TokenIndex - 2) >= m_BufferLen  ?????


I think it should be:

(m_TokenIndex - 2)<= m_BufferLen
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

ollydbg

Ok, fixed by this patch:


Index: tokenizer.cpp
===================================================================
--- tokenizer.cpp (revision 5818)
+++ tokenizer.cpp (working copy)
@@ -230,7 +230,7 @@
         else
         {
             // check for "\\"
-            if (((m_TokenIndex - 2) >= 0) && ((m_TokenIndex - 2) >= m_BufferLen) && (m_Buffer.GetChar(m_TokenIndex - 2) == '\\'))
+            if (((m_TokenIndex - 2) >= 0) && ((m_TokenIndex - 2) <= m_BufferLen) && (m_Buffer.GetChar(m_TokenIndex - 2) == '\\'))
                 break;
         }
         MoveToNextChar();
@@ -286,7 +286,7 @@
         else
         {
             // check for "\\"
-            if (((m_TokenIndex - 2) >= 0) && ((m_TokenIndex - 2) >= m_BufferLen) && (m_Buffer.GetChar(m_TokenIndex - 2) == '\\'))
+            if (((m_TokenIndex - 2) >= 0) && ((m_TokenIndex - 2) <= m_BufferLen) && (m_Buffer.GetChar(m_TokenIndex - 2) == '\\'))
                 break;
         }
         MoveToNextChar();
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

MortenMacFly

Quote from: ollydbg on September 25, 2009, 08:19:23 AM
I think it should be:
(m_TokenIndex - 2)<= m_BufferLen
Definitely. I'll certainly apply this in trunk when tested. But it really looks very ugly to me, too.
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: [url="https://www.codeblocks.org/docs/main_codeblocks_en.html"]https://www.codeblocks.org/docs/main_codeblocks_en.html[/url]
C::B FAQ: [url="https://wiki.codeblocks.org/index.php?title=FAQ"]https://wiki.codeblocks.org/index.php?title=FAQ[/url]

blueshake

Keep low and hear the sadness of little dog.
I fall in love with a girl,but I don't dare to tell her.What should I do?

mmkider

New Code Completion plug-in is more powerful.

:D

MortenMacFly

Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: [url="https://www.codeblocks.org/docs/main_codeblocks_en.html"]https://www.codeblocks.org/docs/main_codeblocks_en.html[/url]
C::B FAQ: [url="https://wiki.codeblocks.org/index.php?title=FAQ"]https://wiki.codeblocks.org/index.php?title=FAQ[/url]

ollydbg

#51
Quote from: MortenMacFly on September 25, 2009, 09:08:02 PM
Added pointer to here:
http://forums.next.codeblocks.org/index.php/topic,11240.0.html
(To keep all issues in one place.)

After several email discuss with blueshake, we finally give a patch to solve this problem:

here is the patch:


Index: nativeparser.cpp
===================================================================
--- nativeparser.cpp (revision 5819)
+++ nativeparser.cpp (working copy)
@@ -1412,6 +1420,8 @@
    static wxString cached_search;
    static size_t cached_results_count = 0;

+
+
    // early-out opportunity
    // if the user starts typing a token that in our last search had 0 results,
    // and we see that he's continuing typing for that same token,
@@ -1419,7 +1429,8 @@
    if (cached_editor == editor &&
        cached_editor_start_word == m_EditorStartWord &&
        cached_results_count == 0 &&
-        actual.StartsWith(cached_search))
+        actual.StartsWith(cached_search)&&
+        actual.Find(_T('(')) == wxNOT_FOUND)
    {
#ifdef DEBUG_CC_AI
        if (s_DebugSmartSense)



Here is the explanation of this patch.

for example, you code is like below:


int aaaa;
void f(int result){
if             <---------enter here

}



If we firstly enter
if
then
if(

the AI function may only give 0 result, also, the result was cached as static variables.

if we continue entering like
if(resu, AI just see that this is already parsed string, and early quite from the function:
NativeParser::AI()

Here is the sample code of such early exit in NativeParser::AI:


static cbEditor* cached_editor = 0;
   static int cached_editor_start_word = 0;
   static wxString cached_search;
   static size_t cached_results_count = 0;



   // early-out opportunity
   // if the user starts typing a token that in our last search had 0 results,
   // and we see that he's continuing typing for that same token,
   // don't even bother to search
   if (cached_editor == editor &&
       cached_editor_start_word == m_EditorStartWord &&
       cached_results_count == 0 &&
       actual.StartsWith(cached_search)&&
       actual.Find(_T('(')) == wxNOT_FOUND) **************************add code here!!!
   {
#ifdef DEBUG_CC_AI
       if (s_DebugSmartSense)
           Manager::Get()->GetLogManager()->DebugLog(_T("Aborting search: last attempt returned 0 results"));
#endif
       // but set m_LastAISearchWasGlobal correctly so C++ keywords can be shown
       std::queue<ParserComponent> components;
       BreakUpComponents(parser, actual, components);
       m_LastAISearchWasGlobal = components.size() <= 1;
       if (!components.empty())
           m_LastAIGlobalSearch = components.front().component;
       return 0;
   }


In fact, at this time( AI entered second time), all the if condition was true.


cached_results_count = 0
cached_search = "if"
actual             = "if(resu"
.....


So, we should add checking actual.Find(_T('(')) == wxNOT_FOUND to avoid the early exit from the function AI.


Thanks to blueshake! :D


If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

ollydbg

hi, there is another patch by blueshake, which is better than mine. :D
Index: src/plugins/codecompletion/nativeparser.cpp
===================================================================
--- src/plugins/codecompletion/nativeparser.cpp (revision 5821)
+++ src/plugins/codecompletion/nativeparser.cpp (working copy)
@@ -1522,6 +1522,7 @@
     }

     cached_editor = editor;
+    if (result.size() || (m_EditorEndWord - m_EditorStartWord))
     cached_editor_start_word = m_EditorStartWord;
     cached_search = actual;
     cached_results_count = result.size();
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

koso

Hello, using latest SVN build (and probably not only latest), I am having problem with code completion for variables declared using "struct" keyword. For example:


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
struct tm *current;
        current->
}


I dont get any suggestions when typing "current->" and also nothing when trying to complete "curr". It works as expected without keyword struct in declaration.
I tried to find symbol current using Code completion debug tool, but i get only empty list with information, that were found Multiple matches and i must choose :P

ollydbg

Add pointer to the this bug report:

http://forums.next.codeblocks.org/index.php/topic,11107.msg76268.html#msg76268

And this problem can be solved by my patch here:


Index: src/plugins/codecompletion/nativeparser.cpp
===================================================================
--- src/plugins/codecompletion/nativeparser.cpp (revision 5824)
+++ src/plugins/codecompletion/nativeparser.cpp (working copy)
@@ -427,71 +427,79 @@
     delete [] Compilers;
} // end of AddCompilerDirs

+
+
wxArrayString NativeParser::GetGCCCompilerDirs(const wxString &cpp_compiler, const wxString &base)
{
     wxArrayString gcc_compiler_dirs;

     // for starters , only do this for gnu compiler
-//    Manager::Get()->GetLogManager()->DebugLog(_T("CompilerID ") + CompilerID);
-    //    wxString Command("mingw32-g++ -v -E -x c++ - < nul");
-    // specifying "< nul", does not seem to work
-    // workaround : create a dummy file (let's hope it does not exist)
+    //Manager::Get()->GetLogManager()->DebugLog(_T("CompilerID ") + CompilerID);
+    //
+    //   windows: mingw32-g++ -v -E -x c++ nul
+    //   linux  : g++ -v -E -x c++ /dev/null
     // do the trick only for c++, not needed then for C (since this is a subset of C++)
-    wxString DummyFileName = wxFileName::CreateTempFileName(_T("Dummy_z4hsdkl9nf7ba3L9nv41"));
-    if(!DummyFileName.IsEmpty())
+
+
+    // let's construct the command
+    // use a null file handler
+    // both works fine in Windows and linux
+
+#ifdef __WXMSW__
+    wxString Command = cpp_compiler + _T(" -v -E -x c++ nul");
+#else
+    wxString Command = cpp_compiler + _T(" -v -E -x c++ /dev/null");
+#endif
+
+    // action time  (everything shows up on the error stream
+    wxArrayString Output, Errors;
+    wxExecute(Command, Output, Errors, wxEXEC_NODISABLE);
+    int nCount = Errors.GetCount();
+    // the include dir (1 per line) show up between the lines
+    // #include <...> search starts here:
+    // End of search list
+    //   let's hope this does not change too quickly, otherwise we need
+    // to adjust our search code (for several versions ...)
+    bool bStart = false;
+    for(int idxCount = 0; idxCount < nCount; ++idxCount)
     {
-        // let's construct the command
-        wxString Command = cpp_compiler + _T(" -v -E -x c++ ") + DummyFileName;
-        // action time  (everything shows up on the error stream
-        wxArrayString Output, Errors;
-        wxExecute(Command, Output, Errors, wxEXEC_NODISABLE);
-        int nCount = Errors.GetCount();
-        // the include dir (1 per line) show up between the lines
-        // #include <...> search starts here:
-        // End of search list
-        //   let's hope this does not change too quickly, otherwise we need
-        // to adjust our search code (for several versions ...)
-        bool bStart = false;
-        for(int idxCount = 0; idxCount < nCount; ++idxCount)
+        if (!bStart && Errors[idxCount] == _("#include <...> search starts here:"))
         {
-            if (!bStart && Errors[idxCount] == _("#include <...> search starts here:"))
+            bStart = true;
+        }
+        else if (bStart && Errors[idxCount] == _("End of search list."))
+        {
+            bStart = false; // could jump out of for loop if we want
+        }
+        else if (bStart)
+        {
+//                Manager::Get()->GetLogManager()->DebugLog("include dir " + Errors[idxCount]);
+            // get rid of the leading space (more general : any whitespace)in front
+            wxRegEx reg(_T("^[ \t]*(.*)"));
+            if(reg.Matches(Errors[idxCount]))
             {
-                bStart = true;
-            }
-            else if (bStart && Errors[idxCount] == _("End of search list."))
-            {
-                bStart = false; // could jump out of for loop if we want
-            }
-            else if (bStart)
-            {
-//                Manager::Get()->GetLogManager()->DebugLog("include dir " + Errors[idxCount]);
-                // get rid of the leading space (more general : any whitespace)in front
-                wxRegEx reg(_T("^[ \t]*(.*)"));
-                if(reg.Matches(Errors[idxCount]))
+                wxString out = reg.GetMatch(Errors[idxCount], 1);
+                if(!out.IsEmpty())
                 {
-                    wxString out = reg.GetMatch(Errors[idxCount], 1);
-                    if(!out.IsEmpty())
+                    wxFileName dir(out);
+                    if (NormalizePath(dir,base))
                     {
-                        wxFileName dir(out);
-                        if (NormalizePath(dir,base))
-                        {
-                            Manager::Get()->GetLogManager()->DebugLog(_T("Caching GCC dir: ") + dir.GetFullPath());
-                            gcc_compiler_dirs.Add(dir.GetFullPath());
-                        }
-                        else
-                        #if wxCHECK_VERSION(2, 9, 0)
-                            Manager::Get()->GetLogManager()->DebugLog(F(_T("Error normalizing path: '%s' from '%s'"),out.wx_str(),base.wx_str()));
-                        #else
-                            Manager::Get()->GetLogManager()->DebugLog(F(_T("Error normalizing path: '%s' from '%s'"),out.c_str(),base.c_str()));
-                        #endif
+                        Manager::Get()->GetLogManager()->DebugLog(_T("Caching GCC dir: ") + dir.GetFullPath());
+                        gcc_compiler_dirs.Add(dir.GetFullPath());
                     }
+                    else
+                    #if wxCHECK_VERSION(2, 9, 0)
+                        Manager::Get()->GetLogManager()->DebugLog(F(_T("Error normalizing path: '%s' from '%s'"),out.wx_str(),base.wx_str()));
+                    #else
+                        Manager::Get()->GetLogManager()->DebugLog(F(_T("Error normalizing path: '%s' from '%s'"),out.c_str(),base.c_str()));
+                    #endif
                 }
             }
-        } // end for : idx : idxCount
-        // clean up our temp file
-        ::wxRemoveFile(DummyFileName);
-    } // Dummy is open
+        }
+    } // end for : idx : idxCount

+
+
     return gcc_compiler_dirs;
}

@@ -1209,11 +1217,16 @@
                     #endif
                     {
                         case ']':
-                        case ')': ++nest; break;
+                        case ')': ++nest; --x;break;

                         case '[':
-                        case '(': --nest; break;
+                        case '(': --nest; --x;break;
+
                     }
+                    while ((x >= 0) && (line.GetChar(x) == ' ' || line.GetChar(x) == '\t'))
+                        --x;
+                    if ((x >= 0) && (line.GetChar(x) == ')' || line.GetChar(x) == ']'))
+                        ++nest;
                 }
                 if ((x > 0) && (wxIsalnum(line.GetChar(x - 1)) || line.GetChar(x - 1) == '_'))
                     --x;
@@ -1268,7 +1281,7 @@
         is_function = line.GetChar(startAt) == '(';

         ++nest;
-        while (startAt < line.Length() - 1 && nest != 0)
+        while (startAt < line.Length()-1 && nest != 0)
         {
             ++startAt;
             #if wxCHECK_VERSION(2, 9, 0)
@@ -1278,13 +1291,18 @@
             #endif
             {
                 case ']':
-                case ')': --nest; break;
+                case ')': --nest; ++startAt;break;

                 case '[':
-                case '(': ++nest; break;
+                case '(': ++nest; ++startAt;break;
             }
+            while (startAt < line.Length()-1&& (line.GetChar(startAt) == ' ' || line.GetChar(startAt) == '\t'))
+                        ++startAt;
+            if (startAt < line.Length()-1 && (line.GetChar(startAt) == '(' || line.GetChar(startAt) == '['))
+                        ++nest;
         }
-        ++startAt;
+        //++startAt;
+
     }

     //Manager::Get()->GetLogManager()->DebugLog("Return at %d (%c): res=%s", startAt, line.GetChar(startAt), res.c_str());
@@ -1412,6 +1430,8 @@
     static wxString cached_search;
     static size_t cached_results_count = 0;

+
+
     // early-out opportunity
     // if the user starts typing a token that in our last search had 0 results,
     // and we see that he's continuing typing for that same token,
@@ -1522,6 +1542,7 @@
     }

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



Note: this patch, the first part was using a null file to get the GCC include path(this avoid creating a dummy file)

here is the screen shot of codecompletion:



I'd like you test it and comments are welcome! thanks.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

ollydbg

#55
Quote from: koso on September 27, 2009, 09:18:14 PM
Hello, using latest SVN build (and probably not only latest), I am having problem with code completion for variables declared using "struct" keyword. For example:


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
struct tm *current;
       current->
}


I dont get any suggestions when typing "current->" and also nothing when trying to complete "curr". It works as expected without keyword struct in declaration.
I tried to find symbol current using Code completion debug tool, but i get only empty list with information, that were found Multiple matches and i must choose :P


I can confirm this bug.
The struct tm is correctly by the parser.

But this code works.


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
   struct tm current;
   current.
}



auto completion list can be shown after the dot.


Edit
Quote
I tried to find symbol current using Code completion debug tool, but i get only empty list with information,

This is because the variable "current" is not in the global token tree.
It is just in temporary token tree in the scope of "main".
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

ollydbg

continue the discussion of reply # 55

I just test this code:


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

struct tm * current;

int main(void)
{

   current->
}

But I can't find "current" in the global token tree. So, I believe there is something wrong with parsing the statement:




struct tm * current;


Need time to find the bug...
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

ollydbg

#57
Quote from: koso on September 27, 2009, 09:18:14 PM
Hello, using latest SVN build (and probably not only latest), I am having problem with code completion for variables declared using "struct" keyword.

This bug is fixed by this patch

see the new patch on this post

http://forums.next.codeblocks.org/index.php?topic=11187.msg76648#msg76648

here is the test code:


struct tm
{
int tm_sec;
int b;

};

struct tm *current;

int main(void)
{

   current->
}


and this is the screenshot:

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

mmkider

#58
I Found a crash, See picture.
At last, I need keyin '\n' but I keyin '\'. it will crash.


[attachment deleted by admin]

ollydbg

Quote from: mmkider on September 28, 2009, 05:25:29 AM
I Found a crash, See picture.
At last, I need keyin '\n' but I keyin '\'. it will crash.


I can't reproduce the crash when entering only one statements, can you give a simple testing code?
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.