forked from qt-creator/qt-creator
C++: fix highlighting type when there is using Namespace::Class
If type is not found we try to find 'using' declaration for this type. Task-number: QTCREATORBUG-7903 Change-Id: I569db9e1a8504a5da3115ebbed2e823d5924f6ca Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
committed by
Erik Verbruggen
parent
e245f2d5f9
commit
d14767a6af
@@ -210,7 +210,7 @@ bool FindUsages::checkCandidates(const QList<LookupItem> &candidates) const
|
|||||||
if (s->enclosingScope()->isTemplate()) {
|
if (s->enclosingScope()->isTemplate()) {
|
||||||
if (s->enclosingScope()->enclosingScope() != _declSymbol->enclosingScope())
|
if (s->enclosingScope()->enclosingScope() != _declSymbol->enclosingScope())
|
||||||
return false;
|
return false;
|
||||||
} else if (s->enclosingScope() != _declSymbol->enclosingScope()) {
|
} else if (! s->isUsingDeclaration() && s->enclosingScope() != _declSymbol->enclosingScope()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -247,6 +247,33 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<LookupItem> LookupContext::lookupByUsing(const Name *name, Scope *scope) const
|
||||||
|
{
|
||||||
|
QList<LookupItem> candidates;
|
||||||
|
// if it is a nameId there can be a using declaration for it
|
||||||
|
if (name->isNameId()) {
|
||||||
|
for (unsigned i = 0, count = scope->memberCount(); i < count; ++i) {
|
||||||
|
if (UsingDeclaration *u = scope->memberAt(i)->asUsingDeclaration()) {
|
||||||
|
if (const QualifiedNameId *q = u->name()->asQualifiedNameId()) {
|
||||||
|
if (q->name()->isEqualTo(name)) {
|
||||||
|
candidates = bindings()->globalNamespace()->find(q);
|
||||||
|
|
||||||
|
// if it is not a global scope(scope of scope is not equal 0)
|
||||||
|
// then add current using declaration as a candidate
|
||||||
|
if (scope->scope()) {
|
||||||
|
LookupItem item;
|
||||||
|
item.setDeclaration(u);
|
||||||
|
item.setScope(scope);
|
||||||
|
candidates.append(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return candidates;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QSharedPointer<CreateBindings> LookupContext::bindings() const
|
QSharedPointer<CreateBindings> LookupContext::bindings() const
|
||||||
{
|
{
|
||||||
@@ -365,6 +392,10 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
candidates = lookupByUsing(name, scope);
|
||||||
|
if (! candidates.isEmpty())
|
||||||
|
return candidates;
|
||||||
|
|
||||||
} else if (Function *fun = scope->asFunction()) {
|
} else if (Function *fun = scope->asFunction()) {
|
||||||
bindings()->lookupInScope(name, fun, &candidates, /*templateId = */ 0, /*binding=*/ 0);
|
bindings()->lookupInScope(name, fun, &candidates, /*templateId = */ 0, /*binding=*/ 0);
|
||||||
|
|
||||||
@@ -390,7 +421,7 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// contunue, and look at the enclosing scope.
|
// continue, and look at the enclosing scope.
|
||||||
|
|
||||||
} else if (ObjCMethod *method = scope->asObjCMethod()) {
|
} else if (ObjCMethod *method = scope->asObjCMethod()) {
|
||||||
bindings()->lookupInScope(name, method, &candidates, /*templateId = */ 0, /*binding=*/ 0);
|
bindings()->lookupInScope(name, method, &candidates, /*templateId = */ 0, /*binding=*/ 0);
|
||||||
@@ -419,6 +450,10 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
|
|||||||
if (! candidates.isEmpty())
|
if (! candidates.isEmpty())
|
||||||
return candidates;
|
return candidates;
|
||||||
|
|
||||||
|
candidates = lookupByUsing(name, scope);
|
||||||
|
if (! candidates.isEmpty())
|
||||||
|
return candidates;
|
||||||
|
|
||||||
} else if (scope->isObjCClass() || scope->isObjCProtocol()) {
|
} else if (scope->isObjCClass() || scope->isObjCProtocol()) {
|
||||||
if (ClassOrNamespace *binding = bindings()->lookupType(scope))
|
if (ClassOrNamespace *binding = bindings()->lookupType(scope))
|
||||||
candidates = binding->find(name);
|
candidates = binding->find(name);
|
||||||
|
|||||||
@@ -311,6 +311,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QList<LookupItem> lookupByUsing(const Name *name, Scope *scope) const;
|
||||||
|
|
||||||
// The current expression.
|
// The current expression.
|
||||||
Document::Ptr _expressionDocument;
|
Document::Ptr _expressionDocument;
|
||||||
|
|
||||||
|
|||||||
@@ -1592,6 +1592,15 @@ CPPEditorWidget::Link CPPEditorWidget::findLinkAt(const QTextCursor &cursor, boo
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (d->isUsingDeclaration()) {
|
||||||
|
int tokenBeginLineNumber = 0, tokenBeginColumnNumber = 0;
|
||||||
|
convertPosition(beginOfToken, &tokenBeginLineNumber, &tokenBeginColumnNumber);
|
||||||
|
if (unsigned(tokenBeginLineNumber) > d->line()
|
||||||
|
|| (unsigned(tokenBeginLineNumber) == d->line()
|
||||||
|
&& unsigned(tokenBeginColumnNumber) > d->column())) {
|
||||||
|
result = r; // take the symbol under cursor.
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,6 +115,9 @@ private slots:
|
|||||||
void test_FollowSymbolUnderCursor_baseClassFunctionIntroducedByUsingDeclaration();
|
void test_FollowSymbolUnderCursor_baseClassFunctionIntroducedByUsingDeclaration();
|
||||||
void test_FollowSymbolUnderCursor_funWithSameNameAsBaseClassFunIntroducedByUsingDeclaration();
|
void test_FollowSymbolUnderCursor_funWithSameNameAsBaseClassFunIntroducedByUsingDeclaration();
|
||||||
void test_FollowSymbolUnderCursor_funLocalVarHidesOuterClass();
|
void test_FollowSymbolUnderCursor_funLocalVarHidesOuterClass();
|
||||||
|
void test_FollowSymbolUnderCursor_using_QTCREATORBUG7903_globalNamespace();
|
||||||
|
void test_FollowSymbolUnderCursor_using_QTCREATORBUG7903_namespace();
|
||||||
|
void test_FollowSymbolUnderCursor_using_QTCREATORBUG7903_insideFunction();
|
||||||
|
|
||||||
void test_doxygen_comments_qt_style();
|
void test_doxygen_comments_qt_style();
|
||||||
void test_doxygen_comments_qt_style_continuation();
|
void test_doxygen_comments_qt_style_continuation();
|
||||||
|
|||||||
@@ -706,6 +706,59 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_funLocalVarHidesOuterClass()
|
|||||||
data.run();
|
data.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CppEditorPlugin::test_FollowSymbolUnderCursor_using_QTCREATORBUG7903_globalNamespace()
|
||||||
|
{
|
||||||
|
const QByteArray source =
|
||||||
|
"namespace NS {\n"
|
||||||
|
"class Foo {};\n"
|
||||||
|
"}\n"
|
||||||
|
"using NS::$Foo;\n"
|
||||||
|
"void fun()\n"
|
||||||
|
"{\n"
|
||||||
|
" @Foo foo;\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
TestCase data(source);
|
||||||
|
data.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppEditorPlugin::test_FollowSymbolUnderCursor_using_QTCREATORBUG7903_namespace()
|
||||||
|
{
|
||||||
|
const QByteArray source =
|
||||||
|
"namespace NS {\n"
|
||||||
|
"class Foo {};\n"
|
||||||
|
"}\n"
|
||||||
|
"namespace NS1 {\n"
|
||||||
|
"void fun()\n"
|
||||||
|
"{\n"
|
||||||
|
" using NS::$Foo;\n"
|
||||||
|
" @Foo foo;\n"
|
||||||
|
"}\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
TestCase data(source);
|
||||||
|
data.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppEditorPlugin::test_FollowSymbolUnderCursor_using_QTCREATORBUG7903_insideFunction()
|
||||||
|
{
|
||||||
|
const QByteArray source =
|
||||||
|
"namespace NS {\n"
|
||||||
|
"class Foo {};\n"
|
||||||
|
"}\n"
|
||||||
|
"void fun()\n"
|
||||||
|
"{\n"
|
||||||
|
" using NS::$Foo;\n"
|
||||||
|
" @Foo foo;\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
TestCase data(source);
|
||||||
|
data.run();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Potential test cases improving name lookup.
|
Potential test cases improving name lookup.
|
||||||
|
|
||||||
|
|||||||
@@ -191,6 +191,9 @@ private slots:
|
|||||||
void test_checksymbols_AnonymousClass();
|
void test_checksymbols_AnonymousClass();
|
||||||
void test_checksymbols_AnonymousClass_insideNamespace();
|
void test_checksymbols_AnonymousClass_insideNamespace();
|
||||||
void test_checksymbols_AnonymousClass_QTCREATORBUG8963();
|
void test_checksymbols_AnonymousClass_QTCREATORBUG8963();
|
||||||
|
void test_checksymbols_highlightingTypeWhenUsingNamespaceClass_QTCREATORBUG7903_globalNamespace();
|
||||||
|
void test_checksymbols_highlightingTypeWhenUsingNamespaceClass_QTCREATORBUG7903_namespace();
|
||||||
|
void test_checksymbols_highlightingTypeWhenUsingNamespaceClass_QTCREATORBUG7903_insideFunction();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_CheckSymbols::test_checksymbols_TypeUse()
|
void tst_CheckSymbols::test_checksymbols_TypeUse()
|
||||||
@@ -1567,5 +1570,87 @@ void tst_CheckSymbols::test_checksymbols_AnonymousClass_QTCREATORBUG8963()
|
|||||||
TestData::check(source, expectedUses);
|
TestData::check(source, expectedUses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_CheckSymbols::test_checksymbols_highlightingTypeWhenUsingNamespaceClass_QTCREATORBUG7903_globalNamespace()
|
||||||
|
{
|
||||||
|
const QByteArray source =
|
||||||
|
"namespace NS {\n"
|
||||||
|
"class Foo {};\n"
|
||||||
|
"}\n"
|
||||||
|
"using NS::Foo;\n"
|
||||||
|
"void fun()\n"
|
||||||
|
"{\n"
|
||||||
|
" Foo foo;\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
const QList<Use> expectedUses = QList<Use>()
|
||||||
|
<< Use(1, 11, 2, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(2, 7, 3, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(4, 7, 2, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(4, 11, 3, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(5, 6, 3, CppHighlightingSupport::FunctionUse)
|
||||||
|
<< Use(7, 5, 3, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(7, 9, 3, CppHighlightingSupport::LocalUse)
|
||||||
|
;
|
||||||
|
|
||||||
|
TestData::check(source, expectedUses);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_CheckSymbols::test_checksymbols_highlightingTypeWhenUsingNamespaceClass_QTCREATORBUG7903_namespace()
|
||||||
|
{
|
||||||
|
const QByteArray source =
|
||||||
|
"namespace NS {\n"
|
||||||
|
"class Foo {};\n"
|
||||||
|
"}\n"
|
||||||
|
"namespace NS1 {\n"
|
||||||
|
"using NS::Foo;\n"
|
||||||
|
"void fun()\n"
|
||||||
|
"{\n"
|
||||||
|
" Foo foo;\n"
|
||||||
|
"}\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
const QList<Use> expectedUses = QList<Use>()
|
||||||
|
<< Use(1, 11, 2, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(2, 7, 3, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(4, 11, 3, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(5, 7, 2, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(5, 11, 3, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(6, 6, 3, CppHighlightingSupport::FunctionUse)
|
||||||
|
<< Use(8, 5, 3, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(8, 9, 3, CppHighlightingSupport::LocalUse)
|
||||||
|
;
|
||||||
|
|
||||||
|
TestData::check(source, expectedUses);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_CheckSymbols::test_checksymbols_highlightingTypeWhenUsingNamespaceClass_QTCREATORBUG7903_insideFunction()
|
||||||
|
{
|
||||||
|
const QByteArray source =
|
||||||
|
"namespace NS {\n"
|
||||||
|
"class Foo {};\n"
|
||||||
|
"}\n"
|
||||||
|
"void fun()\n"
|
||||||
|
"{\n"
|
||||||
|
" using NS::Foo;\n"
|
||||||
|
" Foo foo;\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
const QList<Use> expectedUses = QList<Use>()
|
||||||
|
<< Use(1, 11, 2, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(2, 7, 3, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(4, 6, 3, CppHighlightingSupport::FunctionUse)
|
||||||
|
<< Use(6, 11, 2, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(6, 15, 3, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(7, 5, 3, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(7, 9, 3, CppHighlightingSupport::LocalUse)
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
TestData::check(source, expectedUses);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_APPLESS_MAIN(tst_CheckSymbols)
|
QTEST_APPLESS_MAIN(tst_CheckSymbols)
|
||||||
#include "tst_checksymbols.moc"
|
#include "tst_checksymbols.moc"
|
||||||
|
|||||||
@@ -97,6 +97,9 @@ private Q_SLOTS:
|
|||||||
void operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG9006();
|
void operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG9006();
|
||||||
void operatorArrowOfNestedClassOfTemplateClass_QTCREATORBUG9005();
|
void operatorArrowOfNestedClassOfTemplateClass_QTCREATORBUG9005();
|
||||||
void anonymousClass_QTCREATORBUG8963();
|
void anonymousClass_QTCREATORBUG8963();
|
||||||
|
void using_insideGlobalNamespace();
|
||||||
|
void using_insideNamespace();
|
||||||
|
void using_insideFunction();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -536,6 +539,129 @@ void tst_FindUsages::anonymousClass_QTCREATORBUG8963()
|
|||||||
QCOMPARE(findUsages.usages().size(), 2);
|
QCOMPARE(findUsages.usages().size(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::using_insideGlobalNamespace()
|
||||||
|
{
|
||||||
|
const QByteArray src =
|
||||||
|
"namespace NS\n"
|
||||||
|
"{\n"
|
||||||
|
"struct Struct\n"
|
||||||
|
"{\n"
|
||||||
|
" int bar;\n"
|
||||||
|
"};\n"
|
||||||
|
"}\n"
|
||||||
|
"using NS::Struct;\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" Struct s;\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("using_insideGlobalNamespace");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QCOMPARE(doc->globalSymbolCount(), 3U);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
Namespace *nsSymbol = doc->globalSymbolAt(0)->asNamespace();
|
||||||
|
QVERIFY(nsSymbol);
|
||||||
|
QCOMPARE(nsSymbol->memberCount(), 1U);
|
||||||
|
Class *structSymbol = nsSymbol->memberAt(0)->asClass();
|
||||||
|
QVERIFY(structSymbol);
|
||||||
|
|
||||||
|
FindUsages findUsages(src, doc, snapshot);
|
||||||
|
findUsages(structSymbol);
|
||||||
|
|
||||||
|
QCOMPARE(findUsages.usages().size(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::using_insideNamespace()
|
||||||
|
{
|
||||||
|
const QByteArray src =
|
||||||
|
"namespace NS\n"
|
||||||
|
"{\n"
|
||||||
|
"struct Struct\n"
|
||||||
|
"{\n"
|
||||||
|
" int bar;\n"
|
||||||
|
"};\n"
|
||||||
|
"}\n"
|
||||||
|
"namespace NS1\n"
|
||||||
|
"{\n"
|
||||||
|
"using NS::Struct;\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" Struct s;\n"
|
||||||
|
"}\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("using_insideNamespace");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QCOMPARE(doc->globalSymbolCount(), 2U);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
Namespace *nsSymbol = doc->globalSymbolAt(0)->asNamespace();
|
||||||
|
QVERIFY(nsSymbol);
|
||||||
|
QCOMPARE(nsSymbol->memberCount(), 1U);
|
||||||
|
Class *structSymbol = nsSymbol->memberAt(0)->asClass();
|
||||||
|
QVERIFY(structSymbol);
|
||||||
|
|
||||||
|
FindUsages findUsages(src, doc, snapshot);
|
||||||
|
findUsages(structSymbol);
|
||||||
|
|
||||||
|
QCOMPARE(findUsages.usages().size(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::using_insideFunction()
|
||||||
|
{
|
||||||
|
const QByteArray src =
|
||||||
|
"namespace NS\n"
|
||||||
|
"{\n"
|
||||||
|
"struct Struct\n"
|
||||||
|
"{\n"
|
||||||
|
" int bar;\n"
|
||||||
|
"};\n"
|
||||||
|
"}\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" using NS::Struct;\n"
|
||||||
|
" Struct s;\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("using_insideFunction");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QCOMPARE(doc->globalSymbolCount(), 2U);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
Namespace *nsSymbol = doc->globalSymbolAt(0)->asNamespace();
|
||||||
|
QVERIFY(nsSymbol);
|
||||||
|
QCOMPARE(nsSymbol->memberCount(), 1U);
|
||||||
|
Class *structSymbol = nsSymbol->memberAt(0)->asClass();
|
||||||
|
QVERIFY(structSymbol);
|
||||||
|
|
||||||
|
FindUsages findUsages(src, doc, snapshot);
|
||||||
|
findUsages(structSymbol);
|
||||||
|
|
||||||
|
QCOMPARE(findUsages.usages().size(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
void tst_FindUsages::operatorArrowOfNestedClassOfTemplateClass_QTCREATORBUG9005()
|
void tst_FindUsages::operatorArrowOfNestedClassOfTemplateClass_QTCREATORBUG9005()
|
||||||
{
|
{
|
||||||
const QByteArray src = "\n"
|
const QByteArray src = "\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user