CppEditor: Fix looking up containing function for search result

- Move look-up to CplusPlus::FindUsages, where we are guaranteed that
  we actually have the document source.
- Use the same straightforward algorithm as with clangd.
- Undo the changes to CppDocument::functionAt(), which broke
  the autotest.
Amends 6f7e7980d2.

Change-Id: I008d05ba41a3b63b71e3131d7021e0d4e7d0641f
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Christian Kandeler
2022-06-10 10:47:38 +02:00
parent 737877984d
commit e128c8cbde
4 changed files with 37 additions and 118 deletions

View File

@@ -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();

View File

@@ -142,11 +142,30 @@ void FindUsages::reportResult(unsigned tokenIndex, const QList<LookupItem> &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<AST *> 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:

View File

@@ -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<LookupItem> &candidates);
Usage::Type getType(int line, int column, int tokenIndex);
QString getContainingFunction(int line, int column);
bool checkCandidates(const QList<LookupItem> &candidates) const;
void checkExpression(unsigned startToken, unsigned endToken, Scope *scope = nullptr);