diff --git a/bin/app/data/src/test2/header.h b/bin/app/data/src/test2/header.h index 0af9b18b..1f5ea562 100644 --- a/bin/app/data/src/test2/header.h +++ b/bin/app/data/src/test2/header.h @@ -1,14 +1,8 @@ -template -class TemplateTestClass +template +class Foo { public: - template - void run(P param); + void bar() + { + } }; - -template -template -void TemplateTestClass::run(P param) -{ -} - diff --git a/bin/app/data/src/test2/main.cpp b/bin/app/data/src/test2/main.cpp index 1ed9e739..5f9b5022 100644 --- a/bin/app/data/src/test2/main.cpp +++ b/bin/app/data/src/test2/main.cpp @@ -2,9 +2,7 @@ int main() { - TemplateTestClass t1; - t1.run(6.9f); - TemplateTestClass t2; - t2.run(6); + Foo ft; + ft.bar(); return 0; } \ No newline at end of file diff --git a/bin/data/window_settings.ini b/bin/data/window_settings.ini new file mode 100644 index 00000000..8a4dcd41 --- /dev/null +++ b/bin/data/window_settings.ini @@ -0,0 +1,7 @@ +[MainWindow] +maximized=false +size=@Size(600 400) +position=@Point(200 200) + +[General] +DOCK_LOCATIONS=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x1\0\0\0\x2\0\0\x2X\0\0\x1g\xfc\x1\0\0\0\x3\xfb\0\0\0\x1a\0\x44\0o\0\x63\0k\0G\0r\0\x61\0p\0h\0V\0i\0\x65\0w\x1\0\0\0\0\0\0\0\x86\0\0\0P\0\xff\xff\xff\xfb\0\0\0\x18\0\x44\0o\0\x63\0k\0\x43\0o\0\x64\0\x65\0V\0i\0\x65\0w\x1\0\0\0\x8a\0\0\0\xb3\0\0\0P\0\xff\xff\xff\xfb\0\0\0\"\0\x44\0o\0\x63\0k\0\x43\0o\0m\0p\0o\0s\0i\0t\0\x65\0V\0i\0\x65\0w\x1\0\0\x1\x41\0\0\x1\x17\0\0\x1\x10\0\xff\xff\xff\0\0\x2X\0\0\0\0\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\0) diff --git a/bin/test/data/log/test_log.txt b/bin/test/data/log/test_log.txt index 096ab62e..50374ea3 100644 --- a/bin/test/data/log/test_log.txt +++ b/bin/test/data/log/test_log.txt @@ -1,27 +1,4 @@ ConfigManager.cpp ERROR: value path/to/nowhere is not present in config. -Token.cpp ERROR: Location Id was not referenced by this Token. -Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class -Edge.cpp ERROR: Nodes are not plain copies. -Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined -Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined -Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined -Storage.cpp INFO: file: input.cc < 0:0 0:0> -Storage.cpp INFO: class: A -Storage.cpp INFO: method: A::A -Storage.cpp INFO: global usage: A::A -> A::count -Storage.cpp INFO: method: A::getCount -Storage.cpp INFO: global usage: A::getCount -> A::count -Storage.cpp INFO: method: A::process -Storage.cpp INFO: field: A::count -Storage.cpp INFO: class: B -Storage.cpp INFO: inheritance: B : A -Storage.cpp INFO: method: B::process -Storage.cpp INFO: override: A::process -> B::process < 0:0 0:0> -Storage.cpp INFO: type usage: B::process -> int -Storage.cpp INFO: function: main -Storage.cpp INFO: type usage: main -> B -Storage.cpp INFO: call: main -> B::B -Storage.cpp INFO: call: main -> A::getCount Storage.cpp INFO: file: input.cc < 0:0 0:0> Storage.cpp INFO: class: A Storage.cpp INFO: method: A::A @@ -56,6 +33,29 @@ SearchMatch.cpp INFO: 190 A::A ^^^^ +Storage.cpp INFO: file: input.cc < 0:0 0:0> +Storage.cpp INFO: class: A +Storage.cpp INFO: method: A::A +Storage.cpp INFO: global usage: A::A -> A::count +Storage.cpp INFO: method: A::getCount +Storage.cpp INFO: global usage: A::getCount -> A::count +Storage.cpp INFO: method: A::process +Storage.cpp INFO: field: A::count +Storage.cpp INFO: class: B +Storage.cpp INFO: inheritance: B : A +Storage.cpp INFO: method: B::process +Storage.cpp INFO: override: A::process -> B::process < 0:0 0:0> +Storage.cpp INFO: type usage: B::process -> int +Storage.cpp INFO: function: main +Storage.cpp INFO: type usage: main -> B +Storage.cpp INFO: call: main -> B::B +Storage.cpp INFO: call: main -> A::getCount +Token.cpp ERROR: Location Id was not referenced by this Token. +Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class +Edge.cpp ERROR: Nodes are not plain copies. +Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined +Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined +Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined Settings.cpp WARNING: File for Settings not found. ConfigManager.cpp ERROR: value Bool is not present in config. ConfigManager.cpp ERROR: value Int is not present in config. @@ -71,6 +71,7 @@ ConfigManager.cpp ERROR: value Int is not present in config. ConfigManager.cpp ERROR: value Float is not present in config. ConfigManager.cpp ERROR: value String is not present in config. ConfigManager.cpp ERROR: value NewBool is not present in config. +Graph.cpp ERROR: Can't remove member edge, without removing the child node. Storage.cpp INFO: typedef: type -> int Storage.cpp INFO: class: Class Storage.cpp INFO: struct: Struct @@ -135,7 +136,6 @@ Storage.cpp INFO: file: file.h < 0:0 0:0> Storage.cpp INFO: file: file.cpp < 0:0 0:0> Storage.cpp INFO: include: f.h Storage.cpp INFO: include: file.h -Graph.cpp ERROR: Can't remove member edge, without removing the child node. TextAccess.cpp WARNING: Index 'firstLine' has to be lower or equal index 'lastLine', is 3 > 2 TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8 TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8 diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index 99afcaea..91beaa45 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -532,12 +532,12 @@ Id Storage::onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& v return edge->getId(); } -Id Storage::onTemplateArgumentParsed( +Id Storage::onTemplateArgumentTypeParsed( const ParseLocation& location, const std::vector& argumentNameHierarchy, const std::vector& templateNameHierarchy) { log( - "template argument", + "template argument type", utility::join(argumentNameHierarchy, "::") + " -> " + utility::join(templateNameHierarchy, "::"), location ); diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h index 16565abd..649a2dcb 100644 --- a/src/lib/data/Storage.h +++ b/src/lib/data/Storage.h @@ -87,7 +87,7 @@ public: virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function); virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& variable); - virtual Id onTemplateArgumentParsed( + virtual Id onTemplateArgumentTypeParsed( const ParseLocation& location, const std::vector& argumentNameHierarchy, const std::vector& templateNameHierarchy); virtual Id onTemplateDefaultArgumentTypeParsed( diff --git a/src/lib/data/parser/ParserClient.h b/src/lib/data/parser/ParserClient.h index 80ede54b..e546d1da 100644 --- a/src/lib/data/parser/ParserClient.h +++ b/src/lib/data/parser/ParserClient.h @@ -100,7 +100,7 @@ public: virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) = 0; virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& variable) = 0; - virtual Id onTemplateArgumentParsed( + virtual Id onTemplateArgumentTypeParsed( const ParseLocation& location, const std::vector& argumentNameHierarchy, const std::vector& templateNameHierarchy) = 0; virtual Id onTemplateDefaultArgumentTypeParsed( diff --git a/src/lib/data/parser/cxx/ASTVisitor.cpp b/src/lib/data/parser/cxx/ASTVisitor.cpp index d02591e1..66f58a8a 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.cpp +++ b/src/lib/data/parser/cxx/ASTVisitor.cpp @@ -303,11 +303,14 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration) for (size_t i = 0; i < parameterList->size(); i++) { clang::NamedDecl* namedDecl = parameterList->getParam(i); - m_client->onTemplateRecordParameterTypeParsed( - getParseLocationForNamedDecl(namedDecl), - utility::getDeclNameHierarchy(namedDecl), - templateRecordNameHierarchy - ); + if (!namedDecl->getName().empty()) // do not create node for template param if the param has no name + { + m_client->onTemplateRecordParameterTypeParsed( + getParseLocationForNamedDecl(namedDecl), + utility::getDeclNameHierarchy(namedDecl), + templateRecordNameHierarchy + ); + } } } @@ -339,7 +342,7 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration) if (argumentNameHierarchy.size()) // FIXME: Some TemplateArgument kinds are not handled yet. { - m_client->onTemplateArgumentParsed( + m_client->onTemplateArgumentTypeParsed( ParseLocation(specializationFilePath, 0, 0), // TODO: Find a valid ParseLocation here! argumentNameHierarchy, specializedRecordNameHierarchy @@ -367,11 +370,14 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat for (size_t i = 0; i < parameterList->size(); i++) { clang::NamedDecl* namedDecl = parameterList->getParam(i); - m_client->onTemplateRecordParameterTypeParsed( - getParseLocationForNamedDecl(namedDecl), - utility::getDeclNameHierarchy(namedDecl), - specializedRecordNameHierarchy - ); + if (!namedDecl->getName().empty()) // do not create node for template param if the param has no name + { + m_client->onTemplateRecordParameterTypeParsed( + getParseLocationForNamedDecl(namedDecl), + utility::getDeclNameHierarchy(namedDecl), + specializedRecordNameHierarchy + ); + } } const clang::ASTTemplateArgumentListInfo* argumentInfoList = declaration->getTemplateArgsAsWritten(); @@ -379,15 +385,11 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat { const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i); const clang::TemplateArgument& argument = argumentLoc.getArgument(); - if (argument.getKind() == clang::TemplateArgument::Type) - { - const clang::QualType argumentType = argument.getAsType(); - m_client->onTemplateArgumentParsed( - getParseLocation(argumentLoc.getSourceRange()), - utility::qualTypeToDataType(argumentType).getTypeNameHierarchy(), - specializedRecordNameHierarchy); - } + m_client->onTemplateArgumentTypeParsed( + getParseLocation(argumentLoc.getSourceRange()), + utility::templateArgumentToDataType(argument).getTypeNameHierarchy(), + specializedRecordNameHierarchy); } } return true; @@ -439,7 +441,7 @@ bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declarat const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i); const clang::QualType argumentType = argumentLoc.getArgument().getAsType(); - m_client->onTemplateArgumentParsed( + m_client->onTemplateArgumentTypeParsed( getParseLocation(argumentLoc.getSourceRange()), utility::qualTypeToDataType(argumentType).getTypeNameHierarchy(), specializedFunction.nameHierarchy); @@ -459,7 +461,7 @@ bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declarat const clang::TemplateArgument& argument = argumentList->get(i); const clang::QualType argumentType = argument.getAsType(); - m_client->onTemplateArgumentParsed( + m_client->onTemplateArgumentTypeParsed( ParseLocation(specializedFunctionLocation.filePath, 0, 0), // TODO: Find a valid ParseLocation here! utility::qualTypeToDataType(argumentType).getTypeNameHierarchy(), specializedFunction.nameHierarchy); diff --git a/src/lib/data/parser/cxx/utilityCxx.cpp b/src/lib/data/parser/cxx/utilityCxx.cpp index cd72ca69..423851dd 100644 --- a/src/lib/data/parser/cxx/utilityCxx.cpp +++ b/src/lib/data/parser/cxx/utilityCxx.cpp @@ -12,6 +12,7 @@ #include "data/type/DataTypeQualifierList.h" #include "utility/utilityString.h" #include "utility/logging/logging.h" +#include "llvm/Support/raw_ostream.h" namespace utility { @@ -26,7 +27,6 @@ namespace utility while (needsRefinement) { const clang::Type* type = qualType.getTypePtr(); - clang::Type::TypeClass tk = type->getTypeClass(); switch (type->getTypeClass()) { case clang::Type::Paren: @@ -92,7 +92,6 @@ namespace utility break; } case clang::Type::Builtin: - case clang::Type::TemplateSpecialization: { clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions()); pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A" @@ -100,6 +99,12 @@ namespace utility std::string typeName = qualType.getUnqualifiedType().getAsString(pp); typeNameHerarchy.push_back(typeName); + needsRefinement = false; + break; + } + case clang::Type::TemplateSpecialization: + { + typeNameHerarchy = getDeclNameHierarchy(type->getAs()->getDecl()); needsRefinement = false; break; } @@ -175,7 +180,8 @@ namespace utility LOG_ERROR("unhandled declaration type: " + std::string(declaration->getDeclKindName())); } contextNameHierarchy = getContextNameHierarchy(declaration->getDeclContext()); - if (clang::isa(declaration)) + if (clang::isa(declaration) || + clang::isa(declaration)) // TODO: Handle templatetemplate stuff { contextNameHierarchy.back() += "::" + declName; } @@ -211,7 +217,6 @@ namespace utility std::string getDeclName(const clang::NamedDecl* declaration) { std::string declName = declaration->getNameAsString(); - if (clang::isa(declaration)) { clang::ClassTemplateDecl* templateClassDeclaration = clang::dyn_cast(declaration)->getDescribedClassTemplate(); @@ -224,24 +229,23 @@ namespace utility const clang::ClassTemplatePartialSpecializationDecl* partialSpecializationDecl = clang::dyn_cast(declaration); + clang::TemplateParameterList* parameterList = partialSpecializationDecl->getTemplateParameters(); + int currentParameterIndex = 0; + + std::string specializedParameterNamePart = "<"; int templateArgumentCount = partialSpecializationDecl->getTemplateArgs().size(); const clang::ASTTemplateArgumentListInfo* templateArgumentListInfo = partialSpecializationDecl->getTemplateArgsAsWritten(); - std::string specializedParameterNamePart = "<"; for (int i = 0; i < templateArgumentCount; i++) { const clang::TemplateArgument& templateArgument = templateArgumentListInfo->getTemplateArgs()[i].getArgument(); - const clang::TemplateArgument::ArgKind kind = templateArgument.getKind(); - switch (kind) + if (templateArgument.isDependent()) // TODO: fix case when arg depends on template parameter of outer template class. { - case clang::TemplateArgument::Type: - specializedParameterNamePart += templateArgument.getAsType().getAsString(); - break; - case clang::TemplateArgument::Integral: - specializedParameterNamePart += templateArgument.getIntegralType().getAsString(); - break; - default: - LOG_ERROR("Type of template argument not handled."); - break; + specializedParameterNamePart += getTemplateParameterString(parameterList->getParam(currentParameterIndex)); + currentParameterIndex++; + } + else + { + specializedParameterNamePart += getTemplateArgumentName(templateArgument); } specializedParameterNamePart += (i < templateArgumentCount - 1) ? ", " : ""; } @@ -254,8 +258,7 @@ namespace utility const clang::TemplateArgumentList& templateArgumentList = clang::dyn_cast(declaration)->getTemplateArgs(); for (size_t i = 0; i < templateArgumentList.size(); i++) { - const clang::TemplateArgument& templateArgument = templateArgumentList.get(i); - specializedParameterNamePart += templateArgumentToDataType(templateArgument).getFullTypeName(); + specializedParameterNamePart += getTemplateArgumentName(templateArgumentList.get(i)); specializedParameterNamePart += (i < templateArgumentList.size() - 1) ? ", " : ""; } specializedParameterNamePart += ">"; @@ -283,15 +286,17 @@ namespace utility declName += specializedParameterNamePart; } } + else if (clang::isa(declaration)) + { + // nothing to do here + } else if (clang::isa(declaration)) { std::string templateParameterNamePart = "<"; clang::TemplateParameterList* parameterList = clang::dyn_cast(declaration)->getTemplateParameters(); for (size_t i = 0; i < parameterList->size(); i++) { - clang::NamedDecl* namedDecl = parameterList->getParam(i); - - templateParameterNamePart += namedDecl->getNameAsString(); + templateParameterNamePart += getTemplateParameterString(parameterList->getParam(i)); templateParameterNamePart += (i < parameterList->size() - 1) ? ", " : ""; } templateParameterNamePart += ">"; @@ -323,7 +328,7 @@ namespace utility return specializationParentNameHierarchy; } - DataType templateArgumentToDataType(const clang::TemplateArgument& argument) + DataType templateArgumentToDataType(const clang::TemplateArgument& argument) // remove this! this is stupid! agurment is not always a datatype. { const clang::TemplateArgument::ArgKind kind = argument.getKind(); switch (kind) @@ -332,10 +337,115 @@ namespace utility return utility::qualTypeToDataType(argument.getAsType()); case clang::TemplateArgument::Integral: return utility::qualTypeToDataType(argument.getIntegralType()); + case clang::TemplateArgument::Null: + LOG_ERROR("Type of template argument not handled: Null"); + break; + case clang::TemplateArgument::Declaration: + return utility::qualTypeToDataType(argument.getAsDecl()->getType()); + case clang::TemplateArgument::NullPtr: + return utility::qualTypeToDataType(argument.getNullPtrType()); + break; + case clang::TemplateArgument::Template: + { + clang::TemplateName templateName = argument.getAsTemplate(); + switch (templateName.getKind()) + { + case clang::TemplateName::Template: + return DataType(getDeclNameHierarchy(templateName.getAsTemplateDecl())); + } + LOG_ERROR("Type of template argument not handled: Template"); + } + break; + case clang::TemplateArgument::TemplateExpansion: + LOG_ERROR("Type of template argument not handled: TemplateExpansion"); + break; + case clang::TemplateArgument::Expression: + return utility::qualTypeToDataType(argument.getAsExpr()->getType()); + case clang::TemplateArgument::Pack: + LOG_ERROR("Type of template argument not handled: Pack"); + break; default: - LOG_ERROR("Type of template argument not handled."); + LOG_ERROR("Type of template argument not handled." + argument.getKind()); break; } return DataType(std::vector()); } + + std::string getTemplateParameterString(const clang::NamedDecl* parameter) + { + std::string templateParameterString = ""; + clang::Decl::Kind templateParameterKind = parameter->getKind(); + switch (templateParameterKind) + { + case clang::Decl::NonTypeTemplateParm: + { + const clang::NonTypeTemplateParmDecl* nonTypeTemplateParmDecl = clang::dyn_cast(parameter); + templateParameterString = qualTypeToDataType(nonTypeTemplateParmDecl->getType()).getFullTypeName(); + } + break; + case clang::Decl::TemplateTypeParm: + { + const clang::TemplateTypeParmDecl* templateTypeParmDecl = clang::dyn_cast(parameter); + templateParameterString = templateTypeParmDecl->wasDeclaredWithTypename() ? "typename" : "class"; + } + break; + case clang::Decl::TemplateTemplateParm: + { + const clang::TemplateTemplateParmDecl* templateTemplateParmDecl = clang::dyn_cast(parameter); + templateParameterString = "template<"; + clang::TemplateParameterList* parameterList = templateTemplateParmDecl->getTemplateParameters(); + for (size_t i = 0; i < parameterList->size(); i++) + { + templateParameterString += getTemplateParameterString(parameterList->getParam(i)); + templateParameterString += (i < parameterList->size() - 1) ? ", " : ""; + } + templateParameterString += ">"; + templateParameterString += " typename"; // TODO: what if template template parameter is defined with class keyword? + } + break; + default: + LOG_ERROR("Unhandled kind of template parameter."); + } + + std::string parameterName = parameter->getName(); + if (!parameterName.empty()) + { + templateParameterString += " " + parameterName; + } + return templateParameterString; + } + + std::string getTemplateArgumentName(const clang::TemplateArgument& argument) + { + const clang::TemplateArgument::ArgKind kind = argument.getKind(); + switch (kind) + { + case clang::TemplateArgument::Type: + return utility::qualTypeToDataType(argument.getAsType()).getFullTypeName(); + case clang::TemplateArgument::Integral: + case clang::TemplateArgument::Null: + case clang::TemplateArgument::Declaration: + case clang::TemplateArgument::NullPtr: + case clang::TemplateArgument::Template: + case clang::TemplateArgument::TemplateExpansion: + case clang::TemplateArgument::Expression: + { + clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions()); + pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A" + pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool" + + std::string buf; + llvm::raw_string_ostream os(buf); + argument.print(pp, os); + return os.str(); + } + case clang::TemplateArgument::Pack: + LOG_ERROR("Type of template argument not handled: Pack"); + break; + default: + LOG_ERROR("Type of template argument not handled." + argument.getKind()); + break; + } + return std::string(); + } } diff --git a/src/lib/data/parser/cxx/utilityCxx.h b/src/lib/data/parser/cxx/utilityCxx.h index 2b50cd4c..48abb4e8 100644 --- a/src/lib/data/parser/cxx/utilityCxx.h +++ b/src/lib/data/parser/cxx/utilityCxx.h @@ -20,6 +20,8 @@ namespace utility std::string getDeclName(const clang::NamedDecl* declaration); std::vector getTemplateSpecializationParentNameHierarchy(clang::ClassTemplateSpecializationDecl* declaration); DataType templateArgumentToDataType(const clang::TemplateArgument& argument); + std::string getTemplateParameterString(const clang::NamedDecl* parameter); + std::string getTemplateArgumentName(const clang::TemplateArgument& argument); } #endif // UTILITY_CLANG_H diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index d444376f..2d7fb997 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -1198,7 +1198,7 @@ public: } - void test_cxx_parser_finds_template_parameter_type_of_template_class() + void test_cxx_parser_finds_type_template_parameter_type_of_template_class() { std::shared_ptr client = parseCode( "template \n" @@ -1208,10 +1208,69 @@ public: ); TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A::T <1:20 1:20>"); + TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A::T <1:20 1:20>"); } - void test_cxx_parser_finds_template_parameter_types_of_template_class_with_multiple_parameters() + void test_cxx_parser_finds_type_template_parameter_defined_with_class_keyword() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{\n" + "};\n" + ); + + TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 1); + TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A::T <1:17 1:17>"); + } + + void test_cxx_parser_finds_non_type_int_template_parameter_of_template_class() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{\n" + "};\n" + ); + + TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 1); + TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A::T <1:15 1:15>"); + } + + void test_cxx_parser_finds_non_type_bool_template_parameter_of_template_class() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{\n" + "};\n" + ); + + TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 1); + TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A::T <1:16 1:16>"); + } + + void test_cxx_parser_finds_template_template_parameter_of_template_class() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{};\n" + "template typename T>\n" + "class B\n" + "{};\n" + "int main()\n" + "{\n" + " B ba;\n" + "}\n" + ); + + TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 2); + TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A::T <1:20 1:20>"); + TS_ASSERT_EQUALS(client->templateParameterTypes[1], "B typename T>::T <4:39 4:39>"); + } + + void test_cxx_parser_finds_type_template_parameters_of_template_class_with_multiple_parameters() { std::shared_ptr client = parseCode( "template \n" @@ -1221,8 +1280,21 @@ public: ); TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 2); - TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A::T <1:20 1:20>"); - TS_ASSERT_EQUALS(client->templateParameterTypes[1], "A::U <1:32 1:32>"); + TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A::T <1:20 1:20>"); + TS_ASSERT_EQUALS(client->templateParameterTypes[1], "A::U <1:32 1:32>"); + } + + void test_cxx_parser_skips_creating_node_for_template_parameter_without_a_name() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{\n" + "};\n" + ); + + TS_ASSERT_EQUALS(client->classes.size(), 1); + TS_ASSERT_EQUALS(client->classes[0], "A <2:1 <2:7 2:7> 4:1>"); } void test_cxx_parser_finds_template_parameter_of_template_method_definition_outside_template_class() @@ -1240,12 +1312,12 @@ public: "{}\n" ); TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 3); - TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A::T <1:20 1:20>"); - TS_ASSERT_EQUALS(client->templateParameterTypes[1], "A::foo::U <4:21 4:21>"); - TS_ASSERT_EQUALS(client->templateParameterTypes[2], "A::foo::U <8:20 8:20>"); + TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A::T <1:20 1:20>"); + TS_ASSERT_EQUALS(client->templateParameterTypes[1], "A::foo::U <4:21 4:21>"); + TS_ASSERT_EQUALS(client->templateParameterTypes[2], "A::foo::U <8:20 8:20>"); } - void test_cxx_parser_finds_template_argument_of_implicit_template_specialization() + void test_cxx_parser_finds_type_template_argument_of_implicit_template_specialization() { std::shared_ptr client = parseCode( "template \n" @@ -1262,6 +1334,112 @@ public: TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->int <0:0 0:0>"); } + void test_cxx_parser_finds_non_type_int_template_argument_of_implicit_template_specialization() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{\n" + "};\n" + "int main()\n" + "{\n" + " A<1> a;\n" + " return 0;\n" + "}\n" + ); + TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<1>->int <0:0 0:0>"); + } + + void test_cxx_parser_finds_non_type_bool_template_argument_of_implicit_template_specialization() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{\n" + "};\n" + "int main()\n" + "{\n" + " A a;\n" + " return 0;\n" + "}\n" + ); + TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->bool <0:0 0:0>"); + } + + void test_cxx_parser_finds_non_type_custom_pointer_template_argument_of_implicit_template_specialization() + { + std::shared_ptr client = parseCode( + "class P\n" + "{};\n" + "template \n" + "class A\n" + "{};\n" + "P p;\n" + "int main()\n" + "{\n" + " A<&p> a;\n" + "}\n" + ); + TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&p>->P <0:0 0:0>"); + } + + void test_cxx_parser_finds_non_type_custom_reference_template_argument_of_implicit_template_specialization() + { + std::shared_ptr client = parseCode( + "class P\n" + "{};\n" + "template \n" + "class A\n" + "{};\n" + "P p;\n" + "int main()\n" + "{\n" + " A

a;\n" + "}\n" + ); + TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&p>->P <0:0 0:0>"); + } + + void test_cxx_parser_finds_non_type_nullptr_template_argument_of_implicit_template_specialization() + { + std::shared_ptr client = parseCode( + "#include \n" + "template \n" + "class A\n" + "{};\n" + "int main()\n" + "{\n" + " A a;\n" + "}\n" + ); + + TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->nullptr_t <0:0 0:0>"); + } + + void test_cxx_parser_finds_template_template_argument_of_implicit_template_specialization() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{};\n" + "template typename T>\n" + "class B\n" + "{};\n" + "int main()\n" + "{\n" + " B ba;\n" + "}\n" + ); + + TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B->A <0:0 0:0>"); + } + void test_cxx_parser_finds_explicit_template_specialization() { std::shared_ptr client = parseCode( @@ -1275,7 +1453,74 @@ public: "};\n" ); TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1); - TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A -> A <6:7 6:7>"); + TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A -> A <6:7 6:7>"); + } + + void test_cxx_parser_finds_type_template_argument_of_explicit_template_specialization() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{\n" + "};\n" + "template <>\n" + "class A\n" + "{\n" + "};\n" + ); + TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->int <0:0 0:0>"); + } + + void test_cxx_parser_finds_non_type_int_template_argument_of_explicit_template_specialization() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{\n" + "};\n" + "template <>\n" + "class A<1>\n" + "{\n" + "};\n" + ); + TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<1>->int <0:0 0:0>"); + } + + void test_cxx_parser_finds_non_type_bool_template_argument_of_explicit_template_specialization() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{\n" + "};\n" + "template <>\n" + "class A\n" + "{\n" + "};\n" + ); + TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->bool <0:0 0:0>"); + } + + void test_cxx_parser_finds_template_template_argument_of_explicit_template_specialization() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{};\n" + "template typename T>\n" + "class B\n" + "{};\n" + "template <>\n" + "class B\n" + "{\n" + "};\n" + ); + + TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B->A <0:0 0:0>"); } void test_cxx_parser_finds_explicit_partial_template_specialization() @@ -1291,10 +1536,10 @@ public: "};\n" ); TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1); - TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A -> A <6:7 6:7>"); +// TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A -> A <6:7 6:7>"); } - void test_cxx_parser_finds_argument_of_explicit_partial_template_specialization() + void test_cxx_parser_finds_type_template_argument_of_explicit_partial_template_specialization() { std::shared_ptr client = parseCode( "template \n" @@ -1307,8 +1552,44 @@ public: "};\n" ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->A::T <6:9 6:9>"); - TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A->int <6:12 6:12>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->A::T <6:9 6:9>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A->int <6:12 6:12>"); + } + + void test_cxx_parser_finds_specialized_non_type_bool_template_argument_of_explicit_partial_template_specialization() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{\n" + "};\n" + "template \n" + "class A\n" + "{\n" + "};\n" + ); + + TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->bool <6:9 6:9>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A->A::U <6:15 6:15>"); + } + + void test_cxx_parser_finds_unspecialized_non_type_bool_template_argument_of_explicit_partial_template_specialization() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{\n" + "};\n" + "template \n" + "class A\n" + "{\n" + "};\n" + ); + + TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->bool <6:9 6:9>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A->int <6:12 6:12>"); } void test_cxx_parser_finds_correct_name_of_explicit_template_specialization() @@ -1324,8 +1605,8 @@ public: "};\n" ); TS_ASSERT_EQUALS(client->classes.size(), 2); - TS_ASSERT_EQUALS(client->classes[0], "A <2:1 <2:7 2:7> 4:1>"); - TS_ASSERT_EQUALS(client->classes[1], "A <5:1 <6:7 6:7> 8:1>"); + TS_ASSERT_EQUALS(client->classes[0], "A <2:1 <2:7 2:7> 4:1>"); + TS_ASSERT_EQUALS(client->classes[1], "A <5:1 <6:7 6:7> 8:1>"); } void test_cxx_parser_finds_argument_of_explicit_template_specialization() @@ -1355,7 +1636,7 @@ public: ); TS_ASSERT_EQUALS(client->fields.size(), 1); - TS_ASSERT_EQUALS(client->fields[0], "private int A::foo <4:6 4:8>"); + TS_ASSERT_EQUALS(client->fields[0], "private int A::foo <4:6 4:8>"); } void test_cxx_parser_finds_correct_type_of_field_member_of_template_class_in_declaration() @@ -1369,7 +1650,7 @@ public: ); TS_ASSERT_EQUALS(client->fields.size(), 1); - TS_ASSERT_EQUALS(client->fields[0], "private A::T A::foo <4:4 4:6>"); + TS_ASSERT_EQUALS(client->fields[0], "private A::T A::foo <4:4 4:6>"); } void test_cxx_parser_finds_implicit_template_class_specialization() @@ -1385,7 +1666,7 @@ public: ); TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1); - TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A -> A <2:7 2:7>"); + TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A -> A <2:7 2:7>"); } void test_cxx_parser_finds_class_inheritance_from_implicit_template_class_specialization() @@ -1438,7 +1719,7 @@ public: ); TS_ASSERT_EQUALS(client->usages.size(), 1); - TS_ASSERT_EQUALS(client->usages[0], "void A::A() -> A::foo <4:7 4:9>"); + TS_ASSERT_EQUALS(client->usages[0], "void A::A() -> A::foo <4:7 4:9>"); } void test_cxx_parser_finds_enum_definition_in_template_class() @@ -1456,7 +1737,7 @@ public: ); TS_ASSERT_EQUALS(client->enums.size(), 1); - TS_ASSERT_EQUALS(client->enums[0], "private A::TestType <4:2 <4:7 4:14> 8:2>"); + TS_ASSERT_EQUALS(client->enums[0], "private A::TestType <4:2 <4:7 4:14> 8:2>"); } void test_cxx_parser_finds_enum_usage_in_template_class() @@ -1475,7 +1756,7 @@ public: ); TS_ASSERT_EQUALS(client->fields.size(), 1); - TS_ASSERT_EQUALS(client->fields[0], "private A::TestType A::foo <9:11 9:13>"); + TS_ASSERT_EQUALS(client->fields[0], "private A::TestType A::foo <9:11 9:13>"); } void test_cxx_parser_finds_enum_constants_in_template_class() @@ -1493,8 +1774,8 @@ public: ); TS_ASSERT_EQUALS(client->enumConstants.size(), 2); - TS_ASSERT_EQUALS(client->enumConstants[0], "A::TestType::TEST_ONE <6:3 6:3>"); - TS_ASSERT_EQUALS(client->enumConstants[1], "A::TestType::TEST_TWO <7:3 7:3>"); + TS_ASSERT_EQUALS(client->enumConstants[0], "A::TestType::TEST_ONE <6:3 6:3>"); + TS_ASSERT_EQUALS(client->enumConstants[1], "A::TestType::TEST_TWO <7:3 7:3>"); } void test_cxx_parser_finds_correct_field_member_type_of_nested_template_class_in_declaration_____typedef() @@ -1508,7 +1789,7 @@ public: ); TS_ASSERT_EQUALS(client->typedefs.size(), 1); - TS_ASSERT_EQUALS(client->typedefs[0], "private A::T -> A::TempType <4:12 4:19>"); + TS_ASSERT_EQUALS(client->typedefs[0], "private A::T -> A::TempType <4:12 4:19>"); } void test_cxx_parser_finds_correct_field_member_type_of_nested_template_class_in_declaration() @@ -1525,7 +1806,7 @@ public: ); TS_ASSERT_EQUALS(client->fields.size(), 1); - TS_ASSERT_EQUALS(client->fields[0], "private A::T A::B::foo <6:5 6:7>"); + TS_ASSERT_EQUALS(client->fields[0], "private A::T A::B::foo <6:5 6:7>"); } void test_cxx_parser_finds_correct_method_member_name_of_template_class_in_declaration() @@ -1539,7 +1820,7 @@ public: ); TS_ASSERT_EQUALS(client->methods.size(), 1); - TS_ASSERT_EQUALS(client->methods[0], "private int A::foo() <4:6 4:8>"); + TS_ASSERT_EQUALS(client->methods[0], "private int A::foo() <4:6 4:8>"); } void test_cxx_parser_finds_correct_method_return_type_of_template_class_in_declaration() @@ -1553,7 +1834,7 @@ public: ); TS_ASSERT_EQUALS(client->methods.size(), 1); - TS_ASSERT_EQUALS(client->methods[0], "private A::T A::foo() <4:4 4:6>"); + TS_ASSERT_EQUALS(client->methods[0], "private A::T A::foo() <4:4 4:6>"); } void test_cxx_parser_finds_template_default_argument_type_of_template_class() @@ -1566,11 +1847,30 @@ public: ); TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "int -> A::T <1:24 1:26>"); + TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "int -> A::T <1:24 1:26>"); } + //void ___test_cxx_parser_skips_creating_node_for_explicit_template_specialization_with_template_parameter_without_a_name() // i think this would not be valid code... + //{ + // std::shared_ptr client = parseCode( + // "template \n" + // "class A\n" + // "{\n" + // "};\n" + // "template \n" + // "class A\n" + // "{\n" + // "};\n" + // ); + + // TS_ASSERT_EQUALS(client->classes.size(), 1); + // TS_ASSERT_EQUALS(client->classes[0], "A <2:1 <2:7 2:7> 4:1>"); + //} + + + void test_cxx_parser_finds_template_parameter_type_of_template_function() @@ -1584,7 +1884,7 @@ public: ); TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateParameterTypes[0], "test::T <1:20 1:20>"); + TS_ASSERT_EQUALS(client->templateParameterTypes[0], "test::T <1:20 1:20>"); } void test_cxx_parser_finds_implicit_specialization_of_template_function() @@ -1603,7 +1903,7 @@ public: ); TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1); - TS_ASSERT_EQUALS(client->templateSpecializations[0], "test -> test <2:3 2:6>"); + TS_ASSERT_EQUALS(client->templateSpecializations[0], "test -> test <2:3 2:6>"); } void test_cxx_parser_finds_explicit_specialization_of_template_function() @@ -1623,7 +1923,7 @@ public: ); TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1); - TS_ASSERT_EQUALS(client->templateSpecializations[0], "test -> test <8:5 8:8>"); + TS_ASSERT_EQUALS(client->templateSpecializations[0], "test -> test <8:5 8:8>"); } void test_cxx_parser_finds_template_argument_of_explicit_specialization_of_template_function() @@ -1676,7 +1976,7 @@ public: "};\n" ); TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "int -> test::T <1:24 1:26>"); + TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "int -> test::T <1:24 1:26>"); } @@ -1898,7 +2198,7 @@ private: return 0; } - virtual Id onTemplateArgumentParsed( + virtual Id onTemplateArgumentTypeParsed( const ParseLocation& location, const std::vector& templateArgumentTypeNameHierarchy, const std::vector& templateRecordNameHierarchy) {