diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index c45f86834c2bc75a20c45bdbde869fa7b06faff8..8702f9e4960ab89e047ff55dbf8179bba58d5094 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -861,11 +861,30 @@ CPlusPlus::Symbol *CPPEditor::findCanonicalSymbol(const QTextCursor &cursor, return canonicalSymbol; } +const Macro *CPPEditor::findCanonicalMacro(const QTextCursor &cursor, + Document::Ptr doc) const +{ + if (! doc) + return 0; + + int line, col; + convertPosition(cursor.position(), &line, &col); + + if (const Macro *macro = doc->findMacroDefinitionAt(line)) + return macro; + + if (const Document::MacroUse *use = doc->findMacroUseAt(cursor.position())) + return &use->macro(); + + return 0; +} void CPPEditor::findUsages() { if (Symbol *canonicalSymbol = markSymbols()) { m_modelManager->findUsages(canonicalSymbol); + } else if (const Macro *macro = findCanonicalMacro(textCursor(), m_lastSemanticInfo.doc)) { + m_modelManager->findMacroUsages(*macro); } } diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index b7ac5512cf657a3a604f1e8aca40c0510ca2c870..38f14c141a919df23f8cdb66e73bd471f3b194f8 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -227,6 +227,8 @@ protected: CPlusPlus::Symbol *findCanonicalSymbol(const QTextCursor &cursor, CPlusPlus::Document::Ptr doc, const CPlusPlus::Snapshot &snapshot) const; + const CPlusPlus::Macro *findCanonicalMacro(const QTextCursor &cursor, + CPlusPlus::Document::Ptr doc) const; private Q_SLOTS: void updateFileName(); diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp index 60efaf7784ad8d773dc0c053261b2afb80330a6b..699e7b72c3912cd3a1aee9ab77575ac07aaf844e 100644 --- a/src/plugins/cpptools/cppfindreferences.cpp +++ b/src/plugins/cpptools/cppfindreferences.cpp @@ -65,6 +65,20 @@ using namespace CppTools::Internal; using namespace CPlusPlus; +static QString getSource(const QString &fileName, + const CppTools::CppModelManagerInterface::WorkingCopy &workingCopy) +{ + if (workingCopy.contains(fileName)) { + return workingCopy.source(fileName); + } else { + QFile file(fileName); + if (! file.open(QFile::ReadOnly)) + return QString(); + + return QTextStream(&file).readAll(); // ### FIXME + } +} + namespace { class ProcessFile: public std::unary_function<QString, QList<Usage> > @@ -91,18 +105,8 @@ public: return usages; // skip this document, it's not using symbolId. } - QByteArray source; - - if (workingCopy.contains(fileName)) - source = snapshot.preprocessedCode(workingCopy.source(fileName), fileName); - else { - QFile file(fileName); - if (! file.open(QFile::ReadOnly)) - return usages; - - const QString contents = QTextStream(&file).readAll(); // ### FIXME - source = snapshot.preprocessedCode(contents, fileName); - } + QByteArray source = snapshot.preprocessedCode( + getSource(fileName, workingCopy), fileName); Document::Ptr doc = snapshot.documentFromSource(source, fileName); doc->tokenize(); @@ -294,3 +298,123 @@ void CppFindReferences::openEditor(const Find::SearchResultItem &item) TextEditor::BaseTextEditor::openEditorAt(item.fileName, item.lineNumber, item.searchTermStart); } + +namespace { + +class FindMacroUsesInFile: public std::unary_function<QString, QList<Usage> > +{ + const CppTools::CppModelManagerInterface::WorkingCopy workingCopy; + const Snapshot snapshot; + const Macro ¯o; + +public: + FindMacroUsesInFile(const CppTools::CppModelManagerInterface::WorkingCopy &workingCopy, + const Snapshot snapshot, + const Macro ¯o) + : workingCopy(workingCopy), snapshot(snapshot), macro(macro) + { } + + QList<Usage> operator()(const QString &fileName) + { + QList<Usage> usages; + + const Document::Ptr &doc = snapshot.document(fileName); + QByteArray source; + + foreach (const Document::MacroUse &use, doc->macroUses()) { + const Macro &useMacro = use.macro(); + if (useMacro.line() == macro.line() + && useMacro.fileName() == macro.fileName()) + { + if (source.isEmpty()) + source = getSource(fileName, workingCopy).toLatin1(); // ### FIXME: Encoding? + + unsigned lineStart; + const QString &lineSource = matchingLine(use.begin(), source, &lineStart); + usages.append(Usage(fileName, lineSource, use.beginLine(), + use.begin() - lineStart, use.length())); + } + } + + return usages; + } + + // ### FIXME: Pretty close to FindUsages::matchingLine. + static QString matchingLine(unsigned position, const QByteArray &source, + unsigned *lineStart = 0) + { + const char *beg = source.constData(); + const char *start = beg + position; + for (; start != beg - 1; --start) { + if (*start == '\n') + break; + } + + ++start; + + const char *end = start + 1; + for (; *end; ++end) { + if (*end == '\n') + break; + } + + if (lineStart) + *lineStart = start - beg; + + // ### FIXME: Encoding? + const QString matchingLine = QString::fromUtf8(start, end - start); + return matchingLine; + } +}; + +} // end of anonymous namespace + +static void findMacroUses_helper(QFutureInterface<Usage> &future, + const CppTools::CppModelManagerInterface::WorkingCopy workingCopy, + const Snapshot snapshot, + const Macro macro) +{ + const QString& sourceFile = macro.fileName(); + QStringList files(sourceFile); + files += snapshot.filesDependingOn(sourceFile); + files.removeDuplicates(); + + future.setProgressRange(0, files.size()); + + FindMacroUsesInFile process(workingCopy, snapshot, macro); + UpdateUI reduce(&future); + QtConcurrent::blockingMappedReduced<QList<Usage> > (files, process, reduce); + + future.setProgressValue(files.size()); +} + +void CppFindReferences::findMacroUses(const Macro ¯o) +{ + Find::SearchResult *search = _resultWindow->startNewSearch(Find::SearchResultWindow::SearchOnly); + + _resultWindow->popup(true); + + connect(search, SIGNAL(activated(Find::SearchResultItem)), + this, SLOT(openEditor(Find::SearchResultItem))); + + const Snapshot snapshot = _modelManager->snapshot(); + const CppTools::CppModelManagerInterface::WorkingCopy workingCopy = _modelManager->workingCopy(); + + // add the macro definition itself + { + // ### FIXME: Encoding? + const QByteArray &source = getSource(macro.fileName(), workingCopy).toLatin1(); + _resultWindow->addResult(macro.fileName(), macro.line(), + source.mid(macro.offset(), macro.length()), 0, macro.length()); + } + + QFuture<Usage> result; + result = QtConcurrent::run(&findMacroUses_helper, workingCopy, snapshot, macro); + m_watcher.setFuture(result); + + Core::ProgressManager *progressManager = Core::ICore::instance()->progressManager(); + Core::FutureProgress *progress = progressManager->addTask(result, tr("Searching..."), + CppTools::Constants::TASK_SEARCH); + connect(progress, SIGNAL(clicked()), _resultWindow, SLOT(popup())); +} + diff --git a/src/plugins/cpptools/cppfindreferences.h b/src/plugins/cpptools/cppfindreferences.h index 5425e4988d626c00a74dcbc48df53bd96ddff9f0..a97810389855592b3ea27ee8f73ca3bd6984a60c 100644 --- a/src/plugins/cpptools/cppfindreferences.h +++ b/src/plugins/cpptools/cppfindreferences.h @@ -67,6 +67,8 @@ public: void findUsages(CPlusPlus::Symbol *symbol); void renameUsages(CPlusPlus::Symbol *symbol); + void findMacroUses(const CPlusPlus::Macro ¯o); + private Q_SLOTS: void displayResults(int first, int last); void searchFinished(); diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index a31ed64df5c65d57d842cee3919200554c979194..6f7245072f21ee02772f7ef58f67ef6399d6b53a 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -792,6 +792,11 @@ void CppModelManager::renameUsages(CPlusPlus::Symbol *symbol) m_findReferences->renameUsages(symbol); } +void CppModelManager::findMacroUsages(const CPlusPlus::Macro ¯o) +{ + m_findReferences->findMacroUses(macro); +} + CppModelManager::WorkingCopy CppModelManager::buildWorkingCopyList() { WorkingCopy workingCopy; diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index f5f445d605198f7cdfc519a0fe4452e4a3eb3013..bd5b7c0768f240b3aa82e651aa1abecd3633adeb 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -108,6 +108,8 @@ public: virtual void findUsages(CPlusPlus::Symbol *symbol); virtual void renameUsages(CPlusPlus::Symbol *symbol); + virtual void findMacroUsages(const CPlusPlus::Macro ¯o); + void setHeaderSuffixes(const QStringList &suffixes) { m_headerSuffixes = suffixes; } diff --git a/src/plugins/cpptools/cppmodelmanagerinterface.h b/src/plugins/cpptools/cppmodelmanagerinterface.h index 8db6b02b717e9107f1f64f35bf33b95dc58356b8..9b9e3dd3cd553945193d8c219d3f2a431e09f8e4 100644 --- a/src/plugins/cpptools/cppmodelmanagerinterface.h +++ b/src/plugins/cpptools/cppmodelmanagerinterface.h @@ -123,6 +123,8 @@ public: virtual void renameUsages(CPlusPlus::Symbol *symbol) = 0; virtual void findUsages(CPlusPlus::Symbol *symbol) = 0; + virtual void findMacroUsages(const CPlusPlus::Macro ¯o) = 0; + public Q_SLOTS: void updateModifiedSourceFiles(); virtual void updateSourceFiles(const QStringList &sourceFiles) = 0;