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

Is it possible for the parser to support newlib prototypes?

<< < (10/12) > >>

ollydbg:

--- Quote from: Huki on September 21, 2014, 07:44:47 pm ---
--- Quote ---I'm testing your patch now. It looks like macro expansion is enabled on every identifier like tokens.
--- End quote ---
Yes, when the (!switchHandled) case is reached in DoParse(), it now expands all macros, including variable-like ones.

--- End quote ---
When I first look at this function, I see that it only expand function-like macro usage.


--- Code: ---void ParserThread::HandleMacroExpansion(int id, const wxString &peek)
{
    Token* tk = m_TokenTree->at(id);
    if (tk)
    {
        TRACE(_T("HandleMacroExpansion() : Adding token '%s' (peek='%s')"), tk->m_Name.wx_str(), peek.wx_str());
        DoAddToken(tkMacroUse, tk->m_Name, m_Tokenizer.GetLineNumber(), 0, 0, peek);

        if (m_Options.parseComplexMacros)
            m_Tokenizer.ReplaceFunctionLikeMacro(tk);
    }
}
--- End code ---
But This is not true.

--- Code: ---bool Tokenizer::ReplaceFunctionLikeMacro(const Token* tk)
{
    wxString macroExpandedText;
    if ( GetMacroExpandedText(tk, macroExpandedText) )
        return ReplaceBufferText(macroExpandedText);
    return false;
}

--- End code ---
Our recent changes in GetMacroExpandedText() function covers the handling of variable-like macro usage expansion.

So, the function name "ReplaceFunctionLikeMacro" cause confusing and need to be renamed.  ;D

ollydbg:

--- Quote from: Huki on September 21, 2014, 07:44:47 pm ---...
On second look I noticed we can do a little optimization. This code:

--- Code: ---wxString arg = peek;
arg.Remove(0,1); // remove '('
if (arg.GetChar(0) == ParserConsts::ptr)
{
    arg.Remove(0,1).Trim(false); // remove '*'
    [...]
}
--- End code ---
can be changed to:

--- Code: ---if (peek.GetChar(1) == ParserConsts::ptr)
{
    wxString arg = peek;
    arg.Remove(0,2).Trim(false); // remove "(*"
    [...]
}
--- End code ---

So the entire code for this case:

--- Code: ---// see what is inside the (...)
// try to see whether the peek pattern is (* BBB)
if (peek.GetChar(1) == ParserConsts::ptr)
{
    wxString arg = peek;
    arg.RemoveLast(); // remove ")"
    arg.Remove(0,2).Trim(false); // remove "(* "
    m_Str << token;
    token = m_Tokenizer.GetToken(); //consume the peek
    // BBB is now the function ptr's name
    HandleFunction(/*function name*/ arg,
                   /*isOperator*/    false,
                   /*isPointer*/     true);
}
else if [...]
--- End code ---
That way we don't have to create a temporary variable 'arg' every time when we see a function declaration-like pattern, but only when we know for sure it can be a function pointer.



--- Quote ---I'm testing your patch now. It looks like macro expansion is enabled on every identifier like tokens.
--- End quote ---
Yes, when the (!switchHandled) case is reached in DoParse(), it now expands all macros, including variable-like ones.


--- End quote ---
Hi, Huki' patch is in trunk now, thanks for your contribution!

ollydbg:

--- Quote from: ollydbg on September 22, 2014, 04:04:38 am ---...
So, the function name "ReplaceFunctionLikeMacro" cause confusing and need to be renamed.  ;D

--- End quote ---
Done in the trunk r9934.

WinterMute:
Wow! Amazing job. Thank you so much for doing this - I really wasn't expecting it  :D

Huki:
Hi,
I reviewed some remaining patches I have and noticed I have not yet submitted this one:


--- Quote from: Huki on September 18, 2014, 01:16:09 pm ---
--- Quote from: Teybeo on September 17, 2014, 02:52:54 pm ---Oops yeah, I confirm, it works like in your screenshot, good job :) !

(Minor UI detail, it would be nice if the function calltip was showing the true name of the function and not PFNGLDRAWARRAYSINSTANCEDPROC)

--- End quote ---
Yes, I think it would be better to show the variable name rather than the typedef name. See here:


I'll submit the patch soon...

--- End quote ---

When we display the calltip for a typedef'd function pointer, we can show the function pointer's name rather than the typedef's name.
Here is the patch:


--- Code: ---From 65004d39e614519c66475a5295a6f6d44e4e3341 Mon Sep 17 00:00:00 2001
From: huki <gk7huki@gmail.com>
Date: Thu, 18 Sep 2014 18:25:20 +0530
Subject: CC: update typedef'd func pointer calltip

---
 src/plugins/codecompletion/nativeparser_base.cpp | 47 +++++++++++++-----------
 src/plugins/codecompletion/nativeparser_base.h   |  8 ++--
 2 files changed, 29 insertions(+), 26 deletions(-)

diff --git a/src/plugins/codecompletion/nativeparser_base.cpp b/src/plugins/codecompletion/nativeparser_base.cpp
index 778d55a..5abfadb 100644
--- a/src/plugins/codecompletion/nativeparser_base.cpp
+++ b/src/plugins/codecompletion/nativeparser_base.cpp
@@ -1685,7 +1685,7 @@ void NativeParserBase::ComputeCallTip(TokenTree*         tree,
 
             // either a function or a variable, but it is OK if a macro with not empty m_Args.
             if (tk && ((tk->m_TokenKind ^ tkMacroDef) || !tk->m_Args.empty()))
-                token = tk; // tkVariable could be a typedef'd function ptr (checked later down below)
+                token = tk; // tkVariable could be a typedef'd function ptr (checked in PrettyPrintToken())
             else
             {
                 // a variable like macro, this token don't have m_Args(call tip information), but
@@ -1711,33 +1711,36 @@ void NativeParserBase::ComputeCallTip(TokenTree*         tree,
             }
         }
 
-        // a variable basically don't have call tips, but if it's type is a typedef'd function
-        // pointer, we can still have call tips (which is the typedef function's arguments)
-        if (token->m_TokenKind == tkVariable)
-        {
-            const Token* tk = tree->at(tree->TokenExists(token->m_BaseType, token->m_ParentIndex, tkTypedef));
-            if (!tk && token->m_ParentIndex != -1)
-                tk = tree->at(tree->TokenExists(token->m_BaseType, -1, tkTypedef));
-            if (tk && !tk->m_Args.empty())
-                token = tk; // typedef'd function pointer
-        }
+        wxString tkTip;
+        if ( !PrettyPrintToken(tree, token, tkTip) )
+            tkTip = wxT("Error while pretty printing token!");
+        items.Add(tkTip);
 
-        {
-            wxString tkTip;
-            if ( !PrettyPrintToken(tree, token, tkTip) )
-                tkTip = wxT("Error while pretty printing token!");
-            items.Add(tkTip);
-        }
     }// for
 
     CC_LOCKER_TRACK_TT_MTX_UNLOCK(s_TokenTreeMutex)
 }
 
-bool NativeParserBase::PrettyPrintToken(const TokenTree*  tree,
-                                        const Token*      token,
-                                        wxString&         result,
-                                        bool              isRoot)
+bool NativeParserBase::PrettyPrintToken(TokenTree*      tree,
+                                        const Token*    token,
+                                        wxString&       result,
+                                        bool            isRoot)
 {
+    wxString name = token->m_Name;
+    // a variable basically don't have call tips, but if it's type is a typedef'd function
+    // pointer, we can still have call tips (which is the typedef function's arguments)
+    if (token->m_TokenKind == tkVariable)
+    {
+        const Token* tk = tree->at(tree->TokenExists(token->m_BaseType, token->m_ParentIndex, tkTypedef));
+        if (!tk && token->m_ParentIndex != -1)
+            tk = tree->at(tree->TokenExists(token->m_BaseType, -1, tkTypedef));
+        if (tk && !tk->m_Args.empty()) // typedef'd function pointer
+        {
+            name = token->m_Name;
+            token = tk;
+        }
+    }
+
     // if the token has parents and the token is a container or a function,
     // then pretty print the parent of the token->
     if (   (token->m_ParentIndex != -1)
@@ -1776,7 +1779,7 @@ bool NativeParserBase::PrettyPrintToken(const TokenTree*  tree,
             return true;
 
         case tkTypedef:
-            result = token->m_BaseType + wxT(" ") + result + token->m_Name + token->GetFormattedArgs();
+            result = token->m_BaseType + wxT(" ") + result + name + token->GetFormattedArgs();
             return true;
 
         case tkEnum:
diff --git a/src/plugins/codecompletion/nativeparser_base.h b/src/plugins/codecompletion/nativeparser_base.h
index 586c5ae..ab90894 100644
--- a/src/plugins/codecompletion/nativeparser_base.h
+++ b/src/plugins/codecompletion/nativeparser_base.h
@@ -321,10 +321,10 @@ protected:
     /** For ComputeCallTip()
      * No critical section needed in this recursive function!
      * All functions that call this recursive function, should already entered a critical section. */
-    bool PrettyPrintToken(const TokenTree*   tree,
-                          const Token*       token,
-                          wxString&          result,
-                          bool               isRoot = true);
+    bool PrettyPrintToken(TokenTree*    tree,
+                          const Token*  token,
+                          wxString&     result,
+                          bool          isRoot = true);
 
     // convenient static funcs for fast access and improved readability
 
--
1.9.4.msysgit.0


--- End code ---


PS: I got your notification about checking macro usage for every token, but I was too busy to check it earlier. Anyway, it's too complex so I think it's better to keep it aside for now...

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version