From 94dd4e740a3b6acf28cd3df4015af6f612aae6d5 Mon Sep 17 00:00:00 2001 From: Przemyslaw Gorszkowski Date: Fri, 7 Jun 2013 08:15:19 +0200 Subject: [PATCH] C++: fix 'find usages' for templates Fix find usages for template class(class name and template parameters) or template function(template parameters). Fixed: * marking * find usages * follow symbol Change-Id: I22fdbc11260cbd8ee9aafdd76aaeee0f4f49f9fd Reviewed-by: Erik Verbruggen --- src/libs/cplusplus/CppDocument.cpp | 9 +- src/libs/cplusplus/FindUsages.cpp | 30 ++++- .../cplusplus/findusages/tst_findusages.cpp | 114 +++++++++++++++++- 3 files changed, 146 insertions(+), 7 deletions(-) diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index 7df0d2d2e52..0fec40050ec 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -177,10 +177,11 @@ protected: virtual bool visit(Template *symbol) { - if (symbol->declaration() && symbol->declaration()->isFunction()) - return process(symbol); - else - return true; + if (Symbol *decl = symbol->declaration()) { + if (decl->isFunction() || decl->isClass()) + return process(symbol); + } + return true; } // Objective-C diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp index 07a912b8faf..a178ad088c8 100644 --- a/src/libs/cplusplus/FindUsages.cpp +++ b/src/libs/cplusplus/FindUsages.cpp @@ -207,10 +207,36 @@ bool FindUsages::checkCandidates(const QList &candidates) const } if (isLocalScope(_declSymbol->enclosingScope()) || isLocalScope(s->enclosingScope())) { - if (s->enclosingScope()->isTemplate()) { + if (_declSymbol->isClass() && _declSymbol->enclosingScope()->isTemplate() + && s->isClass() && s->enclosingScope()->isTemplate()) { + // for definition of functions of class defined outside the class definition + Scope *templEnclosingDeclSymbol = _declSymbol->enclosingScope(); + Scope *scopeOfTemplEnclosingDeclSymbol + = templEnclosingDeclSymbol->enclosingScope(); + Scope *templEnclosingCandidateSymbol = s->enclosingScope(); + Scope *scopeOfTemplEnclosingCandidateSymbol + = templEnclosingCandidateSymbol->enclosingScope(); + + if (scopeOfTemplEnclosingCandidateSymbol != scopeOfTemplEnclosingDeclSymbol) + return false; + } else if (_declSymbol->isClass() && _declSymbol->enclosingScope()->isTemplate() + && s->enclosingScope()->isClass() + && s->enclosingScope()->enclosingScope()->isTemplate()) { + // for declaration inside template class + Scope *templEnclosingDeclSymbol = _declSymbol->enclosingScope(); + Scope *scopeOfTemplEnclosingDeclSymbol + = templEnclosingDeclSymbol->enclosingScope(); + Scope *templEnclosingCandidateSymbol = s->enclosingScope()->enclosingScope(); + Scope *scopeOfTemplEnclosingCandidateSymbol + = templEnclosingCandidateSymbol->enclosingScope(); + + if (scopeOfTemplEnclosingCandidateSymbol != scopeOfTemplEnclosingDeclSymbol) + return false; + } else if (s->enclosingScope()->isTemplate() && ! _declSymbol->isTypenameArgument()) { if (s->enclosingScope()->enclosingScope() != _declSymbol->enclosingScope()) return false; - } else if (! s->isUsingDeclaration() && s->enclosingScope() != _declSymbol->enclosingScope()) { + } else if (! s->isUsingDeclaration() + && s->enclosingScope() != _declSymbol->enclosingScope()) { return false; } } diff --git a/tests/auto/cplusplus/findusages/tst_findusages.cpp b/tests/auto/cplusplus/findusages/tst_findusages.cpp index 18f94ce0b25..15962325e16 100644 --- a/tests/auto/cplusplus/findusages/tst_findusages.cpp +++ b/tests/auto/cplusplus/findusages/tst_findusages.cpp @@ -96,11 +96,14 @@ private Q_SLOTS: void instantiateTemplateWithNestedClass(); void operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG9006(); void operatorArrowOfNestedClassOfTemplateClass_QTCREATORBUG9005(); + void templateClassParameters(); + void templateClass_className(); + void templateFunctionParameters(); + void anonymousClass_QTCREATORBUG8963(); void using_insideGlobalNamespace(); void using_insideNamespace(); void using_insideFunction(); - }; void tst_FindUsages::inlineMethod() @@ -706,5 +709,114 @@ void tst_FindUsages::operatorArrowOfNestedClassOfTemplateClass_QTCREATORBUG9005( QCOMPARE(findUsages.usages().size(), 2); } +void tst_FindUsages::templateClassParameters() +{ + const QByteArray src = "\n" + "template \n" + "struct TS\n" + "{\n" + " void set(T t) { T t1 = t; }\n" + " T get();\n" + " T t;\n" + "};\n" + ; + + Document::Ptr doc = Document::create("templateClassParameters"); + doc->setUtf8Source(src); + doc->parse(); + doc->check(); + + QVERIFY(doc->diagnosticMessages().isEmpty()); + QCOMPARE(doc->globalSymbolCount(), 1U); + + Snapshot snapshot; + snapshot.insert(doc); + + Template *templateClassTS = doc->globalSymbolAt(0)->asTemplate(); + QVERIFY(templateClassTS); + QCOMPARE(templateClassTS->memberCount(), 2U); + QCOMPARE(templateClassTS->templateParameterCount(), 1U); + TypenameArgument *templArgument = templateClassTS->templateParameterAt(0)->asTypenameArgument(); + QVERIFY(templArgument); + + FindUsages findUsages(src, doc, snapshot); + findUsages(templArgument); + QCOMPARE(findUsages.usages().size(), 5); +} + +void tst_FindUsages::templateClass_className() +{ + const QByteArray src = "\n" + "template \n" + "struct TS\n" + "{\n" + " TS();\n" + " ~TS();\n" + "};\n" + "template \n" + "TS::TS()\n" + "{\n" + "}\n" + "template \n" + "TS::~TS()\n" + "{\n" + "}\n" + ; + + Document::Ptr doc = Document::create("templateClass_className"); + doc->setUtf8Source(src); + doc->parse(); + doc->check(); + + QVERIFY(doc->diagnosticMessages().isEmpty()); + QCOMPARE(doc->globalSymbolCount(), 3U); + + Snapshot snapshot; + snapshot.insert(doc); + + Template *templateClassTS = doc->globalSymbolAt(0)->asTemplate(); + QVERIFY(templateClassTS); + Class *classTS = templateClassTS->memberAt(1)->asClass(); + QVERIFY(classTS); + QCOMPARE(classTS->memberCount(), 2U); + + FindUsages findUsages(src, doc, snapshot); + findUsages(classTS); + QCOMPARE(findUsages.usages().size(), 6); +} + +void tst_FindUsages::templateFunctionParameters() +{ + const QByteArray src = "\n" + "template\n" + "T foo(T t)\n" + "{\n" + " typename T;\n" + "}\n" + ; + + Document::Ptr doc = Document::create("templateFunctionParameters"); + doc->setUtf8Source(src); + doc->parse(); + doc->check(); + + QVERIFY(doc->diagnosticMessages().isEmpty()); + QCOMPARE(doc->globalSymbolCount(), 1U); + + Snapshot snapshot; + snapshot.insert(doc); + + Template *templateFunctionTS = doc->globalSymbolAt(0)->asTemplate(); + QVERIFY(templateFunctionTS); + QCOMPARE(templateFunctionTS->memberCount(), 2U); + QCOMPARE(templateFunctionTS->templateParameterCount(), 1U); + TypenameArgument *templArgument = templateFunctionTS->templateParameterAt(0)->asTypenameArgument(); + QVERIFY(templArgument); + + FindUsages findUsages(src, doc, snapshot); + findUsages(templArgument); + QCOMPARE(findUsages.usages().size(), 4); +} + QTEST_APPLESS_MAIN(tst_FindUsages) #include "tst_findusages.moc"