diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp new file mode 100644 index 0000000000000000000000000000000000000000..714f524fdf757cd513147898a4b4d4460e173339 --- /dev/null +++ b/src/libs/cplusplus/FindUsages.cpp @@ -0,0 +1,444 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 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 "FindUsages.h" +#include "TypeOfExpression.h" + +#include <Control.h> +#include <Literals.h> +#include <Names.h> +#include <Symbols.h> +#include <AST.h> + +#include <QtCore/QDir> + +using namespace CPlusPlus; + +FindUsages::FindUsages(Document::Ptr doc, const Snapshot &snapshot, QFutureInterface<Usage> *future) + : ASTVisitor(doc->control()), + _future(future), + _doc(doc), + _snapshot(snapshot), + _source(_doc->source()), + _sem(doc->control()), + _inSimpleDeclaration(0) +{ + _snapshot.insert(_doc); +} + +void FindUsages::setGlobalNamespaceBinding(NamespaceBindingPtr globalNamespaceBinding) +{ + _globalNamespaceBinding = globalNamespaceBinding; +} + +QList<int> FindUsages::operator()(Symbol *symbol, Identifier *id, AST *ast) +{ + _references.clear(); + _declSymbol = symbol; + _id = id; + _exprDoc = Document::create("<references>"); + accept(ast); + return _references; +} + +QString FindUsages::matchingLine(const Token &tk) const +{ + const char *beg = _source.constData(); + const char *cp = beg + tk.offset; + for (; cp != beg - 1; --cp) { + if (*cp == '\n') + break; + } + + ++cp; + + const char *lineEnd = cp + 1; + for (; *lineEnd; ++lineEnd) { + if (*lineEnd == '\n') + break; + } + + const QString matchingLine = QString::fromUtf8(cp, lineEnd - cp); + return matchingLine; +} + +void FindUsages::reportResult(unsigned tokenIndex, const QList<Symbol *> &candidates) +{ + const bool isStrongResult = checkCandidates(candidates); + + if (isStrongResult) + reportResult(tokenIndex); +} + +void FindUsages::reportResult(unsigned tokenIndex) +{ + const Token &tk = tokenAt(tokenIndex); + const QString lineText = matchingLine(tk); + + unsigned line, col; + getTokenStartPosition(tokenIndex, &line, &col); + + if (col) + --col; // adjust the column position. + + const int len = tk.f.length; + + if (_future) { + const QString path = QDir::toNativeSeparators(_doc->fileName()); + _future->reportResult(Usage(path, line, lineText, col, len)); + } + + _references.append(tokenIndex); +} + +bool FindUsages::checkCandidates(const QList<Symbol *> &candidates) const +{ + if (Symbol *canonicalSymbol = LookupContext::canonicalSymbol(candidates, _globalNamespaceBinding.data())) { + +#if 0 + qDebug() << "*** canonical symbol:" << canonicalSymbol->fileName() + << canonicalSymbol->line() << canonicalSymbol->column() + << "candidates:" << candidates.size(); +#endif + + return checkSymbol(canonicalSymbol); + } + + return false; +} + +bool FindUsages::checkScope(Symbol *symbol, Symbol *otherSymbol) const +{ + if (! (symbol && otherSymbol)) + return false; + + else if (symbol->scope() == otherSymbol->scope()) + return true; + + else if (symbol->name() && otherSymbol->name()) { + + if (! symbol->name()->isEqualTo(otherSymbol->name())) + return false; + + } else if (symbol->name() != otherSymbol->name()) { + return false; + } + + return checkScope(symbol->enclosingSymbol(), otherSymbol->enclosingSymbol()); +} + +bool FindUsages::checkSymbol(Symbol *symbol) const +{ + if (! symbol) { + return false; + + } else if (symbol == _declSymbol) { + return true; + + } else if (symbol->line() == _declSymbol->line() && symbol->column() == _declSymbol->column()) { + if (! qstrcmp(symbol->fileName(), _declSymbol->fileName())) + return true; + + } else if (symbol->isForwardClassDeclaration() && (_declSymbol->isClass() || + _declSymbol->isForwardClassDeclaration())) { + return checkScope(symbol, _declSymbol); + + } else if (_declSymbol->isForwardClassDeclaration() && (symbol->isClass() || + symbol->isForwardClassDeclaration())) { + return checkScope(symbol, _declSymbol); + } + + return false; +} + +LookupContext FindUsages::currentContext(AST *ast) +{ + unsigned line, column; + getTokenStartPosition(ast->firstToken(), &line, &column); + Symbol *lastVisibleSymbol = _doc->findSymbolAt(line, column); + + if (lastVisibleSymbol && lastVisibleSymbol == _previousContext.symbol()) + return _previousContext; + + LookupContext ctx(lastVisibleSymbol, _exprDoc, _doc, _snapshot); + _previousContext = ctx; + return ctx; +} + +void FindUsages::ensureNameIsValid(NameAST *ast) +{ + if (ast && ! ast->name) + ast->name = _sem.check(ast, /*scope = */ 0); +} + +bool FindUsages::visit(MemInitializerAST *ast) +{ + if (ast->name && ast->name->asSimpleName() != 0) { + ensureNameIsValid(ast->name); + + SimpleNameAST *simple = ast->name->asSimpleName(); + if (identifier(simple->identifier_token) == _id) { + LookupContext context = currentContext(ast); + const QList<Symbol *> candidates = context.resolve(simple->name); + reportResult(simple->identifier_token, candidates); + } + } + accept(ast->expression); + return false; +} + +bool FindUsages::visit(PostfixExpressionAST *ast) +{ + _postfixExpressionStack.append(ast); + return true; +} + +void FindUsages::endVisit(PostfixExpressionAST *) +{ + _postfixExpressionStack.removeLast(); +} + +bool FindUsages::visit(MemberAccessAST *ast) +{ + if (ast->member_name) { + if (SimpleNameAST *simple = ast->member_name->asSimpleName()) { + if (identifier(simple->identifier_token) == _id) { + Q_ASSERT(! _postfixExpressionStack.isEmpty()); + + checkExpression(_postfixExpressionStack.last()->firstToken(), + simple->identifier_token); + + return false; + } + } + } + + return true; +} + +void FindUsages::checkExpression(unsigned startToken, unsigned endToken) +{ + const unsigned begin = tokenAt(startToken).begin(); + const unsigned end = tokenAt(endToken).end(); + + const QString expression = _source.mid(begin, end - begin); + // qDebug() << "*** check expression:" << expression; + + TypeOfExpression typeofExpression; + typeofExpression.setSnapshot(_snapshot); + + unsigned line, column; + getTokenStartPosition(startToken, &line, &column); + Symbol *lastVisibleSymbol = _doc->findSymbolAt(line, column); + + const QList<TypeOfExpression::Result> results = + typeofExpression(expression, _doc, lastVisibleSymbol, + TypeOfExpression::Preprocess); + + QList<Symbol *> candidates; + + foreach (TypeOfExpression::Result r, results) { + FullySpecifiedType ty = r.first; + Symbol *lastVisibleSymbol = r.second; + + candidates.append(lastVisibleSymbol); + } + + reportResult(endToken, candidates); +} + +bool FindUsages::visit(QualifiedNameAST *ast) +{ + for (NestedNameSpecifierAST *nested_name_specifier = ast->nested_name_specifier; + nested_name_specifier; nested_name_specifier = nested_name_specifier->next) { + + if (NameAST *class_or_namespace_name = nested_name_specifier->class_or_namespace_name) { + SimpleNameAST *simple_name = class_or_namespace_name->asSimpleName(); + + TemplateIdAST *template_id = 0; + if (! simple_name) { + template_id = class_or_namespace_name->asTemplateId(); + + if (template_id) { + for (TemplateArgumentListAST *template_arguments = template_id->template_arguments; + template_arguments; template_arguments = template_arguments->next) { + accept(template_arguments->template_argument); + } + } + } + + if (simple_name || template_id) { + const unsigned identifier_token = simple_name + ? simple_name->identifier_token + : template_id->identifier_token; + + if (identifier(identifier_token) == _id) + checkExpression(ast->firstToken(), identifier_token); + } + } + } + + if (NameAST *unqualified_name = ast->unqualified_name) { + unsigned identifier_token = 0; + + if (SimpleNameAST *simple_name = unqualified_name->asSimpleName()) + identifier_token = simple_name->identifier_token; + + else if (DestructorNameAST *dtor_name = unqualified_name->asDestructorName()) + identifier_token = dtor_name->identifier_token; + + TemplateIdAST *template_id = 0; + if (! identifier_token) { + template_id = unqualified_name->asTemplateId(); + + if (template_id) { + identifier_token = template_id->identifier_token; + + for (TemplateArgumentListAST *template_arguments = template_id->template_arguments; + template_arguments; template_arguments = template_arguments->next) { + accept(template_arguments->template_argument); + } + } + } + + if (identifier_token && identifier(identifier_token) == _id) + checkExpression(ast->firstToken(), identifier_token); + } + + return false; +} + +bool FindUsages::visit(EnumeratorAST *ast) +{ + Identifier *id = identifier(ast->identifier_token); + if (id == _id) { + LookupContext context = currentContext(ast); + const QList<Symbol *> candidates = context.resolve(control()->nameId(id)); + reportResult(ast->identifier_token, candidates); + } + + accept(ast->expression); + + return false; +} + +bool FindUsages::visit(SimpleNameAST *ast) +{ + Identifier *id = identifier(ast->identifier_token); + if (id == _id) { + LookupContext context = currentContext(ast); + const QList<Symbol *> candidates = context.resolve(ast->name); + reportResult(ast->identifier_token, candidates); + } + + return false; +} + +bool FindUsages::visit(DestructorNameAST *ast) +{ + Identifier *id = identifier(ast->identifier_token); + if (id == _id) { + LookupContext context = currentContext(ast); + const QList<Symbol *> candidates = context.resolve(ast->name); + reportResult(ast->identifier_token, candidates); + } + + return false; +} + +bool FindUsages::visit(TemplateIdAST *ast) +{ + if (_id == identifier(ast->identifier_token)) { + LookupContext context = currentContext(ast); + const QList<Symbol *> candidates = context.resolve(ast->name); + reportResult(ast->identifier_token, candidates); + } + + for (TemplateArgumentListAST *template_arguments = ast->template_arguments; + template_arguments; template_arguments = template_arguments->next) { + accept(template_arguments->template_argument); + } + + return false; +} + +bool FindUsages::visit(ParameterDeclarationAST *ast) +{ + for (SpecifierAST *spec = ast->type_specifier; spec; spec = spec->next) + accept(spec); + + if (DeclaratorAST *declarator = ast->declarator) { + for (SpecifierAST *attr = declarator->attributes; attr; attr = attr->next) + accept(attr); + + for (PtrOperatorAST *ptr_op = declarator->ptr_operators; ptr_op; ptr_op = ptr_op->next) + accept(ptr_op); + + if (! _inSimpleDeclaration) // visit the core declarator only if we are not in simple-declaration. + accept(declarator->core_declarator); + + for (PostfixDeclaratorAST *fx_op = declarator->postfix_declarators; fx_op; fx_op = fx_op->next) + accept(fx_op); + + for (SpecifierAST *spec = declarator->post_attributes; spec; spec = spec->next) + accept(spec); + + accept(declarator->initializer); + } + + accept(ast->expression); + return false; +} + +bool FindUsages::visit(ExpressionOrDeclarationStatementAST *ast) +{ + accept(ast->declaration); + return false; +} + +bool FindUsages::visit(FunctionDeclaratorAST *ast) +{ + accept(ast->parameters); + + for (SpecifierAST *spec = ast->cv_qualifier_seq; spec; spec = spec->next) + accept(spec); + + accept(ast->exception_specification); + + return false; +} + +bool FindUsages::visit(SimpleDeclarationAST *) +{ + ++_inSimpleDeclaration; + return true; +} + +void FindUsages::endVisit(SimpleDeclarationAST *) +{ --_inSimpleDeclaration; } diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h new file mode 100644 index 0000000000000000000000000000000000000000..9f82949380677777434fb57ec4a8b9e52b7ee5d2 --- /dev/null +++ b/src/libs/cplusplus/FindUsages.h @@ -0,0 +1,121 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 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 FINDUSAGES_H +#define FINDUSAGES_H + +#include "LookupContext.h" +#include "CppDocument.h" +#include "CppBindings.h" +#include "Semantic.h" + +#include <ASTVisitor.h> +#include <QtCore/QFutureInterface> + +namespace CPlusPlus { + +class CPLUSPLUS_EXPORT Usage +{ +public: + Usage() + : line(0), col(0), len(0) {} + + Usage(const QString &path, int line, const QString &lineText, int col, int len) + : path(path), line(line), lineText(lineText), col(col), len(len) {} + +public: + QString path; + int line; + QString lineText; + int col; + int len; +}; + +class CPLUSPLUS_EXPORT FindUsages: protected ASTVisitor +{ +public: + FindUsages(Document::Ptr doc, const Snapshot &snapshot, QFutureInterface<Usage> *future); + + void setGlobalNamespaceBinding(NamespaceBindingPtr globalNamespaceBinding); + + QList<int> operator()(Symbol *symbol, Identifier *id, AST *ast); + +protected: + using ASTVisitor::visit; + using ASTVisitor::endVisit; + + QString matchingLine(const Token &tk) const; + + void reportResult(unsigned tokenIndex, const QList<Symbol *> &candidates); + void reportResult(unsigned tokenIndex); + + bool checkSymbol(Symbol *symbol) const; + bool checkCandidates(const QList<Symbol *> &candidates) const; + bool checkScope(Symbol *symbol, Symbol *otherSymbol) const; + void checkExpression(unsigned startToken, unsigned endToken); + + LookupContext currentContext(AST *ast); + + void ensureNameIsValid(NameAST *ast); + + virtual bool visit(MemInitializerAST *ast); + virtual bool visit(PostfixExpressionAST *ast); + virtual void endVisit(PostfixExpressionAST *); + virtual bool visit(MemberAccessAST *ast); + virtual bool visit(QualifiedNameAST *ast); + virtual bool visit(EnumeratorAST *ast); + virtual bool visit(SimpleNameAST *ast); + virtual bool visit(DestructorNameAST *ast); + virtual bool visit(TemplateIdAST *ast); + virtual bool visit(ParameterDeclarationAST *ast); + virtual bool visit(ExpressionOrDeclarationStatementAST *ast); + virtual bool visit(FunctionDeclaratorAST *ast); + virtual bool visit(SimpleDeclarationAST *); + virtual void endVisit(SimpleDeclarationAST *); + +private: + QFutureInterface<Usage> *_future; + Identifier *_id; + Symbol *_declSymbol; + Document::Ptr _doc; + Snapshot _snapshot; + QByteArray _source; + Document::Ptr _exprDoc; + Semantic _sem; + NamespaceBindingPtr _globalNamespaceBinding; + QList<PostfixExpressionAST *> _postfixExpressionStack; + QList<QualifiedNameAST *> _qualifiedNameStack; + QList<int> _references; + LookupContext _previousContext; + int _inSimpleDeclaration; +}; + +} // end of namespace CPlusPlus + +#endif // FINDUSAGES_H diff --git a/src/libs/cplusplus/cplusplus-lib.pri b/src/libs/cplusplus/cplusplus-lib.pri index 2e50a401333ecb14bdda9d9b5a839cf8fe634b84..611fadf0ac409ec6244da5818ca2d9613c5c22ae 100644 --- a/src/libs/cplusplus/cplusplus-lib.pri +++ b/src/libs/cplusplus/cplusplus-lib.pri @@ -38,6 +38,7 @@ HEADERS += \ $$PWD/CppBindings.h \ $$PWD/ASTParent.h \ $$PWD/GenTemplateInstance.h \ + $$PWD/FindUsages.h \ $$PWD/CheckUndefinedSymbols.h \ $$PWD/PreprocessorClient.h \ $$PWD/PreprocessorEnvironment.h \ @@ -61,6 +62,7 @@ SOURCES += \ $$PWD/CppBindings.cpp \ $$PWD/ASTParent.cpp \ $$PWD/GenTemplateInstance.cpp \ + $$PWD/FindUsages.cpp \ $$PWD/CheckUndefinedSymbols.cpp \ $$PWD/PreprocessorClient.cpp \ $$PWD/PreprocessorEnvironment.cpp \ diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp index 06ae9790602dc07c6bc14437d4b00fc5606c29c7..f8eb27419dfa9ebdfc7bb32712a6619289617b3d 100644 --- a/src/plugins/cpptools/cppfindreferences.cpp +++ b/src/plugins/cpptools/cppfindreferences.cpp @@ -50,11 +50,8 @@ #include <cplusplus/CppDocument.h> #include <cplusplus/CppBindings.h> -#include <cplusplus/ExpressionUnderCursor.h> -#include <cplusplus/ResolveExpression.h> #include <cplusplus/Overview.h> -#include <cplusplus/TypeOfExpression.h> -#include <cplusplus/FastPreprocessor.h> +#include <cplusplus/FindUsages.h> #include <QtCore/QTime> #include <QtCore/QtConcurrentRun> @@ -65,438 +62,6 @@ using namespace CppTools::Internal; using namespace CPlusPlus; -namespace { - -struct Process: protected ASTVisitor -{ -public: - Process(Document::Ptr doc, const Snapshot &snapshot, - QFutureInterface<Utils::FileSearchResult> *future) - : ASTVisitor(doc->control()), - _future(future), - _doc(doc), - _snapshot(snapshot), - _source(_doc->source()), - _sem(doc->control()), - _inSimpleDeclaration(0) - { - _snapshot.insert(_doc); - } - - void setGlobalNamespaceBinding(NamespaceBindingPtr globalNamespaceBinding) - { - _globalNamespaceBinding = globalNamespaceBinding; - } - - QList<int> operator()(Symbol *symbol, Identifier *id, AST *ast) - { - _references.clear(); - _declSymbol = symbol; - _id = id; - _exprDoc = Document::create("<references>"); - accept(ast); - return _references; - } - -protected: - using ASTVisitor::visit; - - QString matchingLine(const Token &tk) const - { - const char *beg = _source.constData(); - const char *cp = beg + tk.offset; - for (; cp != beg - 1; --cp) { - if (*cp == '\n') - break; - } - - ++cp; - - const char *lineEnd = cp + 1; - for (; *lineEnd; ++lineEnd) { - if (*lineEnd == '\n') - break; - } - - const QString matchingLine = QString::fromUtf8(cp, lineEnd - cp); - return matchingLine; - - } - - void reportResult(unsigned tokenIndex, const QList<Symbol *> &candidates) - { - const bool isStrongResult = checkCandidates(candidates); - - if (isStrongResult) - reportResult(tokenIndex); - } - - void reportResult(unsigned tokenIndex) - { - const Token &tk = tokenAt(tokenIndex); - const QString lineText = matchingLine(tk); - - unsigned line, col; - getTokenStartPosition(tokenIndex, &line, &col); - - if (col) - --col; // adjust the column position. - - const int len = tk.f.length; - - if (_future) - _future->reportResult(Utils::FileSearchResult(QDir::toNativeSeparators(_doc->fileName()), - line, lineText, col, len)); - - _references.append(tokenIndex); - } - - bool checkCandidates(const QList<Symbol *> &candidates) const - { - if (Symbol *canonicalSymbol = LookupContext::canonicalSymbol(candidates, _globalNamespaceBinding.data())) { - -#if 0 - qDebug() << "*** canonical symbol:" << canonicalSymbol->fileName() - << canonicalSymbol->line() << canonicalSymbol->column() - << "candidates:" << candidates.size(); -#endif - - return isDeclSymbol(canonicalSymbol); - } - - return false; - } - - bool checkScope(Symbol *symbol, Symbol *otherSymbol) const - { - if (! (symbol && otherSymbol)) - return false; - - else if (symbol->scope() == otherSymbol->scope()) - return true; - - else if (symbol->name() && otherSymbol->name()) { - - if (! symbol->name()->isEqualTo(otherSymbol->name())) - return false; - - } else if (symbol->name() != otherSymbol->name()) { - return false; - } - - return checkScope(symbol->enclosingSymbol(), otherSymbol->enclosingSymbol()); - } - - bool isDeclSymbol(Symbol *symbol) const - { - if (! symbol) { - return false; - - } else if (symbol == _declSymbol) { - return true; - - } else if (symbol->line() == _declSymbol->line() && symbol->column() == _declSymbol->column()) { - if (! qstrcmp(symbol->fileName(), _declSymbol->fileName())) - return true; - - } else if (symbol->isForwardClassDeclaration() && (_declSymbol->isClass() || - _declSymbol->isForwardClassDeclaration())) { - return checkScope(symbol, _declSymbol); - - } else if (_declSymbol->isForwardClassDeclaration() && (symbol->isClass() || - symbol->isForwardClassDeclaration())) { - return checkScope(symbol, _declSymbol); - } - - return false; - } - - LookupContext _previousContext; - - LookupContext currentContext(AST *ast) - { - unsigned line, column; - getTokenStartPosition(ast->firstToken(), &line, &column); - Symbol *lastVisibleSymbol = _doc->findSymbolAt(line, column); - - if (lastVisibleSymbol && lastVisibleSymbol == _previousContext.symbol()) - return _previousContext; - - LookupContext ctx(lastVisibleSymbol, _exprDoc, _doc, _snapshot); - _previousContext = ctx; - return ctx; - } - - void ensureNameIsValid(NameAST *ast) - { - if (ast && ! ast->name) - ast->name = _sem.check(ast, /*scope = */ 0); - } - - virtual bool visit(MemInitializerAST *ast) - { - if (ast->name && ast->name->asSimpleName() != 0) { - ensureNameIsValid(ast->name); - - SimpleNameAST *simple = ast->name->asSimpleName(); - if (identifier(simple->identifier_token) == _id) { - LookupContext context = currentContext(ast); - const QList<Symbol *> candidates = context.resolve(simple->name); - reportResult(simple->identifier_token, candidates); - } - } - accept(ast->expression); - return false; - } - - virtual bool visit(PostfixExpressionAST *ast) - { - _postfixExpressionStack.append(ast); - return true; - } - - virtual void endVisit(PostfixExpressionAST *) - { - _postfixExpressionStack.removeLast(); - } - - virtual bool visit(MemberAccessAST *ast) - { - if (ast->member_name) { - if (SimpleNameAST *simple = ast->member_name->asSimpleName()) { - if (identifier(simple->identifier_token) == _id) { - Q_ASSERT(! _postfixExpressionStack.isEmpty()); - - checkExpression(_postfixExpressionStack.last()->firstToken(), - simple->identifier_token); - - return false; - } - } - } - - return true; - } - - void checkExpression(unsigned startToken, unsigned endToken) - { - const unsigned begin = tokenAt(startToken).begin(); - const unsigned end = tokenAt(endToken).end(); - - const QString expression = _source.mid(begin, end - begin); - // qDebug() << "*** check expression:" << expression; - - TypeOfExpression typeofExpression; - typeofExpression.setSnapshot(_snapshot); - - unsigned line, column; - getTokenStartPosition(startToken, &line, &column); - Symbol *lastVisibleSymbol = _doc->findSymbolAt(line, column); - - const QList<TypeOfExpression::Result> results = - typeofExpression(expression, _doc, lastVisibleSymbol, - TypeOfExpression::Preprocess); - - QList<Symbol *> candidates; - - foreach (TypeOfExpression::Result r, results) { - FullySpecifiedType ty = r.first; - Symbol *lastVisibleSymbol = r.second; - - candidates.append(lastVisibleSymbol); - } - - reportResult(endToken, candidates); - } - - virtual bool visit(QualifiedNameAST *ast) - { - for (NestedNameSpecifierAST *nested_name_specifier = ast->nested_name_specifier; - nested_name_specifier; nested_name_specifier = nested_name_specifier->next) { - - if (NameAST *class_or_namespace_name = nested_name_specifier->class_or_namespace_name) { - SimpleNameAST *simple_name = class_or_namespace_name->asSimpleName(); - - TemplateIdAST *template_id = 0; - if (! simple_name) { - template_id = class_or_namespace_name->asTemplateId(); - - if (template_id) { - for (TemplateArgumentListAST *template_arguments = template_id->template_arguments; - template_arguments; template_arguments = template_arguments->next) { - accept(template_arguments->template_argument); - } - } - } - - if (simple_name || template_id) { - const unsigned identifier_token = simple_name - ? simple_name->identifier_token - : template_id->identifier_token; - - if (identifier(identifier_token) == _id) - checkExpression(ast->firstToken(), identifier_token); - } - } - } - - if (NameAST *unqualified_name = ast->unqualified_name) { - unsigned identifier_token = 0; - - if (SimpleNameAST *simple_name = unqualified_name->asSimpleName()) - identifier_token = simple_name->identifier_token; - - else if (DestructorNameAST *dtor_name = unqualified_name->asDestructorName()) - identifier_token = dtor_name->identifier_token; - - TemplateIdAST *template_id = 0; - if (! identifier_token) { - template_id = unqualified_name->asTemplateId(); - - if (template_id) { - identifier_token = template_id->identifier_token; - - for (TemplateArgumentListAST *template_arguments = template_id->template_arguments; - template_arguments; template_arguments = template_arguments->next) { - accept(template_arguments->template_argument); - } - } - } - - if (identifier_token && identifier(identifier_token) == _id) - checkExpression(ast->firstToken(), identifier_token); - } - - return false; - } - - virtual bool visit(EnumeratorAST *ast) - { - Identifier *id = identifier(ast->identifier_token); - if (id == _id) { - LookupContext context = currentContext(ast); - const QList<Symbol *> candidates = context.resolve(control()->nameId(id)); - reportResult(ast->identifier_token, candidates); - } - - accept(ast->expression); - - return false; - } - - virtual bool visit(SimpleNameAST *ast) - { - Identifier *id = identifier(ast->identifier_token); - if (id == _id) { - LookupContext context = currentContext(ast); - const QList<Symbol *> candidates = context.resolve(ast->name); - reportResult(ast->identifier_token, candidates); - } - - return false; - } - - virtual bool visit(DestructorNameAST *ast) - { - Identifier *id = identifier(ast->identifier_token); - if (id == _id) { - LookupContext context = currentContext(ast); - const QList<Symbol *> candidates = context.resolve(ast->name); - reportResult(ast->identifier_token, candidates); - } - - return false; - } - - virtual bool visit(TemplateIdAST *ast) - { - if (_id == identifier(ast->identifier_token)) { - LookupContext context = currentContext(ast); - const QList<Symbol *> candidates = context.resolve(ast->name); - reportResult(ast->identifier_token, candidates); - } - - for (TemplateArgumentListAST *template_arguments = ast->template_arguments; - template_arguments; template_arguments = template_arguments->next) { - accept(template_arguments->template_argument); - } - - return false; - } - - virtual bool visit(ParameterDeclarationAST *ast) - { - for (SpecifierAST *spec = ast->type_specifier; spec; spec = spec->next) - accept(spec); - - if (DeclaratorAST *declarator = ast->declarator) { - for (SpecifierAST *attr = declarator->attributes; attr; attr = attr->next) - accept(attr); - - for (PtrOperatorAST *ptr_op = declarator->ptr_operators; ptr_op; ptr_op = ptr_op->next) - accept(ptr_op); - - if (! _inSimpleDeclaration) // visit the core declarator only if we are not in simple-declaration. - accept(declarator->core_declarator); - - for (PostfixDeclaratorAST *fx_op = declarator->postfix_declarators; fx_op; fx_op = fx_op->next) - accept(fx_op); - - for (SpecifierAST *spec = declarator->post_attributes; spec; spec = spec->next) - accept(spec); - - accept(declarator->initializer); - } - - accept(ast->expression); - return false; - } - - virtual bool visit(ExpressionOrDeclarationStatementAST *ast) - { - accept(ast->declaration); - return false; - } - - virtual bool visit(FunctionDeclaratorAST *ast) - { - accept(ast->parameters); - - for (SpecifierAST *spec = ast->cv_qualifier_seq; spec; spec = spec->next) - accept(spec); - - accept(ast->exception_specification); - - return false; - } - - virtual bool visit(SimpleDeclarationAST *) - { - ++_inSimpleDeclaration; - return true; - } - - virtual void endVisit(SimpleDeclarationAST *) - { --_inSimpleDeclaration; } - -private: - QFutureInterface<Utils::FileSearchResult> *_future; - Identifier *_id; // ### remove me - Symbol *_declSymbol; - Document::Ptr _doc; - Snapshot _snapshot; - QByteArray _source; - Document::Ptr _exprDoc; - Semantic _sem; - NamespaceBindingPtr _globalNamespaceBinding; - QList<PostfixExpressionAST *> _postfixExpressionStack; - QList<QualifiedNameAST *> _qualifiedNameStack; - QList<int> _references; - int _inSimpleDeclaration; -}; - -} // end of anonymous namespace - CppFindReferences::CppFindReferences(CppTools::CppModelManagerInterface *modelManager) : _modelManager(modelManager), _resultWindow(ExtensionSystem::PluginManager::instance()->getObject<Find::SearchResultWindow>()) @@ -526,14 +91,14 @@ QList<int> CppFindReferences::references(Symbol *symbol, TranslationUnit *translationUnit = doc->translationUnit(); Q_ASSERT(translationUnit != 0); - Process process(doc, snapshot, /*future = */ 0); + FindUsages process(doc, snapshot, /*future = */ 0); process.setGlobalNamespaceBinding(bind(doc, snapshot)); references = process(symbol, id, translationUnit->ast()); return references; } -static void find_helper(QFutureInterface<Utils::FileSearchResult> &future, +static void find_helper(QFutureInterface<Usage> &future, const QMap<QString, QString> wl, Snapshot snapshot, Symbol *symbol) @@ -613,7 +178,7 @@ static void find_helper(QFutureInterface<Utils::FileSearchResult> &future, tm.start(); - Process process(doc, snapshot, &future); + FindUsages process(doc, snapshot, &future); process.setGlobalNamespaceBinding(bind(doc, snapshot)); TranslationUnit *unit = doc->translationUnit(); @@ -666,7 +231,7 @@ void CppFindReferences::findAll_helper(Symbol *symbol) Core::ProgressManager *progressManager = Core::ICore::instance()->progressManager(); - QFuture<Utils::FileSearchResult> result = QtConcurrent::run(&find_helper, wl, snapshot, symbol); + QFuture<Usage> result = QtConcurrent::run(&find_helper, wl, snapshot, symbol); m_watcher.setFuture(result); Core::FutureProgress *progress = progressManager->addTask(result, tr("Searching..."), @@ -759,12 +324,12 @@ void CppFindReferences::onReplaceButtonClicked(const QString &text, void CppFindReferences::displayResult(int index) { - Utils::FileSearchResult result = m_watcher.future().resultAt(index); - _resultWindow->addResult(result.fileName, - result.lineNumber, - result.matchingLine, - result.matchStart, - result.matchLength); + Usage result = m_watcher.future().resultAt(index); + _resultWindow->addResult(result.path, + result.line, + result.lineText, + result.col, + result.len); } void CppFindReferences::searchFinished() diff --git a/src/plugins/cpptools/cppfindreferences.h b/src/plugins/cpptools/cppfindreferences.h index cbddf8fb5c3458d448ca13a908173be8d8e11338..5cdfbdcecb3912f6d957e01c750232a77182607c 100644 --- a/src/plugins/cpptools/cppfindreferences.h +++ b/src/plugins/cpptools/cppfindreferences.h @@ -42,6 +42,10 @@ namespace Find { struct SearchResultItem; } // end of namespace Find +namespace CPlusPlus { + class Usage; +} // end of namespace CPlusPlus + namespace CppTools { class CppModelManagerInterface; @@ -78,7 +82,7 @@ private: private: QPointer<CppModelManagerInterface> _modelManager; Find::SearchResultWindow *_resultWindow; - QFutureWatcher<Utils::FileSearchResult> m_watcher; + QFutureWatcher<CPlusPlus::Usage> m_watcher; }; } // end of namespace Internal