From 463f83630f8a5797cec1bd7dac354a3557572efb Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Fri, 6 Aug 2010 11:29:41 +0200
Subject: [PATCH] Speed up the comutation of the local members.

---
 src/libs/cplusplus/FindUsages.cpp         |   8 +
 src/plugins/cppeditor/cppchecksymbols.cpp |   8 +
 src/plugins/cppeditor/cpplocalsymbols.cpp | 236 +++++++++-------------
 src/shared/cplusplus/CheckDeclaration.cpp |   8 +-
 src/shared/cplusplus/CheckExpression.cpp  |   2 +-
 5 files changed, 118 insertions(+), 144 deletions(-)

diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp
index 8071781de3d..a36f9364b69 100644
--- a/src/libs/cplusplus/FindUsages.cpp
+++ b/src/libs/cplusplus/FindUsages.cpp
@@ -540,6 +540,14 @@ Scope *FindUsages::enclosingScope()
             if (foreachStmt->symbol)
                 return foreachStmt->symbol->members();
 
+        } else if (SwitchStatementAST *switchStmt = ast->asSwitchStatement()) {
+            if (switchStmt->symbol)
+                return switchStmt->symbol->members();
+
+        } else if (CatchClauseAST *catchClause = ast->asCatchClause()) {
+            if (catchClause->symbol)
+                return catchClause->symbol->members();
+
         }
     }
 
diff --git a/src/plugins/cppeditor/cppchecksymbols.cpp b/src/plugins/cppeditor/cppchecksymbols.cpp
index 638a091bdf0..923928063ee 100644
--- a/src/plugins/cppeditor/cppchecksymbols.cpp
+++ b/src/plugins/cppeditor/cppchecksymbols.cpp
@@ -392,6 +392,14 @@ Scope *CheckSymbols::enclosingScope() const
             if (foreachStmt->symbol)
                 return foreachStmt->symbol->members();
 
+        } else if (SwitchStatementAST *switchStmt = ast->asSwitchStatement()) {
+            if (switchStmt->symbol)
+                return switchStmt->symbol->members();
+
+        } else if (CatchClauseAST *catchClause = ast->asCatchClause()) {
+            if (catchClause->symbol)
+                return catchClause->symbol->members();
+
         }
     }
 
diff --git a/src/plugins/cppeditor/cpplocalsymbols.cpp b/src/plugins/cppeditor/cpplocalsymbols.cpp
index 0ec5b58934c..e3fbaaee2aa 100644
--- a/src/plugins/cppeditor/cpplocalsymbols.cpp
+++ b/src/plugins/cppeditor/cpplocalsymbols.cpp
@@ -81,205 +81,167 @@ public:
 
 protected:
     using ASTVisitor::visit;
+    using ASTVisitor::endVisit;
 
-    bool findMember(Scope *scope, NameAST *ast, unsigned line, unsigned column)
+    void enterScope(Scope *scope)
     {
-        if (! (ast && ast->name))
-            return false;
-
-        const Identifier *id = ast->name->identifier();
-
-        if (scope) {
-            for (Symbol *member = scope->lookat(id); member; member = member->next()) {
-                if (member->identifier() != id)
-                    continue;
-                else if (member->line() < line || (member->line() == line && member->column() <= column)) {
-                    localUses[member].append(SemanticInfo::Use(line, column, id->size(), SemanticInfo::Use::Local));
-                    return true;
+        _scopeStack.append(scope);
+
+        for (unsigned i = 0; i < scope->symbolCount(); ++i) {
+            if (Symbol *member = scope->symbolAt(i)) {
+                if (member->isDeclaration() || member->isArgument()) {
+                    if (member->name() && member->name()->isNameId()) {
+                        const Identifier *id = member->identifier();
+                        unsigned line, column;
+                        getTokenStartPosition(member->sourceLocation(), &line, &column);
+                        localUses[member].append(SemanticInfo::Use(line, column, id->size(), SemanticInfo::Use::Local));
+                    }
                 }
             }
         }
-
-        return false;
     }
 
-    void searchUsesInTemplateArguments(NameAST *name)
+    virtual bool visit(IdExpressionAST *ast)
     {
-        if (! name)
-            return;
-
-        else if (TemplateIdAST *template_id = name->asTemplateId()) {
-            for (TemplateArgumentListAST *it = template_id->template_argument_list; it; it = it->next) {
-                accept(it->value);
+        if (SimpleNameAST *simpleName = ast->name->asSimpleName()) {
+            const Identifier *id = identifier(simpleName->identifier_token);
+            for (int i = _scopeStack.size() - 1; i != -1; --i) {
+                if (Symbol *member = _scopeStack.at(i)->lookat(id)) {
+                    if (member->sourceLocation() < ast->firstToken() || member->scope()->isPrototypeScope()) {
+                        unsigned line, column;
+                        getTokenStartPosition(simpleName->identifier_token, &line, &column);
+                        localUses[member].append(SemanticInfo::Use(line, column, id->size(), SemanticInfo::Use::Local));
+                        return false;
+                    }
+                }
             }
         }
-    }
 
-    virtual bool visit(SimpleNameAST *ast)
-    { return findMemberForToken(ast->firstToken(), ast); }
+        return true;
+    }
 
-    bool findMemberForToken(unsigned tokenIdx, NameAST *ast)
+    virtual bool visit(QtMemberDeclarationAST *ast)
     {
-        const Token &tok = tokenAt(tokenIdx);
-        if (tok.generated())
-            return false;
-
-        unsigned line, column;
-        getTokenStartPosition(tokenIdx, &line, &column);
-
-        Scope *scope = _doc->scopeAt(line, column);
-
-        while (scope) {
-            if (scope->isPrototypeScope()) {
-                Function *fun = scope->owner()->asFunction();
-                if (findMember(fun->members(), ast, line, column))
-                    return false;
-                else if (findMember(fun->members(), ast, line, column))
-                    return false;
-            } else if (scope->isObjCMethodScope()) {
-                ObjCMethod *method = scope->owner()->asObjCMethod();
-                if (findMember(method->members(), ast, line, column))
-                    return false;
-                else if (findMember(method->arguments(), ast, line, column))
-                    return false;
-            } else if (scope->isBlockScope()) {
-                if (findMember(scope, ast, line, column))
-                    return false;
-            } else {
-                break;
-            }
-
-            scope = scope->enclosingScope();
-        }
+        if (tokenKind(ast->q_token) == T_Q_D)
+            hasD = true;
+        else
+            hasQ = true;
 
-        return false;
+        return true;
     }
 
-    virtual bool visit(MemInitializerAST *ast)
+    virtual bool visit(FunctionDefinitionAST *ast)
     {
-        accept(ast->expression_list);
-        return false;
+        if (ast->symbol)
+            enterScope(ast->symbol->members());
+        return true;
     }
 
-    virtual bool visit(TemplateIdAST *ast)
+    virtual void endVisit(FunctionDefinitionAST *ast)
     {
-        for (TemplateArgumentListAST *arg = ast->template_argument_list; arg; arg = arg->next)
-            accept(arg->value);
-
-        const Token &tok = tokenAt(ast->identifier_token);
-        if (tok.generated())
-            return false;
-
-        unsigned line, column;
-        getTokenStartPosition(ast->firstToken(), &line, &column);
-
-        Scope *scope = _doc->scopeAt(line, column);
-
-        while (scope) {
-            if (scope->isPrototypeScope()) {
-                Function *fun = scope->owner()->asFunction();
-                if (findMember(fun->members(), ast, line, column))
-                    return false;
-                else if (fun->block() && findMember(fun->block()->members(), ast, line, column))
-                    return false;
-            } else if (scope->isBlockScope()) {
-                if (findMember(scope, ast, line, column))
-                    return false;
-            } else {
-                break;
-            }
-
-            scope = scope->enclosingScope();
-        }
-
-        return false;
+        if (ast->symbol)
+            _scopeStack.removeLast();
     }
 
-    virtual bool visit(QualifiedNameAST *ast)
+    virtual bool visit(CompoundStatementAST *ast)
     {
-        for (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list; it; it = it->next)
-            searchUsesInTemplateArguments(it->value->class_or_namespace_name);
-
-        searchUsesInTemplateArguments(ast->unqualified_name);
-        return false;
+        if (ast->symbol)
+            enterScope(ast->symbol->members());
+        return true;
     }
 
-    virtual bool visit(MemberAccessAST *ast)
+    virtual void endVisit(CompoundStatementAST *ast)
     {
-        // accept only the base expression
-        accept(ast->base_expression);
-        // and ignore the member name.
-        return false;
+        if (ast->symbol)
+            _scopeStack.removeLast();
     }
 
-    virtual bool visit(ElaboratedTypeSpecifierAST *)
+    virtual bool visit(IfStatementAST *ast)
     {
-        // ### template args
-        return false;
+        if (ast->symbol)
+            enterScope(ast->symbol->members());
+        return true;
     }
 
-    virtual bool visit(ClassSpecifierAST *)
+    virtual void endVisit(IfStatementAST *ast)
     {
-        // ### template args
-        return false;
+        if (ast->symbol)
+            _scopeStack.removeLast();
     }
 
-    virtual bool visit(EnumSpecifierAST *)
+    virtual bool visit(WhileStatementAST *ast)
     {
-        // ### template args
-        return false;
+        if (ast->symbol)
+            enterScope(ast->symbol->members());
+        return true;
     }
 
-    virtual bool visit(UsingDirectiveAST *)
+    virtual void endVisit(WhileStatementAST *ast)
     {
-        return false;
+        if (ast->symbol)
+            _scopeStack.removeLast();
     }
 
-    virtual bool visit(UsingAST *ast)
+    virtual bool visit(ForStatementAST *ast)
     {
-        accept(ast->name);
-        return false;
+        if (ast->symbol)
+            enterScope(ast->symbol->members());
+        return true;
     }
 
-    virtual bool visit(QtMemberDeclarationAST *ast)
+    virtual void endVisit(ForStatementAST *ast)
     {
-        if (tokenKind(ast->q_token) == T_Q_D)
-            hasD = true;
-        else
-            hasQ = true;
+        if (ast->symbol)
+            _scopeStack.removeLast();
+    }
 
+    virtual bool visit(ForeachStatementAST *ast)
+    {
+        if (ast->symbol)
+            enterScope(ast->symbol->members());
         return true;
     }
 
-    virtual bool visit(ExpressionOrDeclarationStatementAST *ast)
+    virtual void endVisit(ForeachStatementAST *ast)
     {
-        accept(ast->declaration);
-        return false;
+        if (ast->symbol)
+            _scopeStack.removeLast();
     }
 
-    virtual bool visit(FunctionDeclaratorAST *ast)
+    virtual bool visit(SwitchStatementAST *ast)
     {
-        accept(ast->parameters);
-
-        for (SpecifierListAST *it = ast->cv_qualifier_list; it; it = it->next)
-            accept(it->value);
+        if (ast->symbol)
+            enterScope(ast->symbol->members());
+        return true;
+    }
 
-        accept(ast->exception_specification);
+    virtual void endVisit(SwitchStatementAST *ast)
+    {
+        if (ast->symbol)
+            _scopeStack.removeLast();
+    }
 
-        return false;
+    virtual bool visit(CatchClauseAST *ast)
+    {
+        if (ast->symbol)
+            enterScope(ast->symbol->members());
+        return true;
     }
 
-    virtual bool visit(ObjCMethodPrototypeAST *ast)
+    virtual void endVisit(CatchClauseAST *ast)
     {
-        accept(ast->argument_list);
-        return false;
+        if (ast->symbol)
+            _scopeStack.removeLast();
     }
 
-    virtual bool visit(ObjCMessageArgumentDeclarationAST *ast)
+    virtual bool visit(ExpressionOrDeclarationStatementAST *ast)
     {
-        accept(ast->param_name);
+        accept(ast->declaration);
         return false;
     }
+
+private:
+    QList<Scope *> _scopeStack;
 };
 
 } // end of anonymous namespace
diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp
index 98e8616f704..5eb98735d1e 100644
--- a/src/shared/cplusplus/CheckDeclaration.cpp
+++ b/src/shared/cplusplus/CheckDeclaration.cpp
@@ -187,12 +187,8 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
                                                       _scope, &name);
 
         unsigned location = semantic()->location(it->value);
-        if (! location) {
-            if (it->value)
-                location = it->value->firstToken();
-            else
-                location = ast->firstToken();
-        }
+        if (! location)
+            location = ast->firstToken();
 
         Function *fun = 0;
         if (declTy && 0 != (fun = declTy->asFunctionType())) {
diff --git a/src/shared/cplusplus/CheckExpression.cpp b/src/shared/cplusplus/CheckExpression.cpp
index 6a24d3a51dd..27e05390c0a 100644
--- a/src/shared/cplusplus/CheckExpression.cpp
+++ b/src/shared/cplusplus/CheckExpression.cpp
@@ -123,7 +123,7 @@ bool CheckExpression::visit(ConditionAST *ast)
     const Name *name = 0;
     FullySpecifiedType declTy = semantic()->check(ast->declarator, typeSpecTy.qualifiedType(),
                                                   _scope, &name);
-    Declaration *decl = control()->newDeclaration(ast->declarator->firstToken(), name);
+    Declaration *decl = control()->newDeclaration(semantic()->location(ast->declarator), name);
     decl->setType(declTy);
     _scope->enterSymbol(decl);
     return false;
-- 
GitLab