diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index 60144b23204..90660f2b554 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -96,86 +96,6 @@ protected: } }; -class ContainingFunctionAt: protected SymbolVisitor -{ - TranslationUnit *translationUnit; - Symbol *root; - int line; - int column; - Symbol *functionSymbol; - bool foundFunction; - bool foundBlock; - - bool scopeContains(Scope* scope, int line, int column){ - if (!scope) - return false; - - int scopeStartLine{-1}, scopeStartColumn{-1}, scopeEndLine{-1}, scopeEndColumn{-1}; - translationUnit->getPosition(scope->startOffset(), &scopeStartLine, &scopeStartColumn); - translationUnit->getPosition(scope->endOffset(), &scopeEndLine, &scopeEndColumn); - - if (line < scopeStartLine || line > scopeEndLine) - return false; - - if (line > scopeStartLine && line < scopeEndLine) - return true; - - if (scopeStartLine == line && column >= scopeStartColumn) - return true; - - if (scopeEndLine == line && column <= scopeEndColumn) - return true; - - return false; - } - -public: - ContainingFunctionAt(TranslationUnit *unit, Symbol *root) - : translationUnit(unit), root(root), line(0), column(0), functionSymbol(nullptr) - , foundFunction(false), foundBlock(false) {} - - Symbol *operator()(int line, int column) - { - this->line = line; - this->column = column; - this->functionSymbol = nullptr; - accept(root); - - return foundBlock ? functionSymbol : nullptr; - } - -protected: - bool preVisit(Symbol *s) final - { - if (foundBlock) - return false; - - if (foundFunction) { - auto block = s->asBlock(); - if (!block) - return true; - - if (scopeContains(block->asScope(), line, column)) { - foundBlock = true; - return false; - } - return true; - } - - auto asFunction = s->asFunction(); - if (asFunction) { - if (s->line() < line || (s->line() == line && s->column() <= column)) { - foundFunction = scopeContains(s->asScope(), line, column); - if (foundFunction) - functionSymbol = asFunction; - } - } - - return true; - } -}; - - class FindScopeAt: protected SymbolVisitor { TranslationUnit *_unit; @@ -592,11 +512,19 @@ QString Document::functionAt(int line, int column, int *lineOpeningDeclaratorPar if (line < 1 || column < 1) return QString(); - Symbol *symbol = ContainingFunctionAt{translationUnit(), globalNamespace()}(line, column); + Symbol *symbol = lastVisibleSymbolAt(line, column); if (!symbol) return QString(); + // Find the enclosing function scope (which might be several levels up, or we might be standing + // on it) Scope *scope = symbol->asScope(); + if (!scope) + scope = symbol->enclosingScope(); + + while (scope && !scope->isFunction() ) + scope = scope->enclosingScope(); + if (!scope) return QString(); diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp index df3f6f89f95..c82bbbf1fca 100644 --- a/src/libs/cplusplus/FindUsages.cpp +++ b/src/libs/cplusplus/FindUsages.cpp @@ -142,11 +142,30 @@ void FindUsages::reportResult(unsigned tokenIndex, const QList &cand const int len = tk.utf16chars(); const Usage u(Utils::FilePath::fromString(_doc->fileName()), lineText, - getType(line, col, tokenIndex), line, col - 1, len); + getContainingFunction(line, col), getType(line, col, tokenIndex), + line, col - 1, len); _usages.append(u); _references.append(tokenIndex); } +QString FindUsages::getContainingFunction(int line, int column) +{ + const QList astPath = ASTPath(_doc)(line, column); + bool hasBlock = false; + for (auto it = astPath.crbegin(); it != astPath.crend(); ++it) { + if (!hasBlock && (*it)->asCompoundStatement()) + hasBlock = true; + if (const auto func = (*it)->asFunctionDefinition()) { + if (!hasBlock) + return {}; + if (!func->symbol) + return {}; + return Overview().prettyName(func->symbol->name()); + } + } + return {}; +} + class FindUsages::GetUsageType { public: diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h index 87d1cbaef52..1210a745dae 100644 --- a/src/libs/cplusplus/FindUsages.h +++ b/src/libs/cplusplus/FindUsages.h @@ -42,11 +42,14 @@ public: enum class Type { Declaration, Initialization, Read, Write, WritableRef, Other }; Usage() = default; - Usage(const Utils::FilePath &path, const QString &lineText, Type t, int line, int col, int len) - : path(path), lineText(lineText), type(t), line(line), col(col), len(len) {} + Usage(const Utils::FilePath &path, const QString &lineText, const QString &func, Type t, + int line, int col, int len) + : path(path), lineText(lineText), containingFunction(func), type(t), + line(line), col(col), len(len) {} Utils::FilePath path; QString lineText; + QString containingFunction; Type type = Type::Other; int line = 0; int col = 0; @@ -75,6 +78,7 @@ protected: void reportResult(unsigned tokenIndex, const Name *name, Scope *scope = nullptr); void reportResult(unsigned tokenIndex, const QList &candidates); Usage::Type getType(int line, int column, int tokenIndex); + QString getContainingFunction(int line, int column); bool checkCandidates(const QList &candidates) const; void checkExpression(unsigned startToken, unsigned endToken, Scope *scope = nullptr); diff --git a/src/plugins/cppeditor/cppfindreferences.cpp b/src/plugins/cppeditor/cppfindreferences.cpp index b5e88f1ccd7..44f40505d16 100644 --- a/src/plugins/cppeditor/cppfindreferences.cpp +++ b/src/plugins/cppeditor/cppfindreferences.cpp @@ -632,25 +632,6 @@ CPlusPlus::Symbol *CppFindReferences::findSymbol(const CppFindReferencesParamete return nullptr; } -Utils::optional getContainingFunctionName(const Utils::FilePath &fileName, - int line, - int column) -{ - const CPlusPlus::Snapshot snapshot = CppModelManager::instance()->snapshot(); - auto document = snapshot.document(fileName); - - // context properties need lookup inside function scope, and thus require a full check - CPlusPlus::Document::Ptr localDoc = document; - if (document->checkMode() != CPlusPlus::Document::FullCheck) { - localDoc = snapshot.documentFromSource(document->utf8Source(), document->fileName()); - localDoc->check(); - } - - auto funcName = localDoc->functionAt(line, column); - - return funcName.size() ? Utils::make_optional(funcName) : Utils::nullopt; -} - static void displayResults(SearchResult *search, QFutureWatcher *watcher, int first, @@ -665,24 +646,11 @@ static void displayResults(SearchResult *search, item.setMainRange(result.line, result.col, result.len); item.setLineText(result.lineText); item.setUserData(int(result.type)); + item.setContainingFunctionName(result.containingFunction); item.setStyle(colorStyleForUsageType(result.type)); item.setUseTextEditorFont(true); if (search->supportsReplace()) item.setSelectForReplacement(SessionManager::projectForFile(result.path)); - - // In case we're looking for a function, we need to look at the symbol near the end. This - // is needed to avoid following corner-cases: - // 1) if we're looking at the beginning of the function declaration, we can get the - // declaration of the previous function - // 2) if we're looking somewhere at the middle of the function declaration, we can still - // get the declaration of the previous function if the cursor is located at the - // namespace declaration, i.e. CppReference>|addResult(item); if (parameters.prettySymbolName.isEmpty()) @@ -777,7 +745,7 @@ restart_search: if (macro.name() == useMacro.name()) { unsigned column; const QString &lineSource = matchingLine(use.bytesBegin(), source, &column); - usages.append(CPlusPlus::Usage(fileName, lineSource, + usages.append(CPlusPlus::Usage(fileName, lineSource, {}, CPlusPlus::Usage::Type::Other, use.beginLine(), column, useMacro.nameToQString().size())); }