[Qt-creator] Extract complete prototype of a function from AST

Nikolai Kosjar nikolai.kosjar at digia.com
Thu Oct 31 10:12:44 CET 2013


Hi!

On 10/30/2013 05:04 PM, dydx wrote:
> Hello all, I have read the AST traverse code in FindUsages class. It
> seems that a AST just organize all tokens in a file into a tree. Each
> node in the tree corresponds a syntax element(For example, a statement,
> or an expression). Also, a leaf node will carry a token index, which can
> be used to query the actual token by calling ASTVisitor::tokenAt(idx).

Correct, though non-leaf nodes might also carry token indices, e.g. the 
*statements having a ';' in the end. The AST (Abstract Syntax Tree) is 
the output of the parser.

To visually inspect the AST for given code, you can use the 
cplusplus-ast2png tool residing in tests/tools/cplusplus-ast2png. See 
also [1]

> (1) Is the code above right? Why doc->check() will crash?

Looks ok-ish in general.

Where is your snapshot from? If your file/document is already in the 
snapshot, Snapshot::preprocessedDocument will return the appropriate 
document for that file. And that one was probably already "check()ed", 
hence the Q_ASSERT triggers. Either use an empty Snapshot or don't try 
to check() again.

Document::tokenize() obviously creates tokens, so you can access/inspect 
them via document->translationUnit()->tokenAt(i)/tokenCount().

Document::parse() inspects the tokens and creates the AST, which you can 
access  by document->translationsUnit()->ast().

Document::check() runs on the AST and creates the symbols hierarchy. The 
entry point here is document->globalNamespace().

Note that check() calls parse() if necessary, and this one calls 
tokenize() if necessary.

 >      // It seems that both AST are the same, isn't it ?

Yes. The Control and TranslationUnit are tightly coupled, that's why 
there are two ways to get the AST. If you don't have to, don't use the 
control (way).

> (2) How to release memory when I don't need the AST any more? Just call
> Document::releaseSourceAndAST() ?

Yes. Note that this will also clear the tokens.

> (3) Most importantly, as I want to extract the call graph, I want to get
> the complete and exact declaration of any function I encounter.
>       For example,  there are several overloaded versions of the
> following function:
>       int ClassA::funcA();
>       int ClassA::funcA(int varA);
>       Suppose when I traverse the AST, I encounter "objA->funcA(5);" .
> So how can I find its prototype "int ClassA::funcA(int varA);",
>       instead of "int ClassA::funcA();"? Is there any "binding" for a
> ast element, such as the definition of a function?

The ASTs of function declarations and definitions (SimpleDeclarationAST, 
FunctionDefinitionAST) have a symbol(s) member once Document::check() 
was executed. Check symbol->type()->asFunctionType() - the "Function" 
contains the information about the return value and arguments.

For CallASTs, you have to do a lookup via TypeOfExpression. This is e.g. 
done for F2 / Follow Symbol Under Cursor in Creator. Take a look at 
FollowSymbolUnderCursor::findLink, starting with the line creating the 
TypeOfExpression object.

The SymbolFinder class will help you find the matching 
declarations/definitions.

> (4) An extra question, when I debugged the QtCreator code in visual
> studio, I found it sometimes took a lot of time for QtCreator to
>       parse the source after a project was opened, but quite fast
> (several seconds) in other times. This was really strange because the
>       project was the same. That wasted me a lot of time. How to solve it ?

Might be cache related?


Nikolai


[1] 
https://qt-project.org/wiki/Qt_Creator_DevIntro_CppSupport#a6c32c7c0e089ee14dca4cc704f6efe2



More information about the Qt-creator mailing list