Clang: Support anonymous types in tokens

Add extra data to Keyword tokens.
Does not affect highlighting.

Change-Id: I206499ea35ee4ece5fe442665c904090cf5d90fc
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
Ivan Donchevskii
2018-04-06 14:07:35 +02:00
parent 3290de7a4e
commit 84b983617f
7 changed files with 101 additions and 14 deletions

View File

@@ -226,9 +226,6 @@ CPlusPlus::Icons::IconType iconTypeForToken(const ClangBackEnd::TokenInfoContain
ClangBackEnd::HighlightingType mainType = token.types.mainHighlightingType; ClangBackEnd::HighlightingType mainType = token.types.mainHighlightingType;
if (mainType == ClangBackEnd::HighlightingType::Keyword)
return CPlusPlus::Icons::KeywordIconType;
if (mainType == ClangBackEnd::HighlightingType::QtProperty) if (mainType == ClangBackEnd::HighlightingType::QtProperty)
return CPlusPlus::Icons::PropertyIconType; return CPlusPlus::Icons::PropertyIconType;
@@ -240,7 +237,8 @@ CPlusPlus::Icons::IconType iconTypeForToken(const ClangBackEnd::TokenInfoContain
if (mainType == ClangBackEnd::HighlightingType::Enumeration) if (mainType == ClangBackEnd::HighlightingType::Enumeration)
return CPlusPlus::Icons::EnumeratorIconType; return CPlusPlus::Icons::EnumeratorIconType;
if (mainType == ClangBackEnd::HighlightingType::Type) { if (mainType == ClangBackEnd::HighlightingType::Type
|| mainType == ClangBackEnd::HighlightingType::Keyword) {
const ClangBackEnd::MixinHighlightingTypes &types = token.types.mixinHighlightingTypes; const ClangBackEnd::MixinHighlightingTypes &types = token.types.mixinHighlightingTypes;
if (types.contains(ClangBackEnd::HighlightingType::Enum)) if (types.contains(ClangBackEnd::HighlightingType::Enum))
return CPlusPlus::Icons::EnumIconType; return CPlusPlus::Icons::EnumIconType;
@@ -248,6 +246,10 @@ CPlusPlus::Icons::IconType iconTypeForToken(const ClangBackEnd::TokenInfoContain
return CPlusPlus::Icons::StructIconType; return CPlusPlus::Icons::StructIconType;
if (types.contains(ClangBackEnd::HighlightingType::Namespace)) if (types.contains(ClangBackEnd::HighlightingType::Namespace))
return CPlusPlus::Icons::NamespaceIconType; return CPlusPlus::Icons::NamespaceIconType;
if (types.contains(ClangBackEnd::HighlightingType::Class))
return CPlusPlus::Icons::ClassIconType;
if (mainType == ClangBackEnd::HighlightingType::Keyword)
return CPlusPlus::Icons::KeywordIconType;
return CPlusPlus::Icons::ClassIconType; return CPlusPlus::Icons::ClassIconType;
} }

View File

@@ -27,6 +27,7 @@
#include "cursor.h" #include "cursor.h"
#include "fulltokeninfo.h" #include "fulltokeninfo.h"
#include "sourcerange.h" #include "sourcerange.h"
#include "tokenprocessor.h"
#include <utils/predicates.h> #include <utils/predicates.h>
@@ -42,7 +43,7 @@ FullTokenInfo::FullTokenInfo(const CXCursor &cxCursor,
FullTokenInfo::operator TokenInfoContainer() const FullTokenInfo::operator TokenInfoContainer() const
{ {
return TokenInfoContainer(line(), column(), length(), types(), m_extraInfo); return TokenInfoContainer(line(), column(), length(), m_types, m_extraInfo);
} }
static Utf8String fullyQualifiedType(const Cursor &cursor) static Utf8String fullyQualifiedType(const Cursor &cursor)
@@ -53,6 +54,7 @@ static Utf8String fullyQualifiedType(const Cursor &cursor)
typeSpelling = cursor.unifiedSymbolResolution(); typeSpelling = cursor.unifiedSymbolResolution();
typeSpelling.replace(Utf8StringLiteral("c:@N@"), Utf8StringLiteral("")); typeSpelling.replace(Utf8StringLiteral("c:@N@"), Utf8StringLiteral(""));
typeSpelling.replace(Utf8StringLiteral("@N@"), Utf8StringLiteral("::")); typeSpelling.replace(Utf8StringLiteral("@N@"), Utf8StringLiteral("::"));
typeSpelling.replace(Utf8StringLiteral("c:@aN"), Utf8StringLiteral("(anonymous)"));
} }
return typeSpelling; return typeSpelling;
} }
@@ -159,7 +161,7 @@ void FullTokenInfo::identifierKind(const Cursor &cursor, Recursion recursion)
m_extraInfo.identifier = (cursor.kind() != CXCursor_PreprocessingDirective); m_extraInfo.identifier = (cursor.kind() != CXCursor_PreprocessingDirective);
if (types().mainHighlightingType == HighlightingType::QtProperty) if (m_types.mainHighlightingType == HighlightingType::QtProperty)
updatePropertyData(); updatePropertyData();
else else
m_extraInfo.cursorRange = cursor.sourceRange(); m_extraInfo.cursorRange = cursor.sourceRange();
@@ -220,6 +222,37 @@ void FullTokenInfo::memberReferenceKind(const Cursor &cursor)
} }
} }
void FullTokenInfo::keywordKind(const Cursor &cursor)
{
TokenInfo::keywordKind(cursor);
CXCursorKind cursorKind = cursor.kind();
bool anonymous = false;
if (clang_Cursor_isAnonymous(cursor.cx())) {
anonymous = true;
} else {
const Utf8String type = fullyQualifiedType(cursor);
if (type.endsWith(Utf8StringLiteral(")"))
&& static_cast<const QByteArray &>(type).indexOf("(anonymous") >= 0) {
anonymous = true;
}
}
if (anonymous) {
if (cursorKind == CXCursor_EnumDecl)
m_types.mixinHighlightingTypes.push_back(HighlightingType::Enum);
else if (cursorKind == CXCursor_ClassDecl)
m_types.mixinHighlightingTypes.push_back(HighlightingType::Class);
else if (cursorKind == CXCursor_StructDecl)
m_types.mixinHighlightingTypes.push_back(HighlightingType::Struct);
else if (cursorKind == CXCursor_Namespace)
m_types.mixinHighlightingTypes.push_back(HighlightingType::Namespace);
m_extraInfo.declaration = m_extraInfo.definition = true;
m_extraInfo.token = Utf8StringLiteral("anonymous");
updateTypeSpelling(cursor);
m_extraInfo.cursorRange = cursor.sourceRange();
}
}
void FullTokenInfo::evaluate() void FullTokenInfo::evaluate()
{ {
m_extraInfo.token = ClangString(clang_getTokenSpelling(m_cxTranslationUnit, *m_cxToken)); m_extraInfo.token = ClangString(clang_getTokenSpelling(m_cxTranslationUnit, *m_cxToken));

View File

@@ -31,7 +31,9 @@ namespace ClangBackEnd {
class FullTokenInfo : public TokenInfo class FullTokenInfo : public TokenInfo
{ {
template<class T> friend class TokenProcessor;
public: public:
FullTokenInfo() = default;
FullTokenInfo(const CXCursor &cxCursor, FullTokenInfo(const CXCursor &cxCursor,
CXToken *cxToken, CXToken *cxToken,
CXTranslationUnit cxTranslationUnit, CXTranslationUnit cxTranslationUnit,
@@ -46,6 +48,7 @@ protected:
void variableKind(const Cursor &cursor) override; void variableKind(const Cursor &cursor) override;
void fieldKind(const Cursor &cursor) override; void fieldKind(const Cursor &cursor) override;
void memberReferenceKind(const Cursor &cursor) override; void memberReferenceKind(const Cursor &cursor) override;
void keywordKind(const Cursor &cursor) override;
private: private:
void updateTypeSpelling(const Cursor &cursor, bool functionLike = false); void updateTypeSpelling(const Cursor &cursor, bool functionLike = false);
void updatePropertyData(); void updatePropertyData();

View File

@@ -612,6 +612,13 @@ static HighlightingType highlightingTypeForKeyword(CXTranslationUnit cxTranslati
return HighlightingType::Keyword; return HighlightingType::Keyword;
} }
void TokenInfo::keywordKind(const Cursor &cursor)
{
m_types.mainHighlightingType = highlightingTypeForKeyword(m_cxTranslationUnit,
m_cxToken,
cursor);
}
void TokenInfo::evaluate() void TokenInfo::evaluate()
{ {
auto cxTokenKind = clang_getTokenKind(*m_cxToken); auto cxTokenKind = clang_getTokenKind(*m_cxToken);
@@ -620,9 +627,7 @@ void TokenInfo::evaluate()
switch (cxTokenKind) { switch (cxTokenKind) {
case CXToken_Keyword: case CXToken_Keyword:
m_types.mainHighlightingType = highlightingTypeForKeyword(m_cxTranslationUnit, keywordKind(m_originalCursor);
m_cxToken,
m_originalCursor);
break; break;
case CXToken_Punctuation: case CXToken_Punctuation:
m_types.mainHighlightingType = punctuationKind(m_originalCursor); m_types.mainHighlightingType = punctuationKind(m_originalCursor);

View File

@@ -39,8 +39,9 @@ namespace ClangBackEnd {
class TokenInfo class TokenInfo
{ {
friend bool operator==(const TokenInfo &first, const TokenInfo &second); friend bool operator==(const TokenInfo &first, const TokenInfo &second);
template<class T> friend class TokenProcessor;
public: public:
TokenInfo() = default;
TokenInfo(const CXCursor &cxCursor, TokenInfo(const CXCursor &cxCursor,
CXToken *cxToken, CXToken *cxToken,
CXTranslationUnit cxTranslationUnit, CXTranslationUnit cxTranslationUnit,
@@ -94,11 +95,13 @@ protected:
virtual void memberReferenceKind(const Cursor &cursor); virtual void memberReferenceKind(const Cursor &cursor);
virtual HighlightingType punctuationKind(const Cursor &cursor); virtual HighlightingType punctuationKind(const Cursor &cursor);
virtual void typeKind(const Cursor &cursor); virtual void typeKind(const Cursor &cursor);
virtual void keywordKind(const Cursor &cursor);
virtual void invalidFileKind(); virtual void invalidFileKind();
Cursor m_originalCursor; Cursor m_originalCursor;
CXToken *m_cxToken; CXToken *m_cxToken;
CXTranslationUnit m_cxTranslationUnit; CXTranslationUnit m_cxTranslationUnit;
HighlightingTypes m_types;
private: private:
bool isVirtualMethodDeclarationOrDefinition(const Cursor &cursor) const; bool isVirtualMethodDeclarationOrDefinition(const Cursor &cursor) const;
@@ -111,11 +114,10 @@ private:
bool isArgumentInCurrentOutputArgumentLocations() const; bool isArgumentInCurrentOutputArgumentLocations() const;
std::vector<CXSourceRange> *m_currentOutputArgumentRanges = nullptr; std::vector<CXSourceRange> *m_currentOutputArgumentRanges = nullptr;
uint m_line; uint m_line = 0;
uint m_column; uint m_column = 0;
uint m_length; uint m_length = 0;
uint m_offset = 0; uint m_offset = 0;
HighlightingTypes m_types;
}; };

View File

@@ -599,3 +599,15 @@ class Property {
Q_PROPERTY(const volatile unsigned long long * prop READ getProp WRITE setProp NOTIFY propChanged) Q_PROPERTY(const volatile unsigned long long * prop READ getProp WRITE setProp NOTIFY propChanged)
Q_PROPERTY(const QString str READ getStr) Q_PROPERTY(const QString str READ getStr)
}; };
enum {
Test = 0
};
namespace {
class B {
struct {
int a;
};
};
}

View File

@@ -1324,6 +1324,36 @@ TEST_F(TokenProcessor, CursorRange)
ASSERT_THAT(container.extraInfo.cursorRange, expectedRange); ASSERT_THAT(container.extraInfo.cursorRange, expectedRange);
} }
TEST_F(TokenProcessor, AnonymousEnum)
{
const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(603, 7));
ClangBackEnd::TokenInfoContainer container(infos[0]);
ASSERT_THAT(container.types.mainHighlightingType, ClangBackEnd::HighlightingType::Keyword);
ASSERT_THAT(container.types.mixinHighlightingTypes[0], ClangBackEnd::HighlightingType::Enum);
}
TEST_F(TokenProcessor, AnonymousNamespace)
{
const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(607, 12));
ClangBackEnd::TokenInfoContainer container(infos[0]);
ASSERT_THAT(container.types.mainHighlightingType, ClangBackEnd::HighlightingType::Keyword);
ASSERT_THAT(container.types.mixinHighlightingTypes[0], ClangBackEnd::HighlightingType::Namespace);
}
TEST_F(TokenProcessor, AnonymousStruct)
{
const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(609, 13));
ClangBackEnd::TokenInfoContainer container(infos[0]);
ASSERT_THAT(container.types.mainHighlightingType, ClangBackEnd::HighlightingType::Keyword);
ASSERT_THAT(container.types.mixinHighlightingTypes[0], ClangBackEnd::HighlightingType::Struct);
}
Data *TokenProcessor::d; Data *TokenProcessor::d;
void TokenProcessor::SetUpTestCase() void TokenProcessor::SetUpTestCase()