From bdd5066665b47b57c6caff9b44c27665d77b0d3c Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Fri, 12 Jan 2018 09:44:05 +0100 Subject: [PATCH] Clang: introduce more data in TokenInfo Data added: - return type spelling for functions - parent spelling - access specifier for class fields and methods - storage class New highlighting types are added, therefore types are now categorized by class, struct, etc. Change-Id: I1739b94a6f777045fde655060d8b9a12b6e0889b Reviewed-by: Nikolai Kosjar --- src/libs/clangsupport/clangsupport_global.h | 28 +++- src/libs/clangsupport/tokeninfocontainer.cpp | 11 ++ src/libs/clangsupport/tokeninfocontainer.h | 54 ++++++- .../clangtokeninfosreporter.cpp | 29 +++- src/tools/clangbackend/source/clangtype.cpp | 5 + src/tools/clangbackend/source/clangtype.h | 1 + src/tools/clangbackend/source/cursor.cpp | 45 ++++++ src/tools/clangbackend/source/cursor.h | 4 + src/tools/clangbackend/source/tokeninfo.cpp | 147 ++++++++++++++---- src/tools/clangbackend/source/tokeninfo.h | 6 + .../unittest/clangcodemodelserver-test.cpp | 4 +- tests/unit/unittest/cursor-test.cpp | 90 +++++++++++ tests/unit/unittest/data/cursor.cpp | 8 + tests/unit/unittest/data/cursor.h | 2 + .../unit/unittest/data/highlightingmarks.cpp | 4 +- .../unit/unittest/gtest-creator-printing.cpp | 7 + tests/unit/unittest/tokeninfos-test.cpp | 76 ++++----- 17 files changed, 449 insertions(+), 72 deletions(-) diff --git a/src/libs/clangsupport/clangsupport_global.h b/src/libs/clangsupport/clangsupport_global.h index 67830143f6c..df34e2963eb 100644 --- a/src/libs/clangsupport/clangsupport_global.h +++ b/src/libs/clangsupport/clangsupport_global.h @@ -88,7 +88,33 @@ enum class HighlightingType : quint8 Label, Declaration, FunctionDefinition, - OutputArgument + OutputArgument, + Namespace, + Class, + Struct, + Enum, + Union, + TypeAlias, + Typedef +}; + +enum class StorageClass : quint8 +{ + Invalid, + None, + Extern, + Static, + PrivateExtern, + Auto, + Register +}; + +enum class AccessSpecifier : quint8 +{ + Invalid, + Public, + Protected, + Private }; enum class CompletionCorrection : quint32 diff --git a/src/libs/clangsupport/tokeninfocontainer.cpp b/src/libs/clangsupport/tokeninfocontainer.cpp index 64cb274f163..209ddd57608 100644 --- a/src/libs/clangsupport/tokeninfocontainer.cpp +++ b/src/libs/clangsupport/tokeninfocontainer.cpp @@ -52,6 +52,13 @@ static const char *highlightingTypeToCStringLiteral(HighlightingType type) RETURN_TEXT_FOR_CASE(OutputArgument); RETURN_TEXT_FOR_CASE(PreprocessorDefinition); RETURN_TEXT_FOR_CASE(PreprocessorExpansion); + RETURN_TEXT_FOR_CASE(Namespace); + RETURN_TEXT_FOR_CASE(Class); + RETURN_TEXT_FOR_CASE(Struct); + RETURN_TEXT_FOR_CASE(Enum); + RETURN_TEXT_FOR_CASE(Union); + RETURN_TEXT_FOR_CASE(TypeAlias); + RETURN_TEXT_FOR_CASE(Typedef); default: return "UnhandledHighlightingType"; } } @@ -66,6 +73,10 @@ QDebug operator<<(QDebug debug, const TokenInfoContainer &container) << highlightingTypeToCStringLiteral(container.types().mainHighlightingType) << ", " << container.token() << ", " << container.typeSpelling() << ", " + << container.returnTypeSpelling() << ", " + << container.semanticParentTypeSpelling() << ", " + << static_cast(container.accessSpecifier()) << ", " + << static_cast(container.storageClass()) << ", " << container.isIdentifier() << ", " << container.isIncludeDirectivePath() << ", " << container.isDeclaration() << ", " diff --git a/src/libs/clangsupport/tokeninfocontainer.h b/src/libs/clangsupport/tokeninfocontainer.h index 9d84cdade89..27e0e940d7b 100644 --- a/src/libs/clangsupport/tokeninfocontainer.h +++ b/src/libs/clangsupport/tokeninfocontainer.h @@ -62,7 +62,10 @@ class TokenInfoContainer public: TokenInfoContainer() = default; TokenInfoContainer(uint line, uint column, uint length, HighlightingTypes types, - const Utf8String &token, const Utf8String &typeSpelling, + const Utf8String &token,const Utf8String &typeSpelling, + const Utf8String &returnTypeSpelling, + const Utf8String &semanticParentTypeSpelling, + AccessSpecifier accessSpecifier, StorageClass storageClass, bool isIdentifier = false, bool isIncludeDirectivePath = false, bool isDeclaration = false, bool isDefinition = false) : line_(line), @@ -70,7 +73,11 @@ public: length_(length), types_(types), token_(token), - typeSpelling_(typeSpelling) + typeSpelling_(typeSpelling), + returnTypeSpelling_(returnTypeSpelling), + semanticParentTypeSpelling_(semanticParentTypeSpelling), + accessSpecifier_(accessSpecifier), + storageClass_(storageClass) { bitFields_.set(BitField::Identifier, isIdentifier); bitFields_.set(BitField::IncludeDirectivePath, isIncludeDirectivePath); @@ -141,6 +148,25 @@ public: return typeSpelling_; } + const Utf8String returnTypeSpelling() const + { + return returnTypeSpelling_; + } + + const Utf8String semanticParentTypeSpelling() const + { + return semanticParentTypeSpelling_; + } + + AccessSpecifier accessSpecifier() const + { + return accessSpecifier_; + } + + StorageClass storageClass() const + { + return storageClass_; + } friend QDataStream &operator<<(QDataStream &out, const TokenInfoContainer &container) { @@ -150,6 +176,10 @@ public: out << container.types_; out << container.token_; out << container.typeSpelling_; + out << container.returnTypeSpelling_; + out << container.semanticParentTypeSpelling_; + out << static_cast(container.accessSpecifier_); + out << static_cast(container.storageClass_); out << container.bitFields_; return out; @@ -163,6 +193,16 @@ public: in >> container.types_; in >> container.token_ ; in >> container.typeSpelling_; + in >> container.returnTypeSpelling_; + in >> container.semanticParentTypeSpelling_; + + uint accessSpecifier; + uint storageClass; + in >> accessSpecifier; + in >> storageClass; + container.accessSpecifier_ = static_cast(accessSpecifier); + container.storageClass_ = static_cast(storageClass); + in >> container.bitFields_; return in; @@ -174,6 +214,12 @@ public: && first.column_ == second.column_ && first.length_ == second.length_ && first.types_ == second.types_ + && first.token_ == second.token_ + && first.typeSpelling_ == second.typeSpelling_ + && first.returnTypeSpelling_ == second.returnTypeSpelling_ + && first.semanticParentTypeSpelling_ == second.semanticParentTypeSpelling_ + && first.accessSpecifier_ == second.accessSpecifier_ + && first.storageClass_ == second.storageClass_ && first.bitFields_ == second.bitFields_; } @@ -184,6 +230,10 @@ private: HighlightingTypes types_; Utf8String token_; Utf8String typeSpelling_; + Utf8String returnTypeSpelling_; + Utf8String semanticParentTypeSpelling_; + AccessSpecifier accessSpecifier_; + StorageClass storageClass_; ByteSizeBitset bitFields_; }; diff --git a/src/plugins/clangcodemodel/clangtokeninfosreporter.cpp b/src/plugins/clangcodemodel/clangtokeninfosreporter.cpp index 913861c2677..a7a116e3486 100644 --- a/src/plugins/clangcodemodel/clangtokeninfosreporter.cpp +++ b/src/plugins/clangcodemodel/clangtokeninfosreporter.cpp @@ -78,9 +78,30 @@ TextEditor::TextStyle toTextStyle(ClangBackEnd::HighlightingType type) case HighlightingType::Invalid: QTC_CHECK(false); // never called return TextEditor::C_TEXT; + default: + break; + } + Q_UNREACHABLE(); +} + +bool ignore(ClangBackEnd::HighlightingType type) +{ + using ClangBackEnd::HighlightingType; + + switch (type) { + default: + break; + case HighlightingType::Namespace: + case HighlightingType::Class: + case HighlightingType::Struct: + case HighlightingType::Enum: + case HighlightingType::Union: + case HighlightingType::TypeAlias: + case HighlightingType::Typedef: + return true; } - Q_UNREACHABLE(); + return false; } TextEditor::TextStyles toTextStyles(ClangBackEnd::HighlightingTypes types) @@ -90,8 +111,10 @@ TextEditor::TextStyles toTextStyles(ClangBackEnd::HighlightingTypes types) textStyles.mainStyle = toTextStyle(types.mainHighlightingType); - for (ClangBackEnd::HighlightingType type : types.mixinHighlightingTypes) - textStyles.mixinStyles.push_back(toTextStyle(type)); + for (ClangBackEnd::HighlightingType type : types.mixinHighlightingTypes) { + if (!ignore(type)) + textStyles.mixinStyles.push_back(toTextStyle(type)); + } return textStyles; } diff --git a/src/tools/clangbackend/source/clangtype.cpp b/src/tools/clangbackend/source/clangtype.cpp index 970b9452c1d..42299e2e51b 100644 --- a/src/tools/clangbackend/source/clangtype.cpp +++ b/src/tools/clangbackend/source/clangtype.cpp @@ -206,6 +206,11 @@ Type Type::pointeeType() const return clang_getPointeeType(cxType); } +Type Type::resultType() const +{ + return clang_getResultType(cxType); +} + Type Type::argument(int index) const { return clang_getArgType(cxType, index); diff --git a/src/tools/clangbackend/source/clangtype.h b/src/tools/clangbackend/source/clangtype.h index 6be968d3901..fc02e285df2 100644 --- a/src/tools/clangbackend/source/clangtype.h +++ b/src/tools/clangbackend/source/clangtype.h @@ -64,6 +64,7 @@ public: Type canonical() const; Type classType() const; Type pointeeType() const; + Type resultType() const; Type argument(int index) const; Cursor declaration() const; diff --git a/src/tools/clangbackend/source/cursor.cpp b/src/tools/clangbackend/source/cursor.cpp index 8b9b22f7cc5..7978e914b21 100644 --- a/src/tools/clangbackend/source/cursor.cpp +++ b/src/tools/clangbackend/source/cursor.cpp @@ -436,6 +436,51 @@ CXCursor Cursor::cx() const return cxCursor; } +StorageClass Cursor::storageClass() const +{ + CXCursor cursor = cxCursor; + if (!isDeclaration()) + cursor = referenced().cxCursor; + const CX_StorageClass cxStorageClass = clang_Cursor_getStorageClass(cursor); + switch (cxStorageClass) { + case CX_SC_Invalid: + case CX_SC_OpenCLWorkGroupLocal: + break; + case CX_SC_None: + return StorageClass::None; + case CX_SC_Extern: + return StorageClass::Extern; + case CX_SC_Static: + return StorageClass::Static; + case CX_SC_PrivateExtern: + return StorageClass::PrivateExtern; + case CX_SC_Auto: + return StorageClass::Auto; + case CX_SC_Register: + return StorageClass::Register; + } + return StorageClass::Invalid; +} + +AccessSpecifier Cursor::accessSpecifier() const +{ + CXCursor cursor = cxCursor; + if (!isDeclaration()) + cursor = referenced().cxCursor; + const CX_CXXAccessSpecifier cxAccessSpecifier = clang_getCXXAccessSpecifier(cursor); + switch (cxAccessSpecifier) { + case CX_CXXInvalidAccessSpecifier: + break; + case CX_CXXPublic: + return AccessSpecifier::Public; + case CX_CXXProtected: + return AccessSpecifier::Protected; + case CX_CXXPrivate: + return AccessSpecifier::Private; + } + return AccessSpecifier::Invalid; +} + bool operator==(const Cursor &first, const Cursor &second) { return clang_equalCursors(first.cxCursor, second.cxCursor); diff --git a/src/tools/clangbackend/source/cursor.h b/src/tools/clangbackend/source/cursor.h index bef5a006f4f..b13ae52d867 100644 --- a/src/tools/clangbackend/source/cursor.h +++ b/src/tools/clangbackend/source/cursor.h @@ -27,6 +27,8 @@ #include "clangtype.h" +#include + #include #include @@ -107,6 +109,8 @@ public: unsigned overloadedDeclarationsCount() const; Cursor overloadedDeclaration(unsigned index) const; Cursor specializedCursorTemplate() const; + AccessSpecifier accessSpecifier() const; + StorageClass storageClass() const; CXFile includedFile() const; diff --git a/src/tools/clangbackend/source/tokeninfo.cpp b/src/tools/clangbackend/source/tokeninfo.cpp index a9c84312861..3cc9ba38f97 100644 --- a/src/tools/clangbackend/source/tokeninfo.cpp +++ b/src/tools/clangbackend/source/tokeninfo.cpp @@ -32,6 +32,8 @@ #include "sourcerange.h" #include "sourcerangecontainer.h" +#include + #include namespace ClangBackEnd { @@ -114,6 +116,8 @@ bool TokenInfo::hasFunctionArguments() const TokenInfo::operator TokenInfoContainer() const { return TokenInfoContainer(m_line, m_column, m_length, m_types, m_token, m_typeSpelling, + m_resultTypeSpelling, m_semanticParentTypeSpelling, + m_accessSpecifier, m_storageClass, m_isIdentifier, m_isInclusion, m_isDeclaration, m_isDefinition); } @@ -142,6 +146,8 @@ bool isFunctionInFinalClass(const Cursor &cursor) void TokenInfo::memberReferenceKind(const Cursor &cursor) { if (cursor.isDynamicCall()) { + m_storageClass = cursor.storageClass(); + m_accessSpecifier = cursor.accessSpecifier(); if (isFinalFunction(cursor) || isFunctionInFinalClass(cursor)) m_types.mainHighlightingType = HighlightingType::Function; else @@ -151,22 +157,6 @@ void TokenInfo::memberReferenceKind(const Cursor &cursor) } } -void TokenInfo::referencedTypeKind(const Cursor &cursor) -{ - const Cursor referencedCursor = cursor.referenced(); - - switch (referencedCursor.kind()) { - case CXCursor_ClassDecl: - case CXCursor_StructDecl: - case CXCursor_UnionDecl: - case CXCursor_TypedefDecl: - case CXCursor_TemplateTypeParameter: - case CXCursor_TypeAliasDecl: - case CXCursor_EnumDecl: m_types.mainHighlightingType = HighlightingType::Type; break; - default: m_types.mainHighlightingType = HighlightingType::Invalid; break; - } -} - void TokenInfo::overloadedDeclRefKind(const Cursor &cursor) { m_types.mainHighlightingType = HighlightingType::Function; @@ -183,6 +173,7 @@ void TokenInfo::overloadedDeclRefKind(const Cursor &cursor) void TokenInfo::variableKind(const Cursor &cursor) { + m_storageClass = cursor.storageClass(); if (cursor.isLocalVariable()) m_types.mainHighlightingType = HighlightingType::LocalVariable; else @@ -192,8 +183,10 @@ void TokenInfo::variableKind(const Cursor &cursor) m_types.mixinHighlightingTypes.push_back(HighlightingType::OutputArgument); } -void TokenInfo::fieldKind(const Cursor &) +void TokenInfo::fieldKind(const Cursor &cursor) { + m_accessSpecifier = cursor.accessSpecifier(); + m_storageClass = cursor.storageClass(); m_types.mainHighlightingType = HighlightingType::Field; if (isOutputArgument()) @@ -290,6 +283,11 @@ void TokenInfo::filterOutPreviousOutputArguments() void TokenInfo::functionKind(const Cursor &cursor, Recursion recursion) { + updateTypeSpelling(cursor, true); + + m_accessSpecifier = cursor.accessSpecifier(); + m_storageClass = cursor.storageClass(); + if (isRealDynamicCall(cursor) || isVirtualMethodDeclarationOrDefinition(cursor)) m_types.mainHighlightingType = HighlightingType::VirtualFunction; else @@ -304,14 +302,106 @@ void TokenInfo::functionKind(const Cursor &cursor, Recursion recursion) addExtraTypeIfFirstPass(HighlightingType::FunctionDefinition, recursion); } +Utf8String fullyQualifiedType(const Cursor &cursor) +{ + Utf8String typeSpelling = cursor.type().canonical().utf8Spelling(); + if (typeSpelling.isEmpty()) { + // Only if it's the namespaces level. + typeSpelling = cursor.unifiedSymbolResolution(); + typeSpelling.replace(Utf8StringLiteral("c:@N@"), Utf8StringLiteral("")); + typeSpelling.replace(Utf8StringLiteral("@N@"), Utf8StringLiteral("::")); + } + return typeSpelling; +} + +void TokenInfo::updateTypeSpelling(const Cursor &cursor, bool functionLike) +{ + m_typeSpelling = fullyQualifiedType(cursor); + m_semanticParentTypeSpelling = fullyQualifiedType(cursor.semanticParent()); + if (!functionLike) + return; + Type type = cursor.type().canonical(); + m_resultTypeSpelling = type.resultType().utf8Spelling(); + const bool hasSpaceAfterReturnVal + = m_typeSpelling.constData()[m_resultTypeSpelling.byteSize()] == ' '; + m_typeSpelling = m_typeSpelling.mid(m_resultTypeSpelling.byteSize() + + (hasSpaceAfterReturnVal ? 1 : 0)); +} + +void TokenInfo::referencedTypeKind(const Cursor &cursor) +{ + const Cursor ref = cursor.referenced(); + updateTypeSpelling(ref); + typeKind(ref); +} + +void TokenInfo::typeKind(const Cursor &cursor) +{ + m_types.mainHighlightingType = HighlightingType::Type; + const CXCursorKind kind = cursor.kind(); + switch (kind) { + default: + m_types.mainHighlightingType = HighlightingType::Invalid; + return; + case CXCursor_TemplateRef: + case CXCursor_NamespaceRef: + case CXCursor_TypeRef: + referencedTypeKind(cursor); + return; + case CXCursor_ClassTemplate: + case CXCursor_ClassTemplatePartialSpecialization: + case CXCursor_ClassDecl: + m_types.mixinHighlightingTypes.push_back(HighlightingType::Class); + return; + case CXCursor_UnionDecl: + m_types.mixinHighlightingTypes.push_back(HighlightingType::Union); + return; + case CXCursor_StructDecl: + m_types.mixinHighlightingTypes.push_back(HighlightingType::Struct); + return; + case CXCursor_EnumDecl: + m_types.mixinHighlightingTypes.push_back(HighlightingType::Enum); + return; + case CXCursor_NamespaceAlias: + case CXCursor_Namespace: + m_types.mixinHighlightingTypes.push_back(HighlightingType::Namespace); + return; + case CXCursor_TypeAliasDecl: + m_types.mixinHighlightingTypes.push_back(HighlightingType::TypeAlias); + return; + case CXCursor_TypedefDecl: + m_types.mixinHighlightingTypes.push_back(HighlightingType::Typedef); + return; + case CXCursor_TemplateTypeParameter: + case CXCursor_TemplateTemplateParameter: + case CXCursor_CXXStaticCastExpr: + case CXCursor_CXXReinterpretCastExpr: + case CXCursor_ObjCCategoryDecl: + case CXCursor_ObjCCategoryImplDecl: + case CXCursor_ObjCImplementationDecl: + case CXCursor_ObjCInterfaceDecl: + case CXCursor_ObjCProtocolDecl: + case CXCursor_ObjCProtocolRef: + case CXCursor_ObjCClassRef: + case CXCursor_ObjCSuperClassRef: + break; + } +} + void TokenInfo::identifierKind(const Cursor &cursor, Recursion recursion) { - m_isIdentifier = (cursor.kind() != CXCursor_PreprocessingDirective); + // For now save type spelling only for declarations. + if (m_isDeclaration) + updateTypeSpelling(cursor); - switch (cursor.kind()) { + const CXCursorKind kind = cursor.kind(); + m_isIdentifier = (kind != CXCursor_PreprocessingDirective); + + switch (kind) { case CXCursor_Destructor: case CXCursor_Constructor: case CXCursor_FunctionDecl: + case CXCursor_FunctionTemplate: case CXCursor_CallExpr: case CXCursor_CXXMethod: functionKind(cursor, recursion); break; case CXCursor_NonTypeTemplateParameter: m_types.mainHighlightingType = HighlightingType::LocalVariable; break; @@ -327,21 +417,22 @@ void TokenInfo::identifierKind(const Cursor &cursor, Recursion recursion) case CXCursor_ObjCInstanceMethodDecl: case CXCursor_ObjCSynthesizeDecl: case CXCursor_ObjCDynamicDecl: m_types.mainHighlightingType = HighlightingType::Field; break; + case CXCursor_TemplateRef: + case CXCursor_NamespaceRef: case CXCursor_TypeRef: referencedTypeKind(cursor); break; case CXCursor_ClassDecl: + case CXCursor_ClassTemplate: case CXCursor_ClassTemplatePartialSpecialization: - case CXCursor_TemplateTypeParameter: - case CXCursor_TemplateTemplateParameter: case CXCursor_UnionDecl: case CXCursor_StructDecl: - case CXCursor_TemplateRef: - case CXCursor_Namespace: - case CXCursor_NamespaceRef: + case CXCursor_EnumDecl: + case CXCursor_Namespace: m_types.mixinHighlightingTypes.push_back(HighlightingType::Declaration); + Q_FALLTHROUGH(); + case CXCursor_TemplateTypeParameter: + case CXCursor_TemplateTemplateParameter: case CXCursor_NamespaceAlias: case CXCursor_TypeAliasDecl: case CXCursor_TypedefDecl: - case CXCursor_ClassTemplate: - case CXCursor_EnumDecl: case CXCursor_CXXStaticCastExpr: case CXCursor_CXXReinterpretCastExpr: case CXCursor_ObjCCategoryDecl: @@ -351,9 +442,8 @@ void TokenInfo::identifierKind(const Cursor &cursor, Recursion recursion) case CXCursor_ObjCProtocolDecl: case CXCursor_ObjCProtocolRef: case CXCursor_ObjCClassRef: - case CXCursor_ObjCSuperClassRef: m_types.mainHighlightingType = HighlightingType::Type; break; + case CXCursor_ObjCSuperClassRef: typeKind(cursor); break; case CXCursor_OverloadedDeclRef: overloadedDeclRefKind(cursor); break; - case CXCursor_FunctionTemplate: m_types.mainHighlightingType = HighlightingType::Function; break; case CXCursor_EnumConstantDecl: m_types.mainHighlightingType = HighlightingType::Enumeration; break; case CXCursor_PreprocessingDirective: m_types.mainHighlightingType = HighlightingType::Preprocessor; break; case CXCursor_MacroExpansion: m_types.mainHighlightingType = HighlightingType::PreprocessorExpansion; break; @@ -451,7 +541,6 @@ void TokenInfo::collectKinds(CXTranslationUnit cxTranslationUnit, m_types = HighlightingTypes(); m_token = ClangString(clang_getTokenSpelling(cxTranslationUnit, *cxToken)); - m_typeSpelling = cursor.type().utf8Spelling(); if (cxTokenKind == CXToken_Identifier) { m_isDeclaration = cursor.isDeclaration(); diff --git a/src/tools/clangbackend/source/tokeninfo.h b/src/tools/clangbackend/source/tokeninfo.h index 0a19a8792df..b2d72985bbb 100644 --- a/src/tools/clangbackend/source/tokeninfo.h +++ b/src/tools/clangbackend/source/tokeninfo.h @@ -93,6 +93,7 @@ private: void functionKind(const Cursor &cursor, Recursion recursion); void memberReferenceKind(const Cursor &cursor); HighlightingType punctuationKind(const Cursor &cursor); + void typeKind(const Cursor &cursor); void collectKinds(CXTranslationUnit cxTranslationUnit, CXToken *cxToken, const Cursor &cursor); bool isRealDynamicCall(const Cursor &cursor) const; void addExtraTypeIfFirstPass(HighlightingType type, Recursion recursion); @@ -100,6 +101,7 @@ private: void collectOutputArguments(const Cursor &cursor); void filterOutPreviousOutputArguments(); bool isArgumentInCurrentOutputArgumentLocations() const; + void updateTypeSpelling(const Cursor &cursor, bool functionLike = false); private: std::vector *m_currentOutputArgumentRanges = nullptr; @@ -111,6 +113,10 @@ private: HighlightingTypes m_types; Utf8String m_token; Utf8String m_typeSpelling; + Utf8String m_resultTypeSpelling; + Utf8String m_semanticParentTypeSpelling; + AccessSpecifier m_accessSpecifier = AccessSpecifier::Invalid; + StorageClass m_storageClass = StorageClass::Invalid; bool m_isIdentifier = false; bool m_isInclusion = false; bool m_isDeclaration = false; diff --git a/tests/unit/unittest/clangcodemodelserver-test.cpp b/tests/unit/unittest/clangcodemodelserver-test.cpp index df4afa8004b..a598ab620b7 100644 --- a/tests/unit/unittest/clangcodemodelserver-test.cpp +++ b/tests/unit/unittest/clangcodemodelserver-test.cpp @@ -670,7 +670,9 @@ void ClangCodeModelServer::expectDocumentAnnotationsChangedForFileBWithSpecificH types.mixinHighlightingTypes.push_back(ClangBackEnd::HighlightingType::Declaration); types.mixinHighlightingTypes.push_back(ClangBackEnd::HighlightingType::FunctionDefinition); const TokenInfoContainer tokenInfo(1, 6, 8, types, Utf8String("function", 8), - Utf8String("void (int)", 10), true, false, true, true); + Utf8String("(int)", 5), Utf8String("void", 4), + Utf8String(), AccessSpecifier::Invalid, + StorageClass::None, true, false, true, true); EXPECT_CALL(mockClangCodeModelClient, documentAnnotationsChanged( diff --git a/tests/unit/unittest/cursor-test.cpp b/tests/unit/unittest/cursor-test.cpp index e229c6522a1..4aa2cf0bb9b 100644 --- a/tests/unit/unittest/cursor-test.cpp +++ b/tests/unit/unittest/cursor-test.cpp @@ -803,6 +803,96 @@ TEST_F(Cursor, ConstReferenceIsNotOutputArgument) ASSERT_FALSE(argument.isOutputArgument()); } +TEST_F(Cursor, ResultType) +{ + auto methodCursor = translationUnit.cursorAt(31, 18); + + Utf8String resultType = methodCursor.type().resultType().spelling(); + + ASSERT_THAT(resultType, Utf8String("bool", 4)); +} + +TEST_F(Cursor, PrivateMethodAccessSpecifier) +{ + auto methodCursor = translationUnit.cursorAt(16, 17); + + auto accessSpecifier = methodCursor.accessSpecifier(); + + ASSERT_THAT(accessSpecifier, ClangBackEnd::AccessSpecifier::Private); +} + +TEST_F(Cursor, PublicMethodAccessSpecifier) +{ + auto methodCursor = translationUnit.cursorAt(79, 25); + + auto accessSpecifier = methodCursor.accessSpecifier(); + + ASSERT_THAT(accessSpecifier, ClangBackEnd::AccessSpecifier::Public); +} + +TEST_F(Cursor, ProtectedMethodAccessSpecifier) +{ + auto methodCursor = translationUnit.cursorAt(131, 22); + + auto accessSpecifier = methodCursor.accessSpecifier(); + + ASSERT_THAT(accessSpecifier, ClangBackEnd::AccessSpecifier::Protected); +} + +TEST_F(Cursor, PrivateFieldAccessSpecifier) +{ + auto fieldCursor = translationUnit.cursorAt(21, 12); + + auto accessSpecifier = fieldCursor.accessSpecifier(); + + ASSERT_THAT(accessSpecifier, ClangBackEnd::AccessSpecifier::Private); +} + +TEST_F(Cursor, InvalidAccessSpecifier) +{ + auto localVarCursor = translationUnit.cursorAt(62, 9); + + auto accessSpecifier = localVarCursor.accessSpecifier(); + + ASSERT_THAT(accessSpecifier, ClangBackEnd::AccessSpecifier::Invalid); +} + +TEST_F(Cursor, NoStorageClass) +{ + auto localVarCursor = translationUnit.cursorAt(62, 9); + + auto storageClass = localVarCursor.storageClass(); + + ASSERT_THAT(storageClass, ClangBackEnd::StorageClass::None); +} + +TEST_F(Cursor, ExternVarStorageClass) +{ + auto externalVarCursor = translationUnit.cursorAt(133, 12); + + auto storageClass = externalVarCursor.storageClass(); + + ASSERT_THAT(storageClass, ClangBackEnd::StorageClass::Extern); +} + +TEST_F(Cursor, StaticMethodStorageClass) +{ + auto methodCursor = translationUnit.cursorAt(135, 13); + + auto storageClass = methodCursor.storageClass(); + + ASSERT_THAT(storageClass, ClangBackEnd::StorageClass::Static); +} + +TEST_F(Cursor, InvalidStorageClass) +{ + auto functionTemplateCursor = translationUnit.cursorAt(137, 28); + + auto storageClass = functionTemplateCursor.storageClass(); + + ASSERT_THAT(storageClass, ClangBackEnd::StorageClass::Invalid); +} + Data *Cursor::d; void Cursor::SetUpTestCase() diff --git a/tests/unit/unittest/data/cursor.cpp b/tests/unit/unittest/data/cursor.cpp index a492867dd6b..218e6852f52 100644 --- a/tests/unit/unittest/data/cursor.cpp +++ b/tests/unit/unittest/data/cursor.cpp @@ -127,3 +127,11 @@ void PointerToConst(const int *); void Pointer(int *); void ConstantPointer(int *const); void ConstIntegerValue(const int); + +void NonFinalStruct::ProtectedMethodAccessSpecifier() {} + +extern int ExternVarStorageClass; + +static void StaticMethodStorageClass() {} + +template const T &InvalidStorageClass(const T &type) { return type; } diff --git a/tests/unit/unittest/data/cursor.h b/tests/unit/unittest/data/cursor.h index 3e9e9a2bfb9..7db9be6e97b 100644 --- a/tests/unit/unittest/data/cursor.h +++ b/tests/unit/unittest/data/cursor.h @@ -39,4 +39,6 @@ struct NonFinalStruct { virtual void FinalVirtualMethod() final; void function(); +protected: + void ProtectedMethodAccessSpecifier(); }; diff --git a/tests/unit/unittest/data/highlightingmarks.cpp b/tests/unit/unittest/data/highlightingmarks.cpp index 83df72fa101..778d74cc264 100644 --- a/tests/unit/unittest/data/highlightingmarks.cpp +++ b/tests/unit/unittest/data/highlightingmarks.cpp @@ -331,7 +331,7 @@ void f14() using IntegerAlias = int; using SecondIntegerAlias = IntegerAlias; -using IntegerTypedef = int; +typedef int IntegerTypedef; using Function = void (*)(); @@ -588,3 +588,5 @@ void BaseClass::VirtualFunction() {} class WithVirtualFunctionDefined { virtual void VirtualFunctionDefinition() {}; }; + +namespace NFoo { namespace NBar { namespace NTest { class NamespaceTypeSpelling; } } } diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index 66109d8b3f9..a6fb6dbf1d9 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -490,6 +490,13 @@ static const char *highlightingTypeToCStringLiteral(HighlightingType type) RETURN_TEXT_FOR_CASE(PreprocessorExpansion); RETURN_TEXT_FOR_CASE(PrimitiveType); RETURN_TEXT_FOR_CASE(Declaration); + RETURN_TEXT_FOR_CASE(Namespace); + RETURN_TEXT_FOR_CASE(Class); + RETURN_TEXT_FOR_CASE(Struct); + RETURN_TEXT_FOR_CASE(Enum); + RETURN_TEXT_FOR_CASE(Union); + RETURN_TEXT_FOR_CASE(TypeAlias); + RETURN_TEXT_FOR_CASE(Typedef); } return ""; diff --git a/tests/unit/unittest/tokeninfos-test.cpp b/tests/unit/unittest/tokeninfos-test.cpp index 0d9b34f4b67..0830829026a 100644 --- a/tests/unit/unittest/tokeninfos-test.cpp +++ b/tests/unit/unittest/tokeninfos-test.cpp @@ -75,9 +75,8 @@ MATCHER_P4(IsHighlightingMark, line, column, length, type, + PrintToString(TokenInfo(line, column, length, type)) ) { - const TokenInfo expected(line, column, length, type); - - return arg == expected; + return arg.line() == line && arg.column() == column && arg.length() == length + && arg.types().mainHighlightingType == type; } MATCHER_P(HasOnlyType, type, @@ -396,7 +395,7 @@ TEST_F(TokenInfos, Enumeration) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(118, 17)); - ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Enum)); } TEST_F(TokenInfos, Enumerator) @@ -410,7 +409,7 @@ TEST_F(TokenInfos, EnumerationReferenceDeclarationType) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(125, 28)); - ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Enum)); } TEST_F(TokenInfos, EnumerationReferenceDeclarationVariable) @@ -438,7 +437,7 @@ TEST_F(TokenInfos, ClassForwardDeclaration) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(130, 12)); - ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Class)); } TEST_F(TokenInfos, ConstructorDeclaration) @@ -459,14 +458,14 @@ TEST_F(TokenInfos, ClassForwardDeclarationReference) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(138, 23)); - ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Class)); } TEST_F(TokenInfos, ClassTypeReference) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(140, 32)); - ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Class)); } TEST_F(TokenInfos, ConstructorReferenceVariable) @@ -480,14 +479,14 @@ TEST_F(TokenInfos, UnionDeclaration) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(145, 12)); - ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Union)); } TEST_F(TokenInfos, UnionDeclarationReference) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(150, 33)); - ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Union)); } TEST_F(TokenInfos, GlobalVariable) @@ -501,21 +500,21 @@ TEST_F(TokenInfos, StructDeclaration) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(50, 11)); - ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Struct)); } TEST_F(TokenInfos, NameSpace) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(160, 22)); - ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Namespace)); } TEST_F(TokenInfos, NameSpaceAlias) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(164, 38)); - ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[1], HasTwoTypes(HighlightingType::Type, HighlightingType::Namespace)); } TEST_F(TokenInfos, UsingStructInNameSpace) @@ -529,14 +528,14 @@ TEST_F(TokenInfos, NameSpaceReference) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(166, 35)); - ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Namespace)); } TEST_F(TokenInfos, StructInNameSpaceReference) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(166, 35)); - ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[2], HasTwoTypes(HighlightingType::Type, HighlightingType::Struct)); } TEST_F(TokenInfos, VirtualFunctionDeclaration) @@ -676,7 +675,7 @@ TEST_F(TokenInfos, TemplateDefaultParameter) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(265, 135)); - ASSERT_THAT(infos[5], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[5], HasTwoTypes(HighlightingType::Type, HighlightingType::Struct)); } TEST_F(TokenInfos, NonTypeTemplateParameter) @@ -704,14 +703,14 @@ TEST_F(TokenInfos, TemplateTemplateParameterDefaultArgument) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(265, 135)); - ASSERT_THAT(infos[19], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[19], HasTwoTypes(HighlightingType::Type, HighlightingType::Class)); } TEST_F(TokenInfos, TemplateFunctionDeclaration) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(266, 63)); - ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Function)); + ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Function, HighlightingType::Declaration, HighlightingType::FunctionDefinition)); } TEST_F(TokenInfos, TemplateTypeParameterReference) @@ -824,7 +823,7 @@ TEST_F(TokenInfos, EnumerationType) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(316, 30)); - ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[3], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Enum)); } TEST_F(TokenInfos, TypeInStaticCast) @@ -861,49 +860,49 @@ TEST_F(TokenInfos, IntegerAliasDeclaration) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(333, 41)); - ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[1], HasTwoTypes(HighlightingType::Type, HighlightingType::TypeAlias)); } TEST_F(TokenInfos, IntegerAlias) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(341, 31)); - ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::TypeAlias)); } TEST_F(TokenInfos, SecondIntegerAlias) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(342, 43)); - ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::TypeAlias)); } TEST_F(TokenInfos, IntegerTypedef) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(343, 35)); - ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Typedef)); } TEST_F(TokenInfos, FunctionAlias) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(344, 16)); - ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::TypeAlias)); } TEST_F(TokenInfos, FriendTypeDeclaration) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(350, 28)); - ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[2], HasTwoTypes(HighlightingType::Type, HighlightingType::Class)); } TEST_F(TokenInfos, FriendArgumentTypeDeclaration) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(351, 65)); - ASSERT_THAT(infos[6], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[6], HasTwoTypes(HighlightingType::Type, HighlightingType::Class)); } TEST_F(TokenInfos, FriendArgumentDeclaration) @@ -931,14 +930,14 @@ TEST_F(TokenInfos, TemplatedType) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(377, 21)); - ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Class)); } TEST_F(TokenInfos, TemplatedTypeDeclaration) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(384, 49)); - ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Class)); } TEST_F(TokenInfos, NoOperator) @@ -959,21 +958,21 @@ TEST_F(TokenInfos, TemplateClassNamespace) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(413, 78)); - ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Namespace)); } TEST_F(TokenInfos, TemplateClass) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(413, 78)); - ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[2], HasTwoTypes(HighlightingType::Type, HighlightingType::Class)); } TEST_F(TokenInfos, TemplateClassParameter) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(413, 78)); - ASSERT_THAT(infos[4], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[4], HasTwoTypes(HighlightingType::Type, HighlightingType::Class)); } TEST_F(TokenInfos, TemplateClassDeclaration) @@ -987,14 +986,14 @@ TEST_F(TokenInfos, TypeDefDeclaration) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(418, 36)); - ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[2], HasTwoTypes(HighlightingType::Type, HighlightingType::Typedef)); } TEST_F(TokenInfos, TypeDefDeclarationUsage) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(419, 48)); - ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Typedef)); } TEST_F(TokenInfos, NonConstReferenceArgument) @@ -1156,7 +1155,7 @@ TEST_F(TokenInfos, EnumerationTypeDef) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(424, 41)); - ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[3], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Enum)); } // QTCREATORBUG-15473 @@ -1171,7 +1170,7 @@ TEST_F(TokenInfos, ClassTemplateParticalSpecialization) { const auto infos = translationUnit.tokenInfosInRange(sourceRange(553, 33)); - ASSERT_THAT(infos[6], HasOnlyType(HighlightingType::Type)); + ASSERT_THAT(infos[6], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Class)); } TEST_F(TokenInfos, UsingFunction) @@ -1246,6 +1245,13 @@ TEST_F(TokenInfos, DefineIsNotIdentifier) ASSERT_THAT(container.isIncludeDirectivePath(), false); } +TEST_F(TokenInfos, NamespaceTypeSpelling) +{ + const auto infos = translationUnit.tokenInfosInRange(sourceRange(592, 59)); + ClangBackEnd::TokenInfoContainer container(infos[10]); + ASSERT_THAT(container.semanticParentTypeSpelling(), Utf8StringLiteral("NFoo::NBar::NTest")); +} + Data *TokenInfos::d; void TokenInfos::SetUpTestCase()