forked from qt-creator/qt-creator
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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user