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 <nikolai.kosjar@qt.io>
This commit is contained in:
Ivan Donchevskii
2018-01-12 09:44:05 +01:00
parent 730a8186af
commit bdd5066665
17 changed files with 449 additions and 72 deletions

View File

@@ -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

View File

@@ -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<uint>(container.accessSpecifier()) << ", "
<< static_cast<uint>(container.storageClass()) << ", "
<< container.isIdentifier() << ", "
<< container.isIncludeDirectivePath() << ", "
<< container.isDeclaration() << ", "

View File

@@ -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<uint>(container.accessSpecifier_);
out << static_cast<uint>(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>(accessSpecifier);
container.storageClass_ = static_cast<StorageClass>(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_;
};

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -27,6 +27,8 @@
#include "clangtype.h"
#include <clangsupport/clangsupport_global.h>
#include <clang-c/Index.h>
#include <iosfwd>
@@ -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;

View File

@@ -32,6 +32,8 @@
#include "sourcerange.h"
#include "sourcerangecontainer.h"
#include <utils/qtcfallthrough.h>
#include <QDebug>
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();

View File

@@ -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<CXSourceRange> *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;

View File

@@ -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(

View File

@@ -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()

View File

@@ -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<class T> const T &InvalidStorageClass(const T &type) { return type; }

View File

@@ -39,4 +39,6 @@ struct NonFinalStruct
{
virtual void FinalVirtualMethod() final;
void function();
protected:
void ProtectedMethodAccessSpecifier();
};

View File

@@ -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; } } }

View File

@@ -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 "";

View File

@@ -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()