forked from qt-creator/qt-creator
Clang: Properly handle Q_PROPERTY in TokenInfo
Transform Q_PROPERTY into unique AST node. Mark different parts with types and search for parent in FullTokenInfos. Change-Id: Iaa1ec0c73d34773edf5605d3682bd6a290d195de Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
@@ -23,11 +23,17 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef WRAPPED_QOBJECT_DEFS_H
|
||||||
|
#define WRAPPED_QOBJECT_DEFS_H
|
||||||
|
|
||||||
// Include qobjectdefs.h from Qt ...
|
// Include qobjectdefs.h from Qt ...
|
||||||
#include_next <qobjectdefs.h>
|
#include_next <qobjectdefs.h>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wmacro-redefined"
|
#pragma clang diagnostic ignored "-Wmacro-redefined"
|
||||||
|
#pragma clang diagnostic ignored "-Wgnu-string-literal-operator-template"
|
||||||
|
|
||||||
// ...and redefine macros for tagging signals/slots
|
// ...and redefine macros for tagging signals/slots
|
||||||
#ifdef signals
|
#ifdef signals
|
||||||
@@ -54,4 +60,15 @@
|
|||||||
# define Q_SLOT __attribute__((annotate("qt_slot")))
|
# define Q_SLOT __attribute__((annotate("qt_slot")))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template <char... chars>
|
||||||
|
using QPropertyMagicString = std::integer_sequence<char, chars...>;
|
||||||
|
|
||||||
|
template <class T, T... chars>
|
||||||
|
constexpr QPropertyMagicString<chars...> operator""_qpropstr() { return { }; }
|
||||||
|
|
||||||
|
// Create unique AST node for the property.
|
||||||
|
#define Q_PROPERTY(arg) void QPropertyMagicFunction(decltype(#arg ## _qpropstr));
|
||||||
|
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
|
#endif // WRAPPED_QOBJECT_DEFS_H
|
||||||
|
@@ -95,7 +95,8 @@ enum class HighlightingType : quint8
|
|||||||
Enum,
|
Enum,
|
||||||
Union,
|
Union,
|
||||||
TypeAlias,
|
TypeAlias,
|
||||||
Typedef
|
Typedef,
|
||||||
|
QtProperty
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class StorageClass : quint8
|
enum class StorageClass : quint8
|
||||||
|
@@ -59,6 +59,7 @@ static const char *highlightingTypeToCStringLiteral(HighlightingType type)
|
|||||||
RETURN_TEXT_FOR_CASE(Union);
|
RETURN_TEXT_FOR_CASE(Union);
|
||||||
RETURN_TEXT_FOR_CASE(TypeAlias);
|
RETURN_TEXT_FOR_CASE(TypeAlias);
|
||||||
RETURN_TEXT_FOR_CASE(Typedef);
|
RETURN_TEXT_FOR_CASE(Typedef);
|
||||||
|
RETURN_TEXT_FOR_CASE(QtProperty);
|
||||||
default: return "UnhandledHighlightingType";
|
default: return "UnhandledHighlightingType";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,7 +80,6 @@ QDebug operator<<(QDebug debug, const ExtraInfo &extraInfo)
|
|||||||
<< extraInfo.definition << ", "
|
<< extraInfo.definition << ", "
|
||||||
<< extraInfo.signal << ", "
|
<< extraInfo.signal << ", "
|
||||||
<< extraInfo.slot << ", "
|
<< extraInfo.slot << ", "
|
||||||
<< extraInfo.property
|
|
||||||
<< ")";
|
<< ")";
|
||||||
return debug;
|
return debug;
|
||||||
}
|
}
|
||||||
|
@@ -56,13 +56,12 @@ struct ExtraInfo
|
|||||||
, definition(false)
|
, definition(false)
|
||||||
, signal(false)
|
, signal(false)
|
||||||
, slot(false)
|
, slot(false)
|
||||||
, property(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
ExtraInfo(Utf8String token, Utf8String typeSpelling, Utf8String resultTypeSpelling,
|
ExtraInfo(Utf8String token, Utf8String typeSpelling, Utf8String resultTypeSpelling,
|
||||||
Utf8String semanticParentTypeSpelling, AccessSpecifier accessSpecifier,
|
Utf8String semanticParentTypeSpelling, AccessSpecifier accessSpecifier,
|
||||||
StorageClass storageClass, bool isIdentifier, bool isInclusion,
|
StorageClass storageClass, bool isIdentifier, bool isInclusion,
|
||||||
bool isDeclaration, bool isDefinition, bool isSignal, bool isSlot, bool isProperty)
|
bool isDeclaration, bool isDefinition, bool isSignal, bool isSlot)
|
||||||
: token(token)
|
: token(token)
|
||||||
, typeSpelling(typeSpelling)
|
, typeSpelling(typeSpelling)
|
||||||
, resultTypeSpelling(resultTypeSpelling)
|
, resultTypeSpelling(resultTypeSpelling)
|
||||||
@@ -75,7 +74,6 @@ struct ExtraInfo
|
|||||||
, definition(isDefinition)
|
, definition(isDefinition)
|
||||||
, signal(isSignal)
|
, signal(isSignal)
|
||||||
, slot(isSlot)
|
, slot(isSlot)
|
||||||
, property(isProperty)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
Utf8String token;
|
Utf8String token;
|
||||||
@@ -90,7 +88,6 @@ struct ExtraInfo
|
|||||||
bool definition : 1;
|
bool definition : 1;
|
||||||
bool signal : 1;
|
bool signal : 1;
|
||||||
bool slot : 1;
|
bool slot : 1;
|
||||||
bool property : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline QDataStream &operator<<(QDataStream &out, const ExtraInfo &extraInfo);
|
inline QDataStream &operator<<(QDataStream &out, const ExtraInfo &extraInfo);
|
||||||
@@ -215,7 +212,6 @@ inline QDataStream &operator<<(QDataStream &out, const ExtraInfo &extraInfo)
|
|||||||
out << extraInfo.definition;
|
out << extraInfo.definition;
|
||||||
out << extraInfo.signal;
|
out << extraInfo.signal;
|
||||||
out << extraInfo.slot;
|
out << extraInfo.slot;
|
||||||
out << extraInfo.property;
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +230,6 @@ inline QDataStream &operator>>(QDataStream &in, ExtraInfo &extraInfo)
|
|||||||
bool isDefinition;
|
bool isDefinition;
|
||||||
bool isSignal;
|
bool isSignal;
|
||||||
bool isSlot;
|
bool isSlot;
|
||||||
bool isProperty;
|
|
||||||
|
|
||||||
in >> accessSpecifier;
|
in >> accessSpecifier;
|
||||||
in >> storageClass;
|
in >> storageClass;
|
||||||
@@ -244,7 +239,6 @@ inline QDataStream &operator>>(QDataStream &in, ExtraInfo &extraInfo)
|
|||||||
in >> isDefinition;
|
in >> isDefinition;
|
||||||
in >> isSignal;
|
in >> isSignal;
|
||||||
in >> isSlot;
|
in >> isSlot;
|
||||||
in >> isProperty;
|
|
||||||
|
|
||||||
extraInfo.accessSpecifier = static_cast<AccessSpecifier>(accessSpecifier);
|
extraInfo.accessSpecifier = static_cast<AccessSpecifier>(accessSpecifier);
|
||||||
extraInfo.storageClass = static_cast<StorageClass>(storageClass);
|
extraInfo.storageClass = static_cast<StorageClass>(storageClass);
|
||||||
@@ -254,7 +248,6 @@ inline QDataStream &operator>>(QDataStream &in, ExtraInfo &extraInfo)
|
|||||||
extraInfo.definition = isDefinition;
|
extraInfo.definition = isDefinition;
|
||||||
extraInfo.signal = isSignal;
|
extraInfo.signal = isSignal;
|
||||||
extraInfo.slot = isSlot;
|
extraInfo.slot = isSlot;
|
||||||
extraInfo.property = isProperty;
|
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,8 +264,7 @@ inline bool operator==(const ExtraInfo &first, const ExtraInfo &second)
|
|||||||
&& first.declaration == second.declaration
|
&& first.declaration == second.declaration
|
||||||
&& first.definition == second.definition
|
&& first.definition == second.definition
|
||||||
&& first.signal == second.signal
|
&& first.signal == second.signal
|
||||||
&& first.slot == second.slot
|
&& first.slot == second.slot;
|
||||||
&& first.property == second.property;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline QDataStream &operator<<(QDataStream &out, HighlightingType highlightingType)
|
inline QDataStream &operator<<(QDataStream &out, HighlightingType highlightingType)
|
||||||
|
@@ -50,6 +50,7 @@ TextEditor::TextStyle toTextStyle(ClangBackEnd::HighlightingType type)
|
|||||||
case HighlightingType::LocalVariable:
|
case HighlightingType::LocalVariable:
|
||||||
return TextEditor::C_LOCAL;
|
return TextEditor::C_LOCAL;
|
||||||
case HighlightingType::Field:
|
case HighlightingType::Field:
|
||||||
|
case HighlightingType::QtProperty:
|
||||||
return TextEditor::C_FIELD;
|
return TextEditor::C_FIELD;
|
||||||
case HighlightingType::GlobalVariable:
|
case HighlightingType::GlobalVariable:
|
||||||
return TextEditor::C_GLOBAL;
|
return TextEditor::C_GLOBAL;
|
||||||
|
@@ -26,6 +26,9 @@
|
|||||||
#include "clangstring.h"
|
#include "clangstring.h"
|
||||||
#include "cursor.h"
|
#include "cursor.h"
|
||||||
#include "fulltokeninfo.h"
|
#include "fulltokeninfo.h"
|
||||||
|
#include "sourcerange.h"
|
||||||
|
|
||||||
|
#include <utils/predicates.h>
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
@@ -72,6 +75,73 @@ void FullTokenInfo::updateTypeSpelling(const Cursor &cursor, bool functionLike)
|
|||||||
+ (hasSpaceAfterReturnType ? 1 : 0));
|
+ (hasSpaceAfterReturnType ? 1 : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Utf8String propertyParentSpelling(CXTranslationUnit cxTranslationUnit,
|
||||||
|
const Utf8String &filePath,
|
||||||
|
uint line, uint column)
|
||||||
|
{
|
||||||
|
// Q_PROPERTY expands into QPropertyMagicFunction which can be found as a child of
|
||||||
|
// the containing class.
|
||||||
|
Cursor tuCursor = clang_getTranslationUnitCursor(cxTranslationUnit);
|
||||||
|
Utf8String parentSpelling;
|
||||||
|
tuCursor.visit([&filePath, line, column, &parentSpelling](CXCursor cxCursor, CXCursor parent) {
|
||||||
|
const CXCursorKind kind = clang_getCursorKind(cxCursor);
|
||||||
|
if (kind == CXCursor_Namespace || kind == CXCursor_StructDecl
|
||||||
|
|| kind == CXCursor_ClassDecl || kind == CXCursor_CXXMethod) {
|
||||||
|
Cursor cursor(cxCursor);
|
||||||
|
const SourceRange range = cursor.sourceRange();
|
||||||
|
if (range.start().filePath() != filePath)
|
||||||
|
return CXChildVisit_Continue;
|
||||||
|
if (range.contains(line, column)) {
|
||||||
|
if (kind == CXCursor_Namespace || kind == CXCursor_StructDecl
|
||||||
|
|| kind == CXCursor_ClassDecl) {
|
||||||
|
return CXChildVisit_Recurse;
|
||||||
|
}
|
||||||
|
// CXCursor_CXXMethod case. This is Q_PROPERTY_MAGIC_FUNCTION
|
||||||
|
parentSpelling = Cursor(parent).type().spelling();
|
||||||
|
return CXChildVisit_Break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CXChildVisit_Continue;
|
||||||
|
});
|
||||||
|
return parentSpelling;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Utf8String getPropertyType(const char *const lineContents, uint propertyPosition)
|
||||||
|
{
|
||||||
|
const char *typeStart = std::strstr(lineContents, "Q_PROPERTY") + 10;
|
||||||
|
typeStart += std::strspn(typeStart, "( \t\n\r");
|
||||||
|
if (typeStart - lineContents >= propertyPosition)
|
||||||
|
return Utf8String();
|
||||||
|
auto typeEnd = std::find_if(std::reverse_iterator<const char*>(lineContents + propertyPosition),
|
||||||
|
std::reverse_iterator<const char*>(typeStart),
|
||||||
|
Utils::unequalTo(' '));
|
||||||
|
|
||||||
|
return Utf8String(typeStart, static_cast<int>(&(*typeEnd) + 1 - typeStart));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FullTokenInfo::updatePropertyData()
|
||||||
|
{
|
||||||
|
CXSourceLocation cxLocation(clang_getTokenLocation(m_cxTranslationUnit, *m_cxToken));
|
||||||
|
const SourceLocation location(m_cxTranslationUnit, cxLocation);
|
||||||
|
m_extraInfo.semanticParentTypeSpelling = propertyParentSpelling(m_cxTranslationUnit,
|
||||||
|
location.filePath(),
|
||||||
|
line(),
|
||||||
|
column());
|
||||||
|
m_extraInfo.declaration = true;
|
||||||
|
m_extraInfo.definition = true;
|
||||||
|
#if defined(CINDEX_VERSION_HAS_GETFILECONTENTS_BACKPORTED) || CINDEX_VERSION_MINOR >= 47
|
||||||
|
// Extract property type from the source code
|
||||||
|
CXFile cxFile;
|
||||||
|
uint offset;
|
||||||
|
clang_getFileLocation(cxLocation, &cxFile, nullptr, nullptr, &offset);
|
||||||
|
const uint propertyPosition = column() - 1;
|
||||||
|
const char *const contents = clang_getFileContents(m_cxTranslationUnit, cxFile, nullptr);
|
||||||
|
const char *const lineContents = &contents[offset - propertyPosition];
|
||||||
|
|
||||||
|
m_extraInfo.typeSpelling = getPropertyType(lineContents, propertyPosition);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void FullTokenInfo::identifierKind(const Cursor &cursor, Recursion recursion)
|
void FullTokenInfo::identifierKind(const Cursor &cursor, Recursion recursion)
|
||||||
{
|
{
|
||||||
updateTypeSpelling(cursor);
|
updateTypeSpelling(cursor);
|
||||||
@@ -79,6 +149,8 @@ void FullTokenInfo::identifierKind(const Cursor &cursor, Recursion recursion)
|
|||||||
TokenInfo::identifierKind(cursor, recursion);
|
TokenInfo::identifierKind(cursor, recursion);
|
||||||
|
|
||||||
m_extraInfo.identifier = (cursor.kind() != CXCursor_PreprocessingDirective);
|
m_extraInfo.identifier = (cursor.kind() != CXCursor_PreprocessingDirective);
|
||||||
|
if (types().mainHighlightingType == HighlightingType::QtProperty)
|
||||||
|
updatePropertyData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FullTokenInfo::referencedTypeKind(const Cursor &cursor)
|
void FullTokenInfo::referencedTypeKind(const Cursor &cursor)
|
||||||
@@ -138,8 +210,6 @@ void FullTokenInfo::memberReferenceKind(const Cursor &cursor)
|
|||||||
|
|
||||||
void FullTokenInfo::evaluate()
|
void FullTokenInfo::evaluate()
|
||||||
{
|
{
|
||||||
TokenInfo::evaluate();
|
|
||||||
|
|
||||||
m_extraInfo.token = ClangString(clang_getTokenSpelling(m_cxTranslationUnit, *m_cxToken));
|
m_extraInfo.token = ClangString(clang_getTokenSpelling(m_cxTranslationUnit, *m_cxToken));
|
||||||
|
|
||||||
auto cxTokenKind = clang_getTokenKind(*m_cxToken);
|
auto cxTokenKind = clang_getTokenKind(*m_cxToken);
|
||||||
@@ -148,6 +218,8 @@ void FullTokenInfo::evaluate()
|
|||||||
m_extraInfo.definition = m_originalCursor.isDefinition();
|
m_extraInfo.definition = m_originalCursor.isDefinition();
|
||||||
}
|
}
|
||||||
m_extraInfo.includeDirectivePath = (m_originalCursor.kind() == CXCursor_InclusionDirective);
|
m_extraInfo.includeDirectivePath = (m_originalCursor.kind() == CXCursor_InclusionDirective);
|
||||||
|
|
||||||
|
TokenInfo::evaluate();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
@@ -48,6 +48,7 @@ protected:
|
|||||||
void memberReferenceKind(const Cursor &cursor) override;
|
void memberReferenceKind(const Cursor &cursor) override;
|
||||||
private:
|
private:
|
||||||
void updateTypeSpelling(const Cursor &cursor, bool functionLike = false);
|
void updateTypeSpelling(const Cursor &cursor, bool functionLike = false);
|
||||||
|
void updatePropertyData();
|
||||||
|
|
||||||
ExtraInfo m_extraInfo;
|
ExtraInfo m_extraInfo;
|
||||||
};
|
};
|
||||||
|
@@ -40,6 +40,7 @@ class SourceLocation
|
|||||||
friend class SourceRange;
|
friend class SourceRange;
|
||||||
friend class TranslationUnit;
|
friend class TranslationUnit;
|
||||||
friend class Cursor;
|
friend class Cursor;
|
||||||
|
friend class FullTokenInfo;
|
||||||
friend bool operator==(const SourceLocation &first, const SourceLocation &second);
|
friend bool operator==(const SourceLocation &first, const SourceLocation &second);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@@ -69,10 +69,13 @@ bool SourceRange::contains(unsigned line, unsigned column) const
|
|||||||
const SourceLocation start_ = start();
|
const SourceLocation start_ = start();
|
||||||
const SourceLocation end_ = end();
|
const SourceLocation end_ = end();
|
||||||
|
|
||||||
return start_.line() <= line
|
if (line < start_.line() || line > end_.line())
|
||||||
&& start_.column() <= column
|
return false;
|
||||||
&& line <= end_.line()
|
if (line == start_.line() && column < start_.column())
|
||||||
&& column <= end_.column();
|
return false;
|
||||||
|
if (line == end_.line() && column > end_.column())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceRangeContainer SourceRange::toSourceRangeContainer() const
|
SourceRangeContainer SourceRange::toSourceRangeContainer() const
|
||||||
|
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
#include <utils/qtcfallthrough.h>
|
#include <utils/qtcfallthrough.h>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <array>
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
@@ -421,6 +421,9 @@ void TokenInfo::identifierKind(const Cursor &cursor, Recursion recursion)
|
|||||||
case CXCursor_LabelStmt:
|
case CXCursor_LabelStmt:
|
||||||
m_types.mainHighlightingType = HighlightingType::Label;
|
m_types.mainHighlightingType = HighlightingType::Label;
|
||||||
break;
|
break;
|
||||||
|
case CXCursor_InvalidFile:
|
||||||
|
invalidFileKind();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -466,10 +469,15 @@ HighlightingType TokenInfo::punctuationKind(const Cursor &cursor)
|
|||||||
HighlightingType highlightingType = HighlightingType::Invalid;
|
HighlightingType highlightingType = HighlightingType::Invalid;
|
||||||
|
|
||||||
switch (cursor.kind()) {
|
switch (cursor.kind()) {
|
||||||
case CXCursor_DeclRefExpr: highlightingType = operatorKind(cursor); break;
|
case CXCursor_DeclRefExpr:
|
||||||
|
highlightingType = operatorKind(cursor);
|
||||||
|
break;
|
||||||
case CXCursor_Constructor:
|
case CXCursor_Constructor:
|
||||||
case CXCursor_CallExpr: collectOutputArguments(cursor); break;
|
case CXCursor_CallExpr:
|
||||||
default: break;
|
collectOutputArguments(cursor);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOutputArgument())
|
if (isOutputArgument())
|
||||||
@@ -478,6 +486,75 @@ HighlightingType TokenInfo::punctuationKind(const Cursor &cursor)
|
|||||||
return highlightingType;
|
return highlightingType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class PropertyPart
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Type,
|
||||||
|
Property,
|
||||||
|
Keyword,
|
||||||
|
FunctionOrPrimitiveType
|
||||||
|
};
|
||||||
|
|
||||||
|
static PropertyPart propertyPart(CXTranslationUnit tu, CXToken *token)
|
||||||
|
{
|
||||||
|
static constexpr const char *propertyKeywords[]
|
||||||
|
= {"READ", "WRITE", "MEMBER", "RESET", "NOTIFY", "REVISION", "DESIGNABLE",
|
||||||
|
"SCRIPTABLE", "STORED", "USER", "CONSTANT", "FINAL"
|
||||||
|
};
|
||||||
|
CXSourceLocation location = clang_getTokenLocation(tu, *token);
|
||||||
|
|
||||||
|
// If current token is inside Q_PROPERTY then the cursor from token's position will be
|
||||||
|
// the whole Q_PROPERTY macro cursor.
|
||||||
|
Cursor possibleQPropertyCursor = clang_getCursor(tu, location);
|
||||||
|
if (!(possibleQPropertyCursor.spelling() == "Q_PROPERTY"))
|
||||||
|
return PropertyPart::None;
|
||||||
|
|
||||||
|
const ClangString currentToken = clang_getTokenSpelling(tu, *token);
|
||||||
|
if (std::find(std::begin(propertyKeywords), std::end(propertyKeywords), currentToken)
|
||||||
|
!= std::end(propertyKeywords)) {
|
||||||
|
return PropertyPart::Keyword;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ClangString nextToken = clang_getTokenSpelling(tu, *(token + 1));
|
||||||
|
const ClangString previousToken = clang_getTokenSpelling(tu, *(token - 1));
|
||||||
|
if (std::find(std::begin(propertyKeywords), std::end(propertyKeywords), nextToken)
|
||||||
|
!= std::end(propertyKeywords)) {
|
||||||
|
if (std::find(std::begin(propertyKeywords), std::end(propertyKeywords), previousToken)
|
||||||
|
== std::end(propertyKeywords)) {
|
||||||
|
return PropertyPart::Property;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PropertyPart::FunctionOrPrimitiveType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::find(std::begin(propertyKeywords), std::end(propertyKeywords), previousToken)
|
||||||
|
!= std::end(propertyKeywords)) {
|
||||||
|
return PropertyPart::FunctionOrPrimitiveType;
|
||||||
|
}
|
||||||
|
return PropertyPart::Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TokenInfo::invalidFileKind()
|
||||||
|
{
|
||||||
|
const PropertyPart propPart = propertyPart(m_cxTranslationUnit, m_cxToken);
|
||||||
|
|
||||||
|
switch (propPart) {
|
||||||
|
case PropertyPart::None:
|
||||||
|
case PropertyPart::Keyword:
|
||||||
|
m_types.mainHighlightingType = HighlightingType::Invalid;
|
||||||
|
return;
|
||||||
|
case PropertyPart::Property:
|
||||||
|
m_types.mainHighlightingType = HighlightingType::QtProperty;
|
||||||
|
return;
|
||||||
|
case PropertyPart::Type:
|
||||||
|
m_types.mainHighlightingType = HighlightingType::Type;
|
||||||
|
return;
|
||||||
|
case PropertyPart::FunctionOrPrimitiveType:
|
||||||
|
m_types.mainHighlightingType = HighlightingType::Function;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static HighlightingType highlightingTypeForKeyword(CXTranslationUnit cxTranslationUnit,
|
static HighlightingType highlightingTypeForKeyword(CXTranslationUnit cxTranslationUnit,
|
||||||
CXToken *cxToken,
|
CXToken *cxToken,
|
||||||
const Cursor &cursor)
|
const Cursor &cursor)
|
||||||
|
@@ -94,6 +94,7 @@ 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 invalidFileKind();
|
||||||
|
|
||||||
Cursor m_originalCursor;
|
Cursor m_originalCursor;
|
||||||
CXToken *m_cxToken;
|
CXToken *m_cxToken;
|
||||||
|
@@ -680,7 +680,7 @@ void ClangCodeModelServer::expectDocumentAnnotationsChangedForFileBWithSpecificH
|
|||||||
AccessSpecifier::Invalid,
|
AccessSpecifier::Invalid,
|
||||||
StorageClass::None,
|
StorageClass::None,
|
||||||
true, false, true, true,
|
true, false, true, true,
|
||||||
false, false, false});
|
false, false});
|
||||||
|
|
||||||
EXPECT_CALL(mockClangCodeModelClient,
|
EXPECT_CALL(mockClangCodeModelClient,
|
||||||
documentAnnotationsChanged(
|
documentAnnotationsChanged(
|
||||||
|
@@ -592,3 +592,10 @@ class WithVirtualFunctionDefined {
|
|||||||
namespace NFoo { namespace NBar { namespace NTest { class NamespaceTypeSpelling; } } }
|
namespace NFoo { namespace NBar { namespace NTest { class NamespaceTypeSpelling; } } }
|
||||||
|
|
||||||
Undeclared u;
|
Undeclared u;
|
||||||
|
|
||||||
|
#include "../../../../share/qtcreator/cplusplus/wrappedQtHeaders/QtCore/qobjectdefs.h"
|
||||||
|
|
||||||
|
class Property {
|
||||||
|
Q_PROPERTY(const volatile unsigned long long * prop READ getProp WRITE setProp NOTIFY propChanged)
|
||||||
|
Q_PROPERTY(const QString str READ getStr)
|
||||||
|
};
|
||||||
|
@@ -500,6 +500,7 @@ static const char *highlightingTypeToCStringLiteral(HighlightingType type)
|
|||||||
RETURN_TEXT_FOR_CASE(Union);
|
RETURN_TEXT_FOR_CASE(Union);
|
||||||
RETURN_TEXT_FOR_CASE(TypeAlias);
|
RETURN_TEXT_FOR_CASE(TypeAlias);
|
||||||
RETURN_TEXT_FOR_CASE(Typedef);
|
RETURN_TEXT_FOR_CASE(Typedef);
|
||||||
|
RETURN_TEXT_FOR_CASE(QtProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
@@ -538,8 +539,7 @@ std::ostream &operator<<(std::ostream &os, const ExtraInfo &extraInfo)
|
|||||||
<< extraInfo.declaration << ", "
|
<< extraInfo.declaration << ", "
|
||||||
<< extraInfo.definition << ", "
|
<< extraInfo.definition << ", "
|
||||||
<< extraInfo.signal << ", "
|
<< extraInfo.signal << ", "
|
||||||
<< extraInfo.slot << ", "
|
<< extraInfo.slot
|
||||||
<< extraInfo.property
|
|
||||||
<< ")";
|
<< ")";
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
@@ -1257,18 +1257,53 @@ TEST_F(TokenProcessor, NamespaceTypeSpelling)
|
|||||||
|
|
||||||
TEST_F(TokenProcessor, DISABLED_WITHOUT_INVALIDDECL_PATCH(TypeNameOfInvalidDeclarationIsInvalid))
|
TEST_F(TokenProcessor, DISABLED_WITHOUT_INVALIDDECL_PATCH(TypeNameOfInvalidDeclarationIsInvalid))
|
||||||
{
|
{
|
||||||
const auto infos = translationUnit.tokenInfosInRange(sourceRange(592, 14));
|
const auto infos = translationUnit.tokenInfosInRange(sourceRange(594, 14));
|
||||||
|
|
||||||
ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Invalid));
|
ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Invalid));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TokenProcessor, DISABLED_WITHOUT_INVALIDDECL_PATCH(VariableNameOfInvalidDeclarationIsInvalid))
|
TEST_F(TokenProcessor, DISABLED_WITHOUT_INVALIDDECL_PATCH(VariableNameOfInvalidDeclarationIsInvalid))
|
||||||
{
|
{
|
||||||
const auto infos = translationUnit.tokenInfosInRange(sourceRange(592, 14));
|
const auto infos = translationUnit.tokenInfosInRange(sourceRange(594, 14));
|
||||||
|
|
||||||
ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Invalid));
|
ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Invalid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(TokenProcessor, QtPropertyName)
|
||||||
|
{
|
||||||
|
const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(599, 103));
|
||||||
|
|
||||||
|
ASSERT_THAT(infos[8], HasOnlyType(HighlightingType::QtProperty));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TokenProcessor, QtPropertyFunction)
|
||||||
|
{
|
||||||
|
const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(599, 103));
|
||||||
|
|
||||||
|
ASSERT_THAT(infos[10], HasOnlyType(HighlightingType::Function));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TokenProcessor, QtPropertyInternalKeyword)
|
||||||
|
{
|
||||||
|
const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(599, 103));
|
||||||
|
|
||||||
|
ASSERT_THAT(infos[9], HasOnlyType(HighlightingType::Invalid));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TokenProcessor, QtPropertyLastToken)
|
||||||
|
{
|
||||||
|
const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(599, 103));
|
||||||
|
|
||||||
|
ASSERT_THAT(infos[14], HasOnlyType(HighlightingType::Function));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TokenProcessor, QtPropertyType)
|
||||||
|
{
|
||||||
|
const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(600, 46));
|
||||||
|
|
||||||
|
ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Type));
|
||||||
|
}
|
||||||
|
|
||||||
Data *TokenProcessor::d;
|
Data *TokenProcessor::d;
|
||||||
|
|
||||||
void TokenProcessor::SetUpTestCase()
|
void TokenProcessor::SetUpTestCase()
|
||||||
|
Reference in New Issue
Block a user