forked from qt-creator/qt-creator
C++: fix functionAt(), moved it, and added test.
Thanks to Jesper K. Pedersen for the fix! Change-Id: Ie49c3352e26a9632b1500596b00d559bfe932dff Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
committed by
Nikolai Kosjar
parent
6a4a926622
commit
ca291fbc7b
@@ -464,6 +464,57 @@ void Document::setGlobalNamespace(Namespace *globalNamespace)
|
||||
_globalNamespace = globalNamespace;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Extract the function name including scope at the given position.
|
||||
*
|
||||
* Note that a function (scope) starts at the name of that function, not at the return type. The
|
||||
* implication is that this method will return an empty string when the line/column is on the
|
||||
* return type.
|
||||
*
|
||||
* \param line the line number, starting with line 1
|
||||
* \param column the column number, starting with column 1
|
||||
*/
|
||||
QString Document::functionAt(int line, int column) const
|
||||
{
|
||||
if (line < 1 || column < 1)
|
||||
return QString();
|
||||
|
||||
CPlusPlus::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;
|
||||
if (symbol->isScope())
|
||||
scope = symbol->asScope();
|
||||
else
|
||||
scope = symbol->enclosingScope();
|
||||
|
||||
while (scope && !scope->isFunction() )
|
||||
scope = scope->enclosingScope();
|
||||
|
||||
if (!scope)
|
||||
return QString();
|
||||
|
||||
// We found the function scope, extract its name.
|
||||
const Overview o;
|
||||
QString rc = o.prettyName(scope->name());
|
||||
|
||||
// Prepend namespace "Foo::Foo::foo()" up to empty root namespace
|
||||
for (const Symbol *owner = scope->enclosingNamespace();
|
||||
owner; owner = owner->enclosingNamespace()) {
|
||||
const QString name = o.prettyName(owner->name());
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
} else {
|
||||
rc.prepend(QLatin1String("::"));
|
||||
rc.prepend(name);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
Scope *Document::scopeAt(unsigned line, unsigned column)
|
||||
{
|
||||
FindScopeAt findScopeAt(_translationUnit, line, column);
|
||||
|
@@ -99,6 +99,7 @@ public:
|
||||
QList<Macro> definedMacros() const
|
||||
{ return _definedMacros; }
|
||||
|
||||
QString functionAt(int line, int column) const;
|
||||
Symbol *lastVisibleSymbolAt(unsigned line, unsigned column = 0) const;
|
||||
Scope *scopeAt(unsigned line, unsigned column = 0);
|
||||
|
||||
|
@@ -55,29 +55,13 @@ QString AbstractEditorSupport::functionAt(const CppModelManagerInterface *modelM
|
||||
const QString &fileName,
|
||||
int line, int column)
|
||||
{
|
||||
const CPlusPlus::Snapshot snapshot = modelManager->snapshot();
|
||||
const CPlusPlus::Document::Ptr document = snapshot.document(fileName);
|
||||
if (!document)
|
||||
if (!modelManager)
|
||||
return QString();
|
||||
if (const CPlusPlus::Symbol *symbol = document->lastVisibleSymbolAt(line, column))
|
||||
if (const CPlusPlus::Scope *scope = symbol->enclosingScope())
|
||||
if (const CPlusPlus::Scope *functionScope = scope->enclosingFunction())
|
||||
if (const CPlusPlus::Symbol *function = functionScope) {
|
||||
const CPlusPlus::Overview o;
|
||||
QString rc = o.prettyName(function->name());
|
||||
// Prepend namespace "Foo::Foo::foo()" up to empty root namespace
|
||||
for (const CPlusPlus::Symbol *owner = function->enclosingNamespace();
|
||||
owner; owner = owner->enclosingNamespace()) {
|
||||
const QString name = o.prettyName(owner->name());
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
} else {
|
||||
rc.prepend(QLatin1String("::"));
|
||||
rc.prepend(name);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
const CPlusPlus::Snapshot snapshot = modelManager->snapshot();
|
||||
if (const CPlusPlus::Document::Ptr document = snapshot.document(fileName))
|
||||
return document->functionAt(line, column);
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
@@ -87,6 +87,7 @@ class tst_Lookup: public QObject
|
||||
|
||||
private Q_SLOTS:
|
||||
void base_class_defined_1();
|
||||
void document_functionAt_1();
|
||||
|
||||
// Objective-C
|
||||
void simple_class_1();
|
||||
@@ -153,6 +154,30 @@ void tst_Lookup::base_class_defined_1()
|
||||
QVERIFY(classToAST.value(derivedClass) != 0);
|
||||
}
|
||||
|
||||
void tst_Lookup::document_functionAt_1()
|
||||
{
|
||||
const QByteArray source = "\n"
|
||||
"void Foo::Bar() {\n" // line 1
|
||||
" \n" // line 2
|
||||
" for (int i=0; i < 10; ++i) {\n"
|
||||
" \n" // line 4
|
||||
" }\n"
|
||||
"}\n"; // line 7
|
||||
|
||||
Document::Ptr doc = Document::create("document_functionAt_1");
|
||||
doc->setUtf8Source(source);
|
||||
doc->parse();
|
||||
doc->check();
|
||||
|
||||
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||
QCOMPARE(doc->functionAt(1, 2), QString());
|
||||
QCOMPARE(doc->functionAt(1, 11), QString(QLatin1String("Foo::Bar")));
|
||||
QCOMPARE(doc->functionAt(2, 2), QString(QLatin1String("Foo::Bar")));
|
||||
QCOMPARE(doc->functionAt(3, 10), QString(QLatin1String("Foo::Bar")));
|
||||
QCOMPARE(doc->functionAt(4, 3), QString(QLatin1String("Foo::Bar")));
|
||||
QCOMPARE(doc->functionAt(6, 1), QString(QLatin1String("Foo::Bar")));
|
||||
}
|
||||
|
||||
void tst_Lookup::simple_class_1()
|
||||
{
|
||||
const QByteArray source = "\n"
|
||||
|
Reference in New Issue
Block a user