Commit 94dd4e74 authored by Przemyslaw Gorszkowski's avatar Przemyslaw Gorszkowski Committed by Erik Verbruggen
Browse files

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: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent afe1d5ee
......@@ -177,9 +177,10 @@ protected:
virtual bool visit(Template *symbol)
{
if (symbol->declaration() && symbol->declaration()->isFunction())
if (Symbol *decl = symbol->declaration()) {
if (decl->isFunction() || decl->isClass())
return process(symbol);
else
}
return true;
}
......
......@@ -207,10 +207,36 @@ bool FindUsages::checkCandidates(const QList<LookupItem> &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;
}
}
......
......@@ -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 <class T>\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 <class T>\n"
"struct TS\n"
"{\n"
" TS();\n"
" ~TS();\n"
"};\n"
"template <class T>\n"
"TS<T>::TS()\n"
"{\n"
"}\n"
"template <class T>\n"
"TS<T>::~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<class T>\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"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment