Patch #2566 2008-09-21 07:52

geister

codecompletion: Adding "union" (basic)
Download
2566-codecompletion.patch (10.1 KB)
Category
Plugin::FeatureAdd
Status
Accepted
Close date
2009-08-24 07:42
Assigned to
mortenmacfly
Index: plugins/codecompletion/parser/parserthread.h
===================================================================
--- plugins/codecompletion/parser/parserthread.h    (revision 5213)
+++ plugins/codecompletion/parser/parserthread.h    (working copy)
@@ -86,8 +86,9 @@
         void HandleIncludes();
         void HandleDefines();
         void HandlePreprocessorBlocks(const wxString& preproc);
-        void HandleNamespace();
-        void HandleClass(bool isClass = true);
+        void HandleNamespace();
+        void ReadVarNames();
+        void HandleClass(int isType = 1 /* class */);
         void HandleFunction(const wxString& name, bool isOperator = false);
         void HandleEnum();
         void HandleTypedef();
Index: plugins/codecompletion/parser/parserthread.cpp
===================================================================
--- plugins/codecompletion/parser/parserthread.cpp    (revision 5213)
+++ plugins/codecompletion/parser/parserthread.cpp    (working copy)
@@ -525,7 +525,7 @@
         {
             m_Str.Clear();
             if (m_Options.handleClasses)
-                HandleClass(false);
+                HandleClass(0 /* structure */);
             else
                 SkipToOneOfChars(ParserConsts::semicolonclbrace, true);
         }
@@ -538,7 +538,8 @@
                 SkipToOneOfChars(ParserConsts::semicolonclbrace, true);
         }
         else if (token==ParserConsts::kw_union)
-        {
+        {
+#if 0
             SkipToOneOfChars(ParserConsts::opbracesemicolon);
 //            if (m_Tokenizer.GetToken() == "{")
             {
@@ -546,7 +547,14 @@
                 DoParse();
                 m_Str.Clear();
                 m_pLastParent = oldparent;
-            }
+            }
+#endif
+
+            m_Str.Clear();
+            if (m_Options.handleClasses)
+                HandleClass(2 /* union */);
+            else
+                SkipToOneOfChars(ParserConsts::semicolonclbrace, true);
         }
 #if 1
         else if (token==ParserConsts::kw_operator)
@@ -1101,9 +1109,31 @@
             SkipToOneOfChars(ParserConsts::semicolonopbrace); // some kind of error in code ?
         }
     }
+}
+
+void ParserThread::ReadVarNames()
+{
+    while (1)
+    {
+        wxString current = m_Tokenizer.GetToken();
+
+        if (current.IsEmpty())
+            break;
+        if (current==ParserConsts::comma)
+            continue;
+        else if (current==ParserConsts::semicolon)
+            break;
+        else if (wxIsalpha(current.GetChar(0)))
+        {
+            Manager::Get()->GetLogManager()->DebugLog(F(_T("Adding variable '%s' as '%s' to '%s'"), current.c_str(), m_Str.c_str(), (m_pLastParent?m_pLastParent->m_Name.c_str():_T("<no-parent>"))));
+            DoAddToken(tkVariable, current, m_Tokenizer.GetLineNumber());
+        }
+        else // unexpected
+            break;
+    }
 }
 
-void ParserThread::HandleClass(bool isClass)
+void ParserThread::HandleClass(int isType) // 0 - structure, 1 - class, 2 - union
 {
     // need to force the tokenizer _not_ skip anything
     // as we 're manually parsing class decls
@@ -1188,29 +1218,40 @@
 //                Manager::Get()->GetLogManager()->DebugLog(F(_T("Ancestors: ") + ancestors));
             }
 
-            if (current==ParserConsts::opbrace) // unnamed class/struct
+            if (current==ParserConsts::opbrace) // unnamed class/struct/union
             {
                 static size_t num = 0;
                 wxString unnamedTmp;
-                unnamedTmp.Printf(_T("Unnamed-%s-%d"), isClass ? _T("Class") : _T("Struct"), num++);
+                unnamedTmp.Printf(_T("Unnamed-%s-%d"), isType == 1 ? _T("Class") : isType == 2 ? _T("Union") : _T("Struct"), num++);
 
                 Token* newToken = DoAddToken(tkClass, unnamedTmp, lineNr);
 
                 Token* lastParent = m_pLastParent;
-                TokenScope lastScope = m_LastScope;
+                TokenScope lastScope = m_LastScope;
+                bool parsingTypedef = m_ParsingTypedef;
 
                 m_pLastParent = newToken;
-                // default scope is: private for classes, public for structs
-                m_LastScope = isClass ? tsPrivate : tsPublic;
+                // default scope is: private for classes, public for structs, public for unions
+                m_LastScope = isType == 1 ? tsPrivate : tsPublic;
+                m_ParsingTypedef = false;
 
-                DoParse();
-
-                m_pLastParent = lastParent;
+                DoParse();
+
+                m_ParsingTypedef = parsingTypedef;
+                m_pLastParent = lastParent;
                 m_LastScope = lastScope;
 
-                m_LastUnnamedTokenName = unnamedTmp; // used for typedef'ing anonymous class/struct/union
+                m_LastUnnamedTokenName = unnamedTmp; // used for typedef'ing anonymous class/struct/union
 
-                // we should now be right after the closing brace: read the var name
+                // w
download for full patch...
geister 2008-09-21 08:17

My first patch, so I'm not too sure about the format. Hope that works.

It modifies the codecompletion plugin to add basic "union" support.

It isn't perfect, as it adds "Unnamed-xxx-yyy" tokens to the code completion. Also, the following is not working properly.

union MyUnion {

short s;

char c[2];

};

union MyUnion xx;

"xx" is currently ignored by the parser, as it is presumed to be a forward declaration. Using a typedef for the union declaration will remove the requirement of having the union keyword when declaring xx, therefore taking it in consideration.

Actually, those problems are also present with classes and structures, as it uses the same code.

struct HiddenStruct {

int val;

};

struct HiddenStruct yy;

The same problem occurs. "struct HiddenStruct yy;" is considered to be a forward declaration, when in fact it is an instantiation.

typedef struct {

struct {

int val;

} aa;

} MyStruct;

MyStruct zz;

"aa" in that case is an instance of the unnamed structure, but is not recognized as such by the parser (haven't searched why yet, maybe because it is expecting a "typedef" before the structure or a "=" after the "aa"). It will however display the unnamed structure in the code completion, which is... useless code-wise.

geister 2008-09-21 08:25

Okay, I made an error saying it is considered a forward declaration. But it still is ignored...

geister 2008-09-21 08:59

It now adds the tokens as per the previous example ("yy" is now added and code completion works for it.)

I will try to see how to make it work for the "zz" example.

geister 2008-09-21 10:18

Updated again. Now works with enumerations. Still not working properly with "zz.aa".

Test case:

typedef struct {

struct {

int value;

} aa;

} MyStruct;

MyStruct zz;

struct HiddenStruct {

int val;

};

struct HiddenStruct yy;

enum MyEnum { EnumElementA, EnumElementB = 2 };

enum MyEnum ee;

geister 2008-09-21 12:45

Okay, now I am facing language-specific code.

For more info, see: http://forums.codeblocks.org/index.php/topic,9225.msg65886.html

What does this patch do?

- adds unions to the symbols browser

- allows declaration of variables like "struct MyStruct myvar;"

- allows declarations of variables like "struct AStruct { int blah; } avar, anothervar;"

- probably more stuff I indirectly fixed

What does it not do?

- recursive expansion of variables in classes (coming another day)

geister 2008-09-22 16:55

It doesn't crash anymore when parsing"struct AStruct { int blah; } avar, anothervar;"

Facing bigger problems, for more info see:

http://forums.codeblocks.org/index.php/topic,9225.msg65937.html#msg65937