From 9a2114338432cfc883b29f514daa847205184833 Mon Sep 17 00:00:00 2001 From: Roberto Raggi <roberto.raggi@nokia.com> Date: Wed, 30 Sep 2009 17:15:31 +0200 Subject: [PATCH] Implemented a simple(fast?) strategy to resolve macro references. --- src/libs/cplusplus/FastPreprocessor.cpp | 62 ++++++++++++++++++++++ src/libs/cplusplus/FastPreprocessor.h | 19 +++++++ src/plugins/cppeditor/cppeditor.cpp | 9 +++- src/plugins/cpptools/cppfindreferences.cpp | 12 ++++- src/shared/cplusplus/Parser.cpp | 4 ++ 5 files changed, 103 insertions(+), 3 deletions(-) diff --git a/src/libs/cplusplus/FastPreprocessor.cpp b/src/libs/cplusplus/FastPreprocessor.cpp index a0ad81521e0..1f5838f7a69 100644 --- a/src/libs/cplusplus/FastPreprocessor.cpp +++ b/src/libs/cplusplus/FastPreprocessor.cpp @@ -28,9 +28,71 @@ **************************************************************************/ #include "FastPreprocessor.h" +#include <Literals.h> +#include <TranslationUnit.h> using namespace CPlusPlus; +FastMacroResolver::FastMacroResolver(const Snapshot &snapshot) + : _snapshot(snapshot) +{ } + +bool FastMacroResolver::isMacro(TranslationUnit *unit, unsigned tokenIndex) const +{ + const Token &tk = unit->tokenAt(tokenIndex); + if (tk.isNot(T_IDENTIFIER)) + return false; + + Identifier *id = tk.identifier; + const QByteArray macroName = QByteArray::fromRawData(id->chars(), id->size()); + const QString fileName = QString::fromUtf8(unit->fileName(), unit->fileNameLength()); + + bool done = false; + QSet<QString> processed; + + if (isMacro_helper(macroName, fileName, &processed, &done)) + return true; + + return false; +} + +bool FastMacroResolver::isMacro_helper(const QByteArray ¯oName, + const QString &fileName, + QSet<QString> *processed, + bool *done) const +{ + if (processed->contains(fileName)) + return false; + + processed->insert(fileName); + + if (Document::Ptr doc = _snapshot.value(fileName)) { + const QList<Macro> definedMacros = doc->definedMacros(); + + for (int i = definedMacros.size() - 1; i != -1; --i) { + const Macro ¯o = definedMacros.at(i); + + if (macro.name() == macroName) { // ### handle line numbers. + if (macro.isHidden()) { + *done = true; + return false; + } + + return true; + } + } + + foreach (const Document::Include &incl, doc->includes()) { + if (isMacro_helper(macroName, incl.fileName(), processed, done)) + return true; + else if (*done) + return false; + } + } + + return false; +} + FastPreprocessor::FastPreprocessor(const Snapshot &snapshot) : _snapshot(snapshot), _preproc(this, &_env) diff --git a/src/libs/cplusplus/FastPreprocessor.h b/src/libs/cplusplus/FastPreprocessor.h index 36f3685fc13..4db16643d89 100644 --- a/src/libs/cplusplus/FastPreprocessor.h +++ b/src/libs/cplusplus/FastPreprocessor.h @@ -34,11 +34,30 @@ #include "CppDocument.h" #include "pp.h" +#include <Control.h> + #include <QtCore/QSet> #include <QtCore/QString> namespace CPlusPlus { +class CPLUSPLUS_EXPORT FastMacroResolver: public MacroResolver +{ +public: + FastMacroResolver(const Snapshot &snapshot); + + virtual bool isMacro(TranslationUnit *unit, unsigned tokenIndex) const; + +private: + bool isMacro_helper(const QByteArray ¯oName, + const QString &fileName, + QSet<QString> *processed, + bool *done) const; + +private: + Snapshot _snapshot; +}; + class CPLUSPLUS_EXPORT FastPreprocessor: public Client { Environment _env; diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 9771328c5bb..9a3022c577c 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -57,6 +57,8 @@ #include <cplusplus/TypeOfExpression.h> #include <cplusplus/MatchingText.h> #include <cplusplus/BackwardsScanner.h> +#include <cplusplus/FastPreprocessor.h> + #include <cpptools/cppmodelmanagerinterface.h> #include <coreplugin/icore.h> @@ -2064,10 +2066,13 @@ SemanticInfo SemanticHighlighter::semanticInfo(const Source &source) if (!doc) { const QByteArray preprocessedCode = source.snapshot.preprocessedCode(source.code, source.fileName); + snapshot = source.snapshot; doc = source.snapshot.documentFromSource(preprocessedCode, source.fileName); - doc->check(); - snapshot = source.snapshot; + FastMacroResolver fastMacroResolver(snapshot); + doc->control()->setMacroResolver(&fastMacroResolver); + doc->check(); + doc->control()->setMacroResolver(0); } Control *control = doc->control(); diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp index bbee65f767c..ad9642f8bcb 100644 --- a/src/plugins/cpptools/cppfindreferences.cpp +++ b/src/plugins/cpptools/cppfindreferences.cpp @@ -52,6 +52,7 @@ #include <cplusplus/ResolveExpression.h> #include <cplusplus/Overview.h> #include <cplusplus/TypeOfExpression.h> +#include <cplusplus/FastPreprocessor.h> #include <QtCore/QTime> #include <QtCore/QtConcurrentRun> @@ -425,6 +426,8 @@ static void find_helper(QFutureInterface<Core::Utils::FileSearchResult> &future, future.setProgressRange(0, files.size()); + FastMacroResolver fastMacroResolver(snapshot); + for (int i = 0; i < files.size(); ++i) { const QString &fileName = files.at(i); future.setProgressValueAndText(i, QFileInfo(fileName).fileName()); @@ -456,8 +459,15 @@ static void find_helper(QFutureInterface<Core::Utils::FileSearchResult> &future, Control *control = doc->control(); if (Identifier *id = control->findIdentifier(symbolId->chars(), symbolId->size())) { - doc->check(); TranslationUnit *unit = doc->translationUnit(); + Control *control = doc->control(); + + control->setMacroResolver(&fastMacroResolver); + doc->parse(); + control->setMacroResolver(0); + + doc->check(); + Process process(doc, snapshot, &future); process(symbol, id, unit->ast()); } diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index 86f805b054a..45905829fc1 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -2561,6 +2561,10 @@ bool Parser::parseBuiltinTypeSpecifier(SpecifierAST *&node) bool Parser::parseSimpleDeclaration(DeclarationAST *&node, bool acceptStructDeclarator) { + if (LA() == T_IDENTIFIER && isMacro(cursor())) { + // printf("***** found macro reference `%s'\n", tok().identifier->chars()); + } + unsigned qt_invokable_token = 0; if (acceptStructDeclarator && (LA() == T_Q_SIGNAL || LA() == T_Q_SLOT)) qt_invokable_token = consumeToken(); -- GitLab