forked from qt-creator/qt-creator
CppEditor: Add syntax highlighting for C++ attributes
Fixes: QTCREATORBUG-31241 Change-Id: I7583c3cd08c2ec58ca7702e7758aad6c0e142574 Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -29,6 +29,7 @@
|
|||||||
<style name="Function"/>
|
<style name="Function"/>
|
||||||
<style name="Macro"/>
|
<style name="Macro"/>
|
||||||
<style name="Keyword" foreground="#45c6d6" italic="true"/>
|
<style name="Keyword" foreground="#45c6d6" italic="true"/>
|
||||||
|
<style name="Attribute" foreground="#45c6d6" italic="true"/>
|
||||||
<style name="PrimitiveType" foreground="#d69aa7"/>
|
<style name="PrimitiveType" foreground="#d69aa7"/>
|
||||||
<style name="Punctuation"/>
|
<style name="Punctuation"/>
|
||||||
<style name="Operator" foreground="#d6bb9a"/>
|
<style name="Operator" foreground="#d6bb9a"/>
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
<style name="Macro"/>
|
<style name="Macro"/>
|
||||||
<style name="Global"/>
|
<style name="Global"/>
|
||||||
<style name="Keyword" foreground="#ffff55"/>
|
<style name="Keyword" foreground="#ffff55"/>
|
||||||
|
<style name="Attribute" foreground="#ffff55"/>
|
||||||
<style name="PrimitiveType" foreground="#ffff55"/>
|
<style name="PrimitiveType" foreground="#ffff55"/>
|
||||||
<style name="Label" foreground="#ffff55"/>
|
<style name="Label" foreground="#ffff55"/>
|
||||||
<style name="LineNumber" foreground="#888888" background="#232323"/>
|
<style name="LineNumber" foreground="#888888" background="#232323"/>
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
<style name="Function" background="#ffffff"/>
|
<style name="Function" background="#ffffff"/>
|
||||||
<style name="Macro" background="#ffffff"/>
|
<style name="Macro" background="#ffffff"/>
|
||||||
<style name="Keyword" foreground="#808000"/>
|
<style name="Keyword" foreground="#808000"/>
|
||||||
|
<style name="Attribute" foreground="#808000"/>
|
||||||
<style name="PrimitiveType" foreground="#808000"/>
|
<style name="PrimitiveType" foreground="#808000"/>
|
||||||
<style name="Punctuation"/>
|
<style name="Punctuation"/>
|
||||||
<style name="Operator"/>
|
<style name="Operator"/>
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
<style name="Function"/>
|
<style name="Function"/>
|
||||||
<style name="Macro"/>
|
<style name="Macro"/>
|
||||||
<style name="Keyword" bold="true"/>
|
<style name="Keyword" bold="true"/>
|
||||||
|
<style name="Attribute" bold="true"/>
|
||||||
<style name="PrimitiveType" bold="true"/>
|
<style name="PrimitiveType" bold="true"/>
|
||||||
<style name="Label"/>
|
<style name="Label"/>
|
||||||
<style name="LineNumber" foreground="#c7c4c1" background="#efebe7"/>
|
<style name="LineNumber" foreground="#c7c4c1" background="#efebe7"/>
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
<style name="Macro"/>
|
<style name="Macro"/>
|
||||||
<style name="Global"/>
|
<style name="Global"/>
|
||||||
<style name="Keyword" foreground="#808bed"/>
|
<style name="Keyword" foreground="#808bed"/>
|
||||||
|
<style name="Attribute" foreground="#808bed"/>
|
||||||
<style name="PrimitiveType" foreground="#808bed"/>
|
<style name="PrimitiveType" foreground="#808bed"/>
|
||||||
<style name="Label" foreground="#e76000"/>
|
<style name="Label" foreground="#e76000"/>
|
||||||
<style name="LineNumber" foreground="#8b8bcd" background="#2e2e2e"/>
|
<style name="LineNumber" foreground="#8b8bcd" background="#2e2e2e"/>
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
<style name="Function" foreground="#000000"/>
|
<style name="Function" foreground="#000000"/>
|
||||||
<style name="Macro" foreground="#000000"/>
|
<style name="Macro" foreground="#000000"/>
|
||||||
<style name="Keyword" foreground="#000080" bold="true"/>
|
<style name="Keyword" foreground="#000080" bold="true"/>
|
||||||
|
<style name="Attribute" foreground="#000080" bold="true"/>
|
||||||
<style name="PrimitiveType" foreground="#000080" bold="true"/>
|
<style name="PrimitiveType" foreground="#000080" bold="true"/>
|
||||||
<style name="Label" foreground="#800000" bold="true"/>
|
<style name="Label" foreground="#800000" bold="true"/>
|
||||||
<style name="Local" foreground="#000000"/>
|
<style name="Local" foreground="#000000"/>
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
<style name="Function"/>
|
<style name="Function"/>
|
||||||
<style name="Macro"/>
|
<style name="Macro"/>
|
||||||
<style name="Keyword" foreground="#78d7ec" italic="true"/>
|
<style name="Keyword" foreground="#78d7ec" italic="true"/>
|
||||||
|
<style name="Attribute" foreground="#78d7ec" italic="true"/>
|
||||||
<style name="PrimitiveType" foreground="#ff8080"/>
|
<style name="PrimitiveType" foreground="#ff8080"/>
|
||||||
<style name="Punctuation"/>
|
<style name="Punctuation"/>
|
||||||
<style name="Operator" foreground="#a6e22e"/>
|
<style name="Operator" foreground="#a6e22e"/>
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
<style name="Function" foreground="#839496"/>
|
<style name="Function" foreground="#839496"/>
|
||||||
<style name="Macro" foreground="#839496"/>
|
<style name="Macro" foreground="#839496"/>
|
||||||
<style name="Keyword" foreground="#709d06"/>
|
<style name="Keyword" foreground="#709d06"/>
|
||||||
|
<style name="Attribute" foreground="#709d06"/>
|
||||||
<style name="PrimitiveType" foreground="#808000"/>
|
<style name="PrimitiveType" foreground="#808000"/>
|
||||||
<style name="Punctuation"/>
|
<style name="Punctuation"/>
|
||||||
<style name="Operator" foreground="#839496"/>
|
<style name="Operator" foreground="#839496"/>
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
<style name="Function" foreground="#657b83"/>
|
<style name="Function" foreground="#657b83"/>
|
||||||
<style name="Macro" foreground="#657b83"/>
|
<style name="Macro" foreground="#657b83"/>
|
||||||
<style name="Keyword" foreground="#709d06"/>
|
<style name="Keyword" foreground="#709d06"/>
|
||||||
|
<style name="Attribute" foreground="#709d06"/>
|
||||||
<style name="PrimitiveType" foreground="#808000"/>
|
<style name="PrimitiveType" foreground="#808000"/>
|
||||||
<style name="Punctuation"/>
|
<style name="Punctuation"/>
|
||||||
<style name="Operator" foreground="#657b83"/>
|
<style name="Operator" foreground="#657b83"/>
|
||||||
|
@@ -33,6 +33,15 @@ using namespace CPlusPlus;
|
|||||||
namespace CppEditor {
|
namespace CppEditor {
|
||||||
using namespace Internal;
|
using namespace Internal;
|
||||||
|
|
||||||
|
union AttributeState {
|
||||||
|
struct {
|
||||||
|
quint8 lbrackets: 1;
|
||||||
|
quint8 rbrackets: 1;
|
||||||
|
quint8 opened: 6;
|
||||||
|
};
|
||||||
|
quint8 state;
|
||||||
|
};
|
||||||
|
|
||||||
CppHighlighter::CppHighlighter(QTextDocument *document) :
|
CppHighlighter::CppHighlighter(QTextDocument *document) :
|
||||||
SyntaxHighlighter(document)
|
SyntaxHighlighter(document)
|
||||||
{
|
{
|
||||||
@@ -79,6 +88,8 @@ void CppHighlighter::highlightBlock(const QString &text)
|
|||||||
userData->setFoldingStartIncluded(false);
|
userData->setFoldingStartIncluded(false);
|
||||||
userData->setFoldingEndIncluded(false);
|
userData->setFoldingEndIncluded(false);
|
||||||
}
|
}
|
||||||
|
AttributeState attrState;
|
||||||
|
attrState.state = TextDocumentLayout::attributeState(prevBlock);
|
||||||
|
|
||||||
if (tokens.isEmpty()) {
|
if (tokens.isEmpty()) {
|
||||||
setCurrentBlockState((braceDepth << 8) | lexerState);
|
setCurrentBlockState((braceDepth << 8) | lexerState);
|
||||||
@@ -93,6 +104,7 @@ void CppHighlighter::highlightBlock(const QString &text)
|
|||||||
}
|
}
|
||||||
TextDocumentLayout::setFoldingIndent(currentBlock(), foldingIndent);
|
TextDocumentLayout::setFoldingIndent(currentBlock(), foldingIndent);
|
||||||
TextDocumentLayout::setExpectedRawStringSuffix(currentBlock(), inheritedRawStringSuffix);
|
TextDocumentLayout::setExpectedRawStringSuffix(currentBlock(), inheritedRawStringSuffix);
|
||||||
|
TextDocumentLayout::setAttributeState(currentBlock(), attrState.state);
|
||||||
qCDebug(highlighterLog) << "no tokens, storing brace depth" << braceDepth << "and foldingIndent"
|
qCDebug(highlighterLog) << "no tokens, storing brace depth" << braceDepth << "and foldingIndent"
|
||||||
<< foldingIndent;
|
<< foldingIndent;
|
||||||
return;
|
return;
|
||||||
@@ -185,6 +197,25 @@ void CppHighlighter::highlightBlock(const QString &text)
|
|||||||
if (onlyHighlightComments && !tk.isComment())
|
if (onlyHighlightComments && !tk.isComment())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Handle attributes, i.e. identifiers in pairs of "[[" and "]]".
|
||||||
|
if (tk.is(T_LBRACKET) && !tk.isOperator()) {
|
||||||
|
attrState.lbrackets = !attrState.lbrackets;
|
||||||
|
if (attrState.lbrackets == 0)
|
||||||
|
++attrState.opened;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (tk.is(T_RBRACKET) && !tk.isOperator()) {
|
||||||
|
attrState.rbrackets = !attrState.rbrackets;
|
||||||
|
if (attrState.rbrackets == 0 && attrState.opened > 0)
|
||||||
|
--attrState.opened;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
attrState.lbrackets = attrState.rbrackets = 0;
|
||||||
|
if (attrState.opened && (tk.is(T_IDENTIFIER) || (tk.isKeyword() && !tk.is(T_USING)))) {
|
||||||
|
setFormat(tk.utf16charsBegin(), tk.utf16chars(), formatForCategory(C_ATTRIBUTE));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (i == 0 && tk.is(T_POUND)) {
|
if (i == 0 && tk.is(T_POUND)) {
|
||||||
setFormatWithSpaces(text, tk.utf16charsBegin(), tk.utf16chars(),
|
setFormatWithSpaces(text, tk.utf16charsBegin(), tk.utf16chars(),
|
||||||
formatForCategory(C_PREPROCESSOR));
|
formatForCategory(C_PREPROCESSOR));
|
||||||
@@ -297,6 +328,7 @@ void CppHighlighter::highlightBlock(const QString &text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextDocumentLayout::setParentheses(currentBlock(), parentheses);
|
TextDocumentLayout::setParentheses(currentBlock(), parentheses);
|
||||||
|
TextDocumentLayout::setAttributeState(currentBlock(), attrState.state);
|
||||||
|
|
||||||
TextDocumentLayout::setFoldingIndent(currentBlock(), foldingIndent);
|
TextDocumentLayout::setFoldingIndent(currentBlock(), foldingIndent);
|
||||||
setCurrentBlockState(rehighlightNextBlock | (braceDepth << 8) | tokenize.state());
|
setCurrentBlockState(rehighlightNextBlock | (braceDepth << 8) | tokenize.state());
|
||||||
@@ -655,6 +687,46 @@ private slots:
|
|||||||
<< 73 << 17 << 73 << 18 << C_STRING;
|
<< 73 << 17 << 73 << 18 << C_STRING;
|
||||||
QTest::newRow("wide char literal with user-defined suffix (suffix)")
|
QTest::newRow("wide char literal with user-defined suffix (suffix)")
|
||||||
<< 73 << 20 << 73 << 22 << C_OVERLOADED_OPERATOR;
|
<< 73 << 20 << 73 << 22 << C_OVERLOADED_OPERATOR;
|
||||||
|
QTest::newRow("separate attributes specs, 1/4, namespace")
|
||||||
|
<< 75 << 3 << 72 << 5 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("separate attributes specs, 1/4, attr")
|
||||||
|
<< 75 << 8 << 72 << 20 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("separate attributes specs, 2/4, namespace")
|
||||||
|
<< 75 << 26 << 72 << 28 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("separate attributes specs, 2/4, attr")
|
||||||
|
<< 75 << 31 << 72 << 33 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("separate attributes specs, 3/4, namespace")
|
||||||
|
<< 75 << 39 << 72 << 41 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("separate attributes specs, 3/4, attr")
|
||||||
|
<< 75 << 44 << 72 << 48 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("separate attributes specs, 4/4, attr")
|
||||||
|
<< 75 << 54 << 72 << 62 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("single attributes spec, 1/4, namespace")
|
||||||
|
<< 76 << 3 << 73 << 5 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("single attributes spec, 1/4, attr")
|
||||||
|
<< 76 << 8 << 73 << 20 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("single attributes spec, 2/4, namespace")
|
||||||
|
<< 76 << 23 << 73 << 25 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("single attributes spec, 2/4, attr")
|
||||||
|
<< 76 << 28 << 73 << 32 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("single attributes spec, 3/4, namespace")
|
||||||
|
<< 76 << 35 << 73 << 37 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("single attributes spec, 3/4, attr")
|
||||||
|
<< 76 << 40 << 73 << 42 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("single attributes spec, 4/4, attr")
|
||||||
|
<< 76 << 45 << 73 << 53 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("attributes with using, namespace")
|
||||||
|
<< 77 << 9 << 74 << 11 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("attributes with using, attr 1/3")
|
||||||
|
<< 77 << 15 << 74 << 19 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("attributes with using, attr 2/3")
|
||||||
|
<< 77 << 22 << 74 << 34 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("attributes with using, attr 3/3")
|
||||||
|
<< 77 << 37 << 74 << 39 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("attribute with line split, namespace")
|
||||||
|
<< 79 << 9 << 76 << 11 << C_ATTRIBUTE;
|
||||||
|
QTest::newRow("attribute with line split, attr")
|
||||||
|
<< 79 << 14 << 76 << 26 << C_ATTRIBUTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void test()
|
void test()
|
||||||
|
@@ -71,3 +71,10 @@ static void parenTest2()
|
|||||||
|
|
||||||
wchar_t operator ""_wc(const wchar_t c) { return c; }
|
wchar_t operator ""_wc(const wchar_t c) { return c; }
|
||||||
const auto c = L'c'_wc;
|
const auto c = L'c'_wc;
|
||||||
|
|
||||||
|
[[gnu::always_inline]] [[gnu::hot]] [[gnu::const]] [[nodiscard]] int attr1();
|
||||||
|
[[gnu::always_inline, gnu::const, gnu::hot, nodiscard]] int attr2();
|
||||||
|
[[using gnu : const, always_inline, hot]] int attr3[
|
||||||
|
[
|
||||||
|
gnu::always_inline]
|
||||||
|
]();
|
||||||
|
@@ -543,6 +543,21 @@ TextSuggestion *TextDocumentLayout::suggestion(const QTextBlock &block)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextDocumentLayout::setAttributeState(const QTextBlock &block, quint8 attrState)
|
||||||
|
{
|
||||||
|
if (TextBlockUserData * const data = textUserData(block))
|
||||||
|
data->setAttrState(attrState);
|
||||||
|
else if (attrState)
|
||||||
|
userData(block)->setAttrState(attrState);
|
||||||
|
}
|
||||||
|
|
||||||
|
quint8 TextDocumentLayout::attributeState(const QTextBlock &block)
|
||||||
|
{
|
||||||
|
if (TextBlockUserData *userData = textUserData(block))
|
||||||
|
return userData->attrState();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void TextDocumentLayout::updateSuggestionFormats(const QTextBlock &block,
|
void TextDocumentLayout::updateSuggestionFormats(const QTextBlock &block,
|
||||||
const FontSettings &fontSettings)
|
const FontSettings &fontSettings)
|
||||||
{
|
{
|
||||||
|
@@ -153,6 +153,9 @@ public:
|
|||||||
TextSuggestion *suggestion() const;
|
TextSuggestion *suggestion() const;
|
||||||
void clearSuggestion();
|
void clearSuggestion();
|
||||||
|
|
||||||
|
void setAttrState(quint8 state) { m_attrState = state; }
|
||||||
|
quint8 attrState() const { return m_attrState; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TextMarks m_marks;
|
TextMarks m_marks;
|
||||||
int m_foldingIndent : 16;
|
int m_foldingIndent : 16;
|
||||||
@@ -168,6 +171,7 @@ private:
|
|||||||
QByteArray m_expectedRawStringSuffix; // A bit C++-specific, but let's be pragmatic.
|
QByteArray m_expectedRawStringSuffix; // A bit C++-specific, but let's be pragmatic.
|
||||||
std::unique_ptr<QTextDocument> m_replacement;
|
std::unique_ptr<QTextDocument> m_replacement;
|
||||||
std::unique_ptr<TextSuggestion> m_suggestion;
|
std::unique_ptr<TextSuggestion> m_suggestion;
|
||||||
|
quint8 m_attrState = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TEXTEDITOR_EXPORT TextDocumentLayout : public QPlainTextDocumentLayout
|
class TEXTEDITOR_EXPORT TextDocumentLayout : public QPlainTextDocumentLayout
|
||||||
@@ -201,6 +205,8 @@ public:
|
|||||||
static void setExpectedRawStringSuffix(const QTextBlock &block, const QByteArray &suffix);
|
static void setExpectedRawStringSuffix(const QTextBlock &block, const QByteArray &suffix);
|
||||||
static QByteArray expectedRawStringSuffix(const QTextBlock &block);
|
static QByteArray expectedRawStringSuffix(const QTextBlock &block);
|
||||||
static TextSuggestion *suggestion(const QTextBlock &block);
|
static TextSuggestion *suggestion(const QTextBlock &block);
|
||||||
|
static void setAttributeState(const QTextBlock &block, quint8 attrState);
|
||||||
|
static quint8 attributeState(const QTextBlock &block);
|
||||||
static void updateSuggestionFormats(const QTextBlock &block,
|
static void updateSuggestionFormats(const QTextBlock &block,
|
||||||
const FontSettings &fontSettings);
|
const FontSettings &fontSettings);
|
||||||
static bool updateSuggestion(const QTextBlock &block,
|
static bool updateSuggestion(const QTextBlock &block,
|
||||||
|
@@ -52,6 +52,7 @@ const char *nameForStyle(TextStyle style)
|
|||||||
case C_PREPROCESSOR: return "Preprocessor";
|
case C_PREPROCESSOR: return "Preprocessor";
|
||||||
case C_MACRO: return "Macro";
|
case C_MACRO: return "Macro";
|
||||||
case C_LABEL: return "Label";
|
case C_LABEL: return "Label";
|
||||||
|
case C_ATTRIBUTE: return "Attribute";
|
||||||
case C_COMMENT: return "Comment";
|
case C_COMMENT: return "Comment";
|
||||||
case C_DOXYGEN_COMMENT: return "Doxygen.Comment";
|
case C_DOXYGEN_COMMENT: return "Doxygen.Comment";
|
||||||
case C_DOXYGEN_TAG: return "Doxygen.Tag";
|
case C_DOXYGEN_TAG: return "Doxygen.Tag";
|
||||||
|
@@ -50,6 +50,7 @@ enum TextStyle : quint8 {
|
|||||||
C_PREPROCESSOR,
|
C_PREPROCESSOR,
|
||||||
C_MACRO,
|
C_MACRO,
|
||||||
C_LABEL,
|
C_LABEL,
|
||||||
|
C_ATTRIBUTE,
|
||||||
C_COMMENT,
|
C_COMMENT,
|
||||||
C_DOXYGEN_COMMENT,
|
C_DOXYGEN_COMMENT,
|
||||||
C_DOXYGEN_TAG,
|
C_DOXYGEN_TAG,
|
||||||
|
@@ -251,6 +251,8 @@ FormatDescriptions TextEditorSettingsPrivate::initialFormats()
|
|||||||
Tr::tr("Macros."), functionFormat);
|
Tr::tr("Macros."), functionFormat);
|
||||||
formatDescr.emplace_back(C_LABEL, Tr::tr("Label"), Tr::tr("Labels for goto statements."),
|
formatDescr.emplace_back(C_LABEL, Tr::tr("Label"), Tr::tr("Labels for goto statements."),
|
||||||
Qt::darkRed);
|
Qt::darkRed);
|
||||||
|
formatDescr.emplace_back(C_ATTRIBUTE, Tr::tr("Attribute"), Tr::tr("Attributes."),
|
||||||
|
Qt::darkYellow);
|
||||||
formatDescr.emplace_back(C_COMMENT, Tr::tr("Comment"),
|
formatDescr.emplace_back(C_COMMENT, Tr::tr("Comment"),
|
||||||
Tr::tr("All style of comments except Doxygen comments."),
|
Tr::tr("All style of comments except Doxygen comments."),
|
||||||
Qt::darkGreen);
|
Qt::darkGreen);
|
||||||
|
Reference in New Issue
Block a user