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;
|
_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)
|
Scope *Document::scopeAt(unsigned line, unsigned column)
|
||||||
{
|
{
|
||||||
FindScopeAt findScopeAt(_translationUnit, line, column);
|
FindScopeAt findScopeAt(_translationUnit, line, column);
|
||||||
|
@@ -99,6 +99,7 @@ public:
|
|||||||
QList<Macro> definedMacros() const
|
QList<Macro> definedMacros() const
|
||||||
{ return _definedMacros; }
|
{ return _definedMacros; }
|
||||||
|
|
||||||
|
QString functionAt(int line, int column) const;
|
||||||
Symbol *lastVisibleSymbolAt(unsigned line, unsigned column = 0) const;
|
Symbol *lastVisibleSymbolAt(unsigned line, unsigned column = 0) const;
|
||||||
Scope *scopeAt(unsigned line, unsigned column = 0);
|
Scope *scopeAt(unsigned line, unsigned column = 0);
|
||||||
|
|
||||||
|
@@ -55,29 +55,13 @@ QString AbstractEditorSupport::functionAt(const CppModelManagerInterface *modelM
|
|||||||
const QString &fileName,
|
const QString &fileName,
|
||||||
int line, int column)
|
int line, int column)
|
||||||
{
|
{
|
||||||
const CPlusPlus::Snapshot snapshot = modelManager->snapshot();
|
if (!modelManager)
|
||||||
const CPlusPlus::Document::Ptr document = snapshot.document(fileName);
|
|
||||||
if (!document)
|
|
||||||
return QString();
|
return QString();
|
||||||
if (const CPlusPlus::Symbol *symbol = document->lastVisibleSymbolAt(line, column))
|
|
||||||
if (const CPlusPlus::Scope *scope = symbol->enclosingScope())
|
const CPlusPlus::Snapshot snapshot = modelManager->snapshot();
|
||||||
if (const CPlusPlus::Scope *functionScope = scope->enclosingFunction())
|
if (const CPlusPlus::Document::Ptr document = snapshot.document(fileName))
|
||||||
if (const CPlusPlus::Symbol *function = functionScope) {
|
return document->functionAt(line, column);
|
||||||
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;
|
|
||||||
}
|
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -87,6 +87,7 @@ class tst_Lookup: public QObject
|
|||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void base_class_defined_1();
|
void base_class_defined_1();
|
||||||
|
void document_functionAt_1();
|
||||||
|
|
||||||
// Objective-C
|
// Objective-C
|
||||||
void simple_class_1();
|
void simple_class_1();
|
||||||
@@ -153,6 +154,30 @@ void tst_Lookup::base_class_defined_1()
|
|||||||
QVERIFY(classToAST.value(derivedClass) != 0);
|
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()
|
void tst_Lookup::simple_class_1()
|
||||||
{
|
{
|
||||||
const QByteArray source = "\n"
|
const QByteArray source = "\n"
|
||||||
|
Reference in New Issue
Block a user