Developer forums (C::B DEVELOPMENT STRICTLY!) > Development

Several improvements to Code Completion plugin

<< < (24/29) > >>

Huki:
Here is a patch that adds support for:
1) Nested unnamed (struct or union) within unnamed: all the members should be invokable from the parent class or struct.
2) Show tooltips for members of unnamed / enum within class invoked directly (also for nested cases).

Patch:

--- Code: ---From ef154d4ef188d77b10bc7ff55d5bcb54b18d66a2 Mon Sep 17 00:00:00 2001
From: huki <gk7huki@gmail.com>
Date: Tue, 24 Jun 2014 08:15:00 +0530
Subject: CC: Support unnamed or enum within class, recursive

---
 src/plugins/codecompletion/nativeparser_base.cpp | 13 +++++++--
 src/plugins/codecompletion/nativeparser_base.h   | 34 +++++++++++++++++++++++-
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/src/plugins/codecompletion/nativeparser_base.cpp b/src/plugins/codecompletion/nativeparser_base.cpp
index e85b8be..5f04b0c 100644
--- a/src/plugins/codecompletion/nativeparser_base.cpp
+++ b/src/plugins/codecompletion/nativeparser_base.cpp
@@ -1411,7 +1411,14 @@ size_t NativeParserBase::GenerateResultSet(TokenTree*          tree,
                 {
                     const Token* token = tree->at(*it);
                     // check whether its under the parentIdx
-                    if (token && (token->m_ParentIndex == parentIdx))
+                    //NOTE: check for unnamed or enum inside class.
+                    // eg, 'ParserCommon::ParserState::ptCreateParser' should be accessed as 'ParserCommon::ptCreateParser'.
+                    // Here, token is ptCreateParser and parentIdx is ParserCommon, so 'token->m_ParentIndex == parentIdx'
+                    // is false. Now, we iterate over the children of parentIdx and check if any of them is unnamed or enum
+                    // and match with token->m_ParentIndex. Thus if we confirm that 'token' is a child of unnamed or enum
+                    // (i.e., m_ParentIndex), we add the token to result.
+                    if (token && ((token->m_ParentIndex == parentIdx)
+                              || IsChildOfUnnamedOrEnum(tree, token->m_ParentIndex, parentIdx)))
                         result.insert(*it);
 
                     // "result" will become the search scope for the next loop, so
@@ -1437,7 +1444,9 @@ size_t NativeParserBase::GenerateResultSet(TokenTree*          tree,
                                   ancestorIterator != tokenParent->m_Ancestors.end();
                                   ++ancestorIterator )
                             {
-                                if (token->m_ParentIndex == (*ancestorIterator)) //matched
+                                //NOTE: check for unnamed or enum inside class (see note above).
+                                if (token && ((token->m_ParentIndex == (*ancestorIterator)) //matched
+                                          || IsChildOfUnnamedOrEnum(tree, token->m_ParentIndex, (*ancestorIterator))))
                                     result.insert(*it);
                             }
                         }
diff --git a/src/plugins/codecompletion/nativeparser_base.h b/src/plugins/codecompletion/nativeparser_base.h
index 3141e61..da60fea 100644
--- a/src/plugins/codecompletion/nativeparser_base.h
+++ b/src/plugins/codecompletion/nativeparser_base.h
@@ -495,7 +495,12 @@ private:
                 if (    tokenChild
                     && (parent->m_TokenKind == tkClass || tokenChild->m_Scope != tsPrivate) )
                 {
-                    result.insert(*it);
+                    //NOTE: recurse (eg: class A contains struct contains union or enum)
+                    if ( !AddChildrenOfUnnamed(tree, tokenChild, result) )
+                    {
+                        result.insert(*it);
+                        AddChildrenOfEnum(tree, tokenChild, result);
+                    }
                 }
             }
             return true;
@@ -520,6 +525,33 @@ private:
         }
         return false;
     }
+
+    bool IsChildOfUnnamedOrEnum(TokenTree* tree, const int targetIdx, const int parentIdx)
+    {
+        if (targetIdx == parentIdx)
+            return true;
+        if (parentIdx == -1)
+            return false;
+
+        Token* parent = tree->at(parentIdx);
+        if (parent && (parent->m_TokenKind & tkClass))
+        {
+            for (TokenIdxSet::const_iterator it = parent->m_Children.begin();
+                                             it != parent->m_Children.end(); ++it)
+            {
+                Token* token = tree->at(*it);
+                if (token && (((token->m_TokenKind & tkClass)
+                                && (token->m_IsAnonymous == true))
+                             || (token->m_TokenKind & tkEnum)))
+                {
+                    if ((targetIdx == (*it)) || IsChildOfUnnamedOrEnum(tree, targetIdx, (*it)))
+                        return true;
+                }
+            }
+        }
+        return false;
+    }
+
 
     /**  loop on the input Token index set (source), add all its public constructors to output Token index set (dest) */
     void AddConstructors(TokenTree *tree, const TokenIdxSet& source, TokenIdxSet& dest);
--
1.9.4.msysgit.0


--- End code ---

Code to test:

--- Code: ---class ClassA
{
public:
    int a;
    struct A
    {
        int c;
    } z;
    struct
    {
        int s;
        union
        {
            int u;
            short v;
        };
        enum EnumS
        {
            STRUCT_A,
            STRUCT_B,
        };
    };

    enum
    {
        UNNAMED_A,
        UNNAMED_B
    };
    enum EnumA
    {
        ENUM_A,
        ENUM_B
    };
};

// Hovering on following member variables should
// show tooltip: a, s, u, v, all the enums like STRUCT_A, etc.
ClassA::a; // replace 'a' with other members listed above

// However ClassA::c is illegal and should not display tooltip.
ClassA::c; // no tip
ClassA::A::c; // should show tip

// Code completion should show all legal members.
ClassA:: // cursor here


--- End code ---

SteelRat:

--- Quote from: ollydbg on August 28, 2014, 03:32:36 am ---I just test a minimal sample code

--- Code: ---#define TOUCHSCREEN 1
#if defined(TOUCHSCREEN)
void InputManager::ConvertTouch(sf::Event& event)
{

}
#endif

--- End code ---
It works fine here, I can see the member function symbols in code completion plugin's symbol browser tree.

--- End quote ---

Here it is, macros highlighting for inactive code is ON, TEST defined in Compiler's global defines. Parser knows about it and about TEST2, but it can't find declaration for TEST2 and TEST3.

ollydbg:

--- Quote from: SteelRat on August 29, 2014, 10:34:53 pm ---Here it is, macros highlighting for inactive code is ON

--- End quote ---
This option is not related to CC plugin.



--- Quote ---TEST defined in Compiler's global defines. Parser knows about it and about TEST2, but it can't find declaration for TEST2 and TEST3.

--- End quote ---

Confirm this bug. It looks like CC doesn't collect the macro definitions if it is defined in "Compiler's global defines".

Note that the below code works OK

--- Code: ---#define TEST

#ifdef TEST
    #define TEST2
#endif // TEST

#ifdef TEST2
    #define TEST3
#endif // TEST2


--- End code ---


MortenMacFly:

--- Quote from: ollydbg on August 30, 2014, 08:11:00 am ---Confirm this bug. It looks like CC doesn't collect the macro definitions if it is defined in "Compiler's global defines".

--- End quote ---
I've noticed this, too. Its even worse: CC does not honour if you've setup something like "target options only" or alike. Also the order of global compile/project/target settings is not considered which may override #defines. Collecting existing macros could need some improvements.

I have it on my todo list but didn't look into it so far...

ollydbg:

--- Quote from: MortenMacFly on August 30, 2014, 11:47:55 am ---
--- Quote from: ollydbg on August 30, 2014, 08:11:00 am ---Confirm this bug. It looks like CC doesn't collect the macro definitions if it is defined in "Compiler's global defines".

--- End quote ---
I've noticed this, too. Its even worse: CC does not honour if you've setup something like "target options only" or alike.

--- End quote ---
I think CC just collect all the target options, we have discussed this some times ago in this thread, Huki has a patch to reparse the project if an active target changes, but I have some concerns about this option.


--- Quote ---Also the order of global compile/project/target settings is not considered which may override #defines. Collecting existing macros could need some improvements.
--- End quote ---
We have already a function bool NativeParser::AddProjectDefinedMacros(cbProject* project, ParserBase* parser), which collects macro definitions for a whole project. Adding the global compiler options should be similar.

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version