summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Raggi <roberto.raggi@nokia.com>2010-07-15 16:03:48 +0200
committerRoberto Raggi <roberto.raggi@nokia.com>2010-07-15 16:04:16 +0200
commit9b24e0ae2af9523691f99a30bca9e83200bfd6d9 (patch)
tree06ff3c1d52be85f528b6667a8ec3ae4a12e28fb5
parentcc3179ef0309cf6a3d4b33b9bff73c14614e391c (diff)
downloadqt-creator-9b24e0ae2af9523691f99a30bca9e83200bfd6d9.tar.gz
Highlight local and member symbols.
-rw-r--r--src/plugins/cppeditor/cppchecksymbols.cpp115
-rw-r--r--src/plugins/cppeditor/cppchecksymbols.h8
-rw-r--r--src/plugins/cppeditor/cppeditor.cpp274
-rw-r--r--src/plugins/cppeditor/cppeditor.pro6
-rw-r--r--src/plugins/cppeditor/cpplocalsymbols.cpp289
-rw-r--r--src/plugins/cppeditor/cpplocalsymbols.h56
-rw-r--r--src/plugins/cppeditor/cppsemanticinfo.h11
7 files changed, 503 insertions, 256 deletions
diff --git a/src/plugins/cppeditor/cppchecksymbols.cpp b/src/plugins/cppeditor/cppchecksymbols.cpp
index 635ddb6285..f33c6bdf46 100644
--- a/src/plugins/cppeditor/cppchecksymbols.cpp
+++ b/src/plugins/cppeditor/cppchecksymbols.cpp
@@ -28,6 +28,8 @@
**************************************************************************/
#include "cppchecksymbols.h"
+#include "cpplocalsymbols.h"
+
#include <cplusplus/Overview.h>
#include <Names.h>
@@ -45,6 +47,7 @@
#include <qtconcurrent/runextensions.h>
using namespace CPlusPlus;
+using namespace CppEditor::Internal;
namespace {
@@ -53,6 +56,7 @@ class CollectTypes: protected SymbolVisitor
Document::Ptr _doc;
Snapshot _snapshot;
QSet<QByteArray> _types;
+ QSet<QByteArray> _members;
QList<ScopedSymbol *> _scopes;
QList<NameAST *> _names;
bool _mainDocument;
@@ -70,6 +74,11 @@ public:
return _types;
}
+ const QSet<QByteArray> &members() const
+ {
+ return _members;
+ }
+
const QList<ScopedSymbol *> &scopes() const
{
return _scopes;
@@ -126,6 +135,18 @@ protected:
}
}
+ void addMember(const Name *name)
+ {
+ if (! name) {
+ return;
+
+ } else if (name->isNameId()) {
+ const Identifier *id = name->identifier();
+ _members.insert(QByteArray::fromRawData(id->chars(), id->size()));
+
+ }
+ }
+
void addScope(ScopedSymbol *symbol)
{
if (_mainDocument)
@@ -166,6 +187,8 @@ protected:
{
if (symbol->isTypedef())
addType(symbol->name());
+ else if (! symbol->type()->isFunctionType() && symbol->enclosingSymbol()->isClass())
+ addMember(symbol->name());
return true;
}
@@ -267,6 +290,7 @@ CheckSymbols::CheckSymbols(Document::Ptr doc, const LookupContext &context)
_fileName = doc->fileName();
CollectTypes collectTypes(doc, context.snapshot());
_potentialTypes = collectTypes.types();
+ _potentialMembers = collectTypes.members();
_scopes = collectTypes.scopes();
_flushRequested = false;
_flushLine = 0;
@@ -351,6 +375,12 @@ bool CheckSymbols::visit(NamedTypeSpecifierAST *)
return true;
}
+bool CheckSymbols::visit(MemberAccessAST *ast)
+{
+ accept(ast->base_expression);
+ return false;
+}
+
void CheckSymbols::checkNamespace(NameAST *name)
{
if (! name)
@@ -380,6 +410,28 @@ void CheckSymbols::checkName(NameAST *ast)
Scope *scope = findScope(ast);
const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
addTypeUsage(candidates, ast);
+ } else if (_potentialMembers.contains(id)) {
+ Scope *scope = findScope(ast);
+ const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
+ addMemberUsage(candidates, ast);
+ }
+ }
+ }
+}
+
+void CheckSymbols::checkMemberName(NameAST *ast)
+{
+ if (ast && ast->name) {
+ if (const Identifier *ident = ast->name->identifier()) {
+ const QByteArray id = QByteArray::fromRawData(ident->chars(), ident->size());
+ if (_potentialMembers.contains(id)) {
+ Scope *scope = findScope(ast);
+ const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
+ addMemberUsage(candidates, ast);
+ } else if (_potentialMembers.contains(id)) {
+ Scope *scope = findScope(ast);
+ const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
+ addMemberUsage(candidates, ast);
}
}
}
@@ -473,14 +525,35 @@ void CheckSymbols::endVisit(TemplateDeclarationAST *)
_templateDeclarationStack.takeFirst();
}
+bool CheckSymbols::visit(FunctionDefinitionAST *ast)
+{
+ _functionDefinitionStack.append(ast);
+ const LocalSymbols locals(_doc, ast);
+ QList<SemanticInfo::Use> uses;
+ foreach (uses, locals.uses) {
+ foreach (const SemanticInfo::Use &u, uses)
+ addTypeUsage(u);
+ }
+
+ accept(ast->decl_specifier_list);
+ accept(ast->declarator);
+ accept(ast->ctor_initializer);
+ accept(ast->function_body);
+
+ _functionDefinitionStack.removeLast();
+ return false;
+}
+
void CheckSymbols::addTypeUsage(const Use &use)
{
- if (_typeUsages.size() >= 50) {
- if (_flushRequested && use.line != _flushLine)
- flush();
- else if (! _flushRequested) {
- _flushRequested = true;
- _flushLine = use.line;
+ if (_functionDefinitionStack.isEmpty()) {
+ if (_typeUsages.size() >= 50) {
+ if (_flushRequested && use.line != _flushLine)
+ flush();
+ else if (! _flushRequested) {
+ _flushRequested = true;
+ _flushLine = use.line;
+ }
}
}
@@ -538,6 +611,36 @@ void CheckSymbols::addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast)
}
}
+void CheckSymbols::addMemberUsage(const QList<Symbol *> &candidates, NameAST *ast)
+{
+ unsigned startToken = ast->firstToken();
+ if (DestructorNameAST *dtor = ast->asDestructorName())
+ startToken = dtor->identifier_token;
+
+ const Token &tok = tokenAt(startToken);
+ if (tok.generated())
+ return;
+
+ unsigned line, column;
+ getTokenStartPosition(startToken, &line, &column);
+ const unsigned length = tok.length();
+
+ foreach (Symbol *c, candidates) {
+ if (! c->isDeclaration())
+ continue;
+ else if (c->isTypedef())
+ continue;
+ else if (c->type()->isFunctionType())
+ continue;
+ else if (! c->enclosingSymbol()->isClass())
+ continue;
+
+ const Use use(line, column, length, Use::Field);
+ addTypeUsage(use);
+ //qDebug() << "added use" << oo(ast->name) << line << column << length;
+ }
+}
+
unsigned CheckSymbols::startOfTemplateDeclaration(TemplateDeclarationAST *ast) const
{
if (ast->declaration) {
diff --git a/src/plugins/cppeditor/cppchecksymbols.h b/src/plugins/cppeditor/cppchecksymbols.h
index 876132ab3f..bb996fb691 100644
--- a/src/plugins/cppeditor/cppchecksymbols.h
+++ b/src/plugins/cppeditor/cppchecksymbols.h
@@ -87,6 +87,9 @@ protected:
void addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast);
void addTypeUsage(const Use &use);
+ void checkMemberName(NameAST *ast);
+ void addMemberUsage(const QList<Symbol *> &candidates, NameAST *ast);
+
virtual bool preVisit(AST *);
virtual bool visit(NamespaceAST *);
@@ -105,6 +108,9 @@ protected:
virtual bool visit(TypenameTypeParameterAST *ast);
virtual bool visit(TemplateTypeParameterAST *ast);
+ virtual bool visit(FunctionDefinitionAST *ast);
+ virtual bool visit(MemberAccessAST *ast);
+
unsigned startOfTemplateDeclaration(TemplateDeclarationAST *ast) const;
Scope *findScope(AST *ast) const;
@@ -116,8 +122,10 @@ private:
QString _fileName;
QList<Document::DiagnosticMessage> _diagnosticMessages;
QSet<QByteArray> _potentialTypes;
+ QSet<QByteArray> _potentialMembers;
QList<ScopedSymbol *> _scopes;
QList<TemplateDeclarationAST *> _templateDeclarationStack;
+ QList<FunctionDefinitionAST *> _functionDefinitionStack;
QVector<Use> _typeUsages;
bool _flushRequested;
unsigned _flushLine;
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index adef080f35..034e178312 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -33,6 +33,7 @@
#include "cpphighlighter.h"
#include "cppchecksymbols.h"
#include "cppquickfix.h"
+#include "cpplocalsymbols.h"
#include <AST.h>
#include <Control.h>
@@ -172,240 +173,6 @@ private:
CPlusPlus::OverviewModel *m_sourceModel;
};
-
-class FindLocalUses: protected ASTVisitor
-{
- Scope *_functionScope;
- Document::Ptr _doc;
-
-public:
- FindLocalUses(Document::Ptr doc)
- : ASTVisitor(doc->translationUnit()), _doc(doc), hasD(false), hasQ(false)
- { }
-
- // local and external uses.
- SemanticInfo::LocalUseMap localUses;
- bool hasD;
- bool hasQ;
-
- void operator()(DeclarationAST *ast)
- {
- localUses.clear();
-
- if (!ast)
- return;
-
- if (FunctionDefinitionAST *def = ast->asFunctionDefinition()) {
- if (def->symbol) {
- _functionScope = def->symbol->members();
- accept(ast);
- }
- } else if (ObjCMethodDeclarationAST *decl = ast->asObjCMethodDeclaration()) {
- if (decl->method_prototype->symbol) {
- _functionScope = decl->method_prototype->symbol->members();
- accept(ast);
- }
- }
- }
-
-protected:
- using ASTVisitor::visit;
-
- bool findMember(Scope *scope, NameAST *ast, unsigned line, unsigned column)
- {
- 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()));
- return true;
- }
- }
- }
-
- return false;
- }
-
- void searchUsesInTemplateArguments(NameAST *name)
- {
- 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);
- }
- }
- }
-
- virtual bool visit(SimpleNameAST *ast)
- { return findMemberForToken(ast->firstToken(), ast); }
-
- bool findMemberForToken(unsigned tokenIdx, NameAST *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->isFunctionScope()) {
- Function *fun = scope->owner()->asFunction();
- if (findMember(fun->members(), ast, line, column))
- return false;
- else if (findMember(fun->arguments(), 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();
- }
-
- return false;
- }
-
- virtual bool visit(TemplateIdAST *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->isFunctionScope()) {
- Function *fun = scope->owner()->asFunction();
- if (findMember(fun->members(), ast, line, column))
- return false;
- else if (findMember(fun->arguments(), ast, line, column))
- return false;
- } else if (scope->isBlockScope()) {
- if (findMember(scope, ast, line, column))
- return false;
- } else {
- break;
- }
-
- scope = scope->enclosingScope();
- }
-
- return false;
- }
-
- virtual bool visit(QualifiedNameAST *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;
- }
-
- virtual bool visit(MemberAccessAST *ast)
- {
- // accept only the base expression
- accept(ast->base_expression);
- // and ignore the member name.
- return false;
- }
-
- virtual bool visit(ElaboratedTypeSpecifierAST *)
- {
- // ### template args
- return false;
- }
-
- virtual bool visit(ClassSpecifierAST *)
- {
- // ### template args
- return false;
- }
-
- virtual bool visit(EnumSpecifierAST *)
- {
- // ### template args
- return false;
- }
-
- virtual bool visit(UsingDirectiveAST *)
- {
- return false;
- }
-
- virtual bool visit(UsingAST *ast)
- {
- accept(ast->name);
- return false;
- }
-
- virtual bool visit(QtMemberDeclarationAST *ast)
- {
- if (tokenKind(ast->q_token) == T_Q_D)
- hasD = true;
- else
- hasQ = true;
-
- return true;
- }
-
- virtual bool visit(ExpressionOrDeclarationStatementAST *ast)
- {
- accept(ast->declaration);
- return false;
- }
-
- virtual bool visit(FunctionDeclaratorAST *ast)
- {
- accept(ast->parameters);
-
- for (SpecifierListAST *it = ast->cv_qualifier_list; it; it = it->next)
- accept(it->value);
-
- accept(ast->exception_specification);
-
- return false;
- }
-
- virtual bool visit(ObjCMethodPrototypeAST *ast)
- {
- accept(ast->argument_list);
- return false;
- }
-
- virtual bool visit(ObjCMessageArgumentDeclarationAST *ast)
- {
- accept(ast->param_name);
- return false;
- }
-};
-
-
class FunctionDefinitionUnderCursor: protected ASTVisitor
{
unsigned _line;
@@ -1131,6 +898,12 @@ void CPPEditor::highlightTypeUsages(int from, int to)
Q_ASSERT(!chunks.isEmpty());
QTextBlock b = doc->findBlockByNumber(m_nextHighlightBlockNumber);
+ QTextCharFormat localUseFormat;
+ localUseFormat.setForeground(Qt::darkBlue); // ### hardcoded
+
+ QTextCharFormat memberUseFormat;
+ memberUseFormat.setForeground(Qt::darkRed); // ### hardcoded
+
QMapIterator<int, QVector<SemanticInfo::Use> > it(chunks);
while (b.isValid() && it.hasNext()) {
it.next();
@@ -1146,7 +919,24 @@ void CPPEditor::highlightTypeUsages(int from, int to)
QList<QTextLayout::FormatRange> formats;
foreach (const SemanticInfo::Use &use, it.value()) {
QTextLayout::FormatRange formatRange;
- formatRange.format = m_typeFormat;
+
+ switch (use.kind) {
+ case SemanticInfo::Use::Type:
+ formatRange.format = m_typeFormat;
+ break;
+
+ case SemanticInfo::Use::Field:
+ formatRange.format = memberUseFormat;
+ break;
+
+ case SemanticInfo::Use::Local:
+ formatRange.format = localUseFormat;
+ break;
+
+ default:
+ continue;
+ }
+
formatRange.start = use.column - 1;
formatRange.length = use.length;
formats.append(formatRange);
@@ -2187,8 +1977,7 @@ SemanticInfo SemanticHighlighter::semanticInfo(const Source &source)
Snapshot snapshot;
Document::Ptr doc;
QList<Document::DiagnosticMessage> diagnosticMessages;
- QList<SemanticInfo::Use> typeUsages, objcKeywords;
- LookupContext context;
+ QList<SemanticInfo::Use> objcKeywords;
if (! source.force && revision == source.revision) {
m_mutex.lock();
@@ -2207,13 +1996,7 @@ SemanticInfo SemanticHighlighter::semanticInfo(const Source &source)
doc->check();
#if 0
- context = LookupContext(doc, snapshot);
-
if (TranslationUnit *unit = doc->translationUnit()) {
- CheckUndefinedSymbols checkUndefinedSymbols(unit, context);
- diagnosticMessages = checkUndefinedSymbols(unit->ast());
- typeUsages = checkUndefinedSymbols.typeUsages();
-
FindObjCKeywords findObjCKeywords(unit); // ### remove me
objcKeywords = findObjCKeywords();
}
@@ -2226,14 +2009,13 @@ SemanticInfo SemanticHighlighter::semanticInfo(const Source &source)
FunctionDefinitionUnderCursor functionDefinitionUnderCursor(translationUnit);
DeclarationAST *currentFunctionDefinition = functionDefinitionUnderCursor(ast, source.line, source.column);
- FindLocalUses useTable(doc);
- useTable(currentFunctionDefinition);
+ const LocalSymbols useTable(doc, currentFunctionDefinition);
SemanticInfo semanticInfo;
semanticInfo.revision = source.revision;
semanticInfo.snapshot = snapshot;
semanticInfo.doc = doc;
- semanticInfo.localUses = useTable.localUses;
+ semanticInfo.localUses = useTable.uses;
semanticInfo.hasQ = useTable.hasQ;
semanticInfo.hasD = useTable.hasD;
semanticInfo.forced = source.force;
diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro
index 4b017f64fe..274639f414 100644
--- a/src/plugins/cppeditor/cppeditor.pro
+++ b/src/plugins/cppeditor/cppeditor.pro
@@ -20,7 +20,8 @@ HEADERS += cppplugin.h \
cppchecksymbols.h \
cppsemanticinfo.h \
cppoutline.h \
- cppdeclfromdef.h
+ cppdeclfromdef.h \
+ cpplocalsymbols.h
SOURCES += cppplugin.cpp \
cppeditor.cpp \
@@ -33,7 +34,8 @@ SOURCES += cppplugin.cpp \
cppchecksymbols.cpp \
cppsemanticinfo.cpp \
cppoutline.cpp \
- cppdeclfromdef.cpp
+ cppdeclfromdef.cpp \
+ cpplocalsymbols.cpp
RESOURCES += cppeditor.qrc
diff --git a/src/plugins/cppeditor/cpplocalsymbols.cpp b/src/plugins/cppeditor/cpplocalsymbols.cpp
new file mode 100644
index 0000000000..1f5e9f4300
--- /dev/null
+++ b/src/plugins/cppeditor/cpplocalsymbols.cpp
@@ -0,0 +1,289 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "cpplocalsymbols.h"
+#include "cppsemanticinfo.h"
+
+#include <cplusplus/CppDocument.h>
+#include <ASTVisitor.h>
+#include <AST.h>
+#include <Scope.h>
+#include <Symbols.h>
+#include <CoreTypes.h>
+#include <Names.h>
+#include <Literals.h>
+
+using namespace CPlusPlus;
+using namespace CppEditor::Internal;
+
+namespace {
+
+class FindLocalSymbols: protected ASTVisitor
+{
+ Scope *_functionScope;
+ Document::Ptr _doc;
+
+public:
+ FindLocalSymbols(Document::Ptr doc)
+ : ASTVisitor(doc->translationUnit()), _doc(doc), hasD(false), hasQ(false)
+ { }
+
+ // local and external uses.
+ SemanticInfo::LocalUseMap localUses;
+ bool hasD;
+ bool hasQ;
+
+ void operator()(DeclarationAST *ast)
+ {
+ localUses.clear();
+
+ if (!ast)
+ return;
+
+ if (FunctionDefinitionAST *def = ast->asFunctionDefinition()) {
+ if (def->symbol) {
+ _functionScope = def->symbol->members();
+ accept(ast);
+ }
+ } else if (ObjCMethodDeclarationAST *decl = ast->asObjCMethodDeclaration()) {
+ if (decl->method_prototype->symbol) {
+ _functionScope = decl->method_prototype->symbol->members();
+ accept(ast);
+ }
+ }
+ }
+
+protected:
+ using ASTVisitor::visit;
+
+ bool findMember(Scope *scope, NameAST *ast, unsigned line, unsigned column)
+ {
+ 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;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ void searchUsesInTemplateArguments(NameAST *name)
+ {
+ 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);
+ }
+ }
+ }
+
+ virtual bool visit(SimpleNameAST *ast)
+ { return findMemberForToken(ast->firstToken(), ast); }
+
+ bool findMemberForToken(unsigned tokenIdx, NameAST *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->isFunctionScope()) {
+ Function *fun = scope->owner()->asFunction();
+ if (findMember(fun->members(), ast, line, column))
+ return false;
+ else if (findMember(fun->arguments(), 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();
+ }
+
+ return false;
+ }
+
+ virtual bool visit(TemplateIdAST *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->isFunctionScope()) {
+ Function *fun = scope->owner()->asFunction();
+ if (findMember(fun->members(), ast, line, column))
+ return false;
+ else if (findMember(fun->arguments(), ast, line, column))
+ return false;
+ } else if (scope->isBlockScope()) {
+ if (findMember(scope, ast, line, column))
+ return false;
+ } else {
+ break;
+ }
+
+ scope = scope->enclosingScope();
+ }
+
+ return false;
+ }
+
+ virtual bool visit(QualifiedNameAST *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;
+ }
+
+ virtual bool visit(MemberAccessAST *ast)
+ {
+ // accept only the base expression
+ accept(ast->base_expression);
+ // and ignore the member name.
+ return false;
+ }
+
+ virtual bool visit(ElaboratedTypeSpecifierAST *)
+ {
+ // ### template args
+ return false;
+ }
+
+ virtual bool visit(ClassSpecifierAST *)
+ {
+ // ### template args
+ return false;
+ }
+
+ virtual bool visit(EnumSpecifierAST *)
+ {
+ // ### template args
+ return false;
+ }
+
+ virtual bool visit(UsingDirectiveAST *)
+ {
+ return false;
+ }
+
+ virtual bool visit(UsingAST *ast)
+ {
+ accept(ast->name);
+ return false;
+ }
+
+ virtual bool visit(QtMemberDeclarationAST *ast)
+ {
+ if (tokenKind(ast->q_token) == T_Q_D)
+ hasD = true;
+ else
+ hasQ = true;
+
+ return true;
+ }
+
+ virtual bool visit(ExpressionOrDeclarationStatementAST *ast)
+ {
+ accept(ast->declaration);
+ return false;
+ }
+
+ virtual bool visit(FunctionDeclaratorAST *ast)
+ {
+ accept(ast->parameters);
+
+ for (SpecifierListAST *it = ast->cv_qualifier_list; it; it = it->next)
+ accept(it->value);
+
+ accept(ast->exception_specification);
+
+ return false;
+ }
+
+ virtual bool visit(ObjCMethodPrototypeAST *ast)
+ {
+ accept(ast->argument_list);
+ return false;
+ }
+
+ virtual bool visit(ObjCMessageArgumentDeclarationAST *ast)
+ {
+ accept(ast->param_name);
+ return false;
+ }
+};
+
+} // end of anonymous namespace
+
+
+LocalSymbols::LocalSymbols(CPlusPlus::Document::Ptr doc, CPlusPlus::DeclarationAST *ast)
+{
+ FindLocalSymbols FindLocalSymbols(doc);
+ FindLocalSymbols(ast);
+ hasD = FindLocalSymbols.hasD;
+ hasQ = FindLocalSymbols.hasQ;
+ uses = FindLocalSymbols.localUses;
+}
diff --git a/src/plugins/cppeditor/cpplocalsymbols.h b/src/plugins/cppeditor/cpplocalsymbols.h
new file mode 100644
index 0000000000..42f3a2fb0a
--- /dev/null
+++ b/src/plugins/cppeditor/cpplocalsymbols.h
@@ -0,0 +1,56 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CPPLOCALSYMBOLS_H
+#define CPPLOCALSYMBOLS_H
+
+#include "cppsemanticinfo.h"
+#include <cplusplus/CppDocument.h>
+#include <ASTfwd.h>
+
+namespace CppEditor {
+namespace Internal {
+
+class LocalSymbols
+{
+ Q_DISABLE_COPY(LocalSymbols)
+
+public:
+ LocalSymbols(CPlusPlus::Document::Ptr doc, CPlusPlus::DeclarationAST *ast);
+
+ bool hasD;
+ bool hasQ;
+ SemanticInfo::LocalUseMap uses;
+};
+
+}
+
+}
+
+#endif // CPPLOCALSYMBOLS_H
diff --git a/src/plugins/cppeditor/cppsemanticinfo.h b/src/plugins/cppeditor/cppsemanticinfo.h
index 7f374c8ffd..3ea662bdbb 100644
--- a/src/plugins/cppeditor/cppsemanticinfo.h
+++ b/src/plugins/cppeditor/cppsemanticinfo.h
@@ -46,9 +46,16 @@ public:
unsigned line;
unsigned column;
unsigned length;
+ unsigned kind;
- Use(unsigned line = 0, unsigned column = 0, unsigned length = 0)
- : line(line), column(column), length(length) {}
+ enum {
+ Type = 0,
+ Local,
+ Field
+ };
+
+ Use(unsigned line = 0, unsigned column = 0, unsigned length = 0, unsigned kind = Type)
+ : line(line), column(column), length(length), kind(kind) {}
};
typedef QHash<CPlusPlus::Symbol *, QList<Use> > LocalUseMap;