forked from qt-creator/qt-creator
TextEditor: Implement highlighting of function definitions
This allows users to style function names at their definitions. Once set, the XML-style token "FunctionDefinition" will highlight all function definitions: the style option is a mixin to Function and Virtual Function. TEST=Default themes and locally hacked themes that lack Function, FunctionDefinition, Declaration-styling look as they did before this patch. Requires Clang. Task-number: QTCREATORBUG-16625 Change-Id: I49d8e401211bdf28ff74699feac16fe98f6d64ce Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
@@ -84,8 +84,9 @@ enum class HighlightingType : quint8
|
||||
PreprocessorDefinition,
|
||||
PreprocessorExpansion,
|
||||
Label,
|
||||
OutputArgument,
|
||||
Declaration
|
||||
Declaration,
|
||||
FunctionDefinition,
|
||||
OutputArgument
|
||||
};
|
||||
|
||||
enum class CompletionCorrection : quint32
|
||||
|
@@ -50,6 +50,7 @@ static const char *highlightingTypeToCStringLiteral(HighlightingType type)
|
||||
RETURN_TEXT_FOR_CASE(Operator);
|
||||
RETURN_TEXT_FOR_CASE(Preprocessor);
|
||||
RETURN_TEXT_FOR_CASE(Label);
|
||||
RETURN_TEXT_FOR_CASE(FunctionDefinition);
|
||||
RETURN_TEXT_FOR_CASE(OutputArgument);
|
||||
RETURN_TEXT_FOR_CASE(PreprocessorDefinition);
|
||||
RETURN_TEXT_FOR_CASE(PreprocessorExpansion);
|
||||
|
@@ -63,6 +63,8 @@ TextEditor::TextStyle toTextStyle(ClangBackEnd::HighlightingType type)
|
||||
return TextEditor::C_PREPROCESSOR;
|
||||
case HighlightingType::Declaration:
|
||||
return TextEditor::C_DECLARATION;
|
||||
case HighlightingType::FunctionDefinition:
|
||||
return TextEditor::C_FUNCTION_DEFINITION;
|
||||
case HighlightingType::OutputArgument:
|
||||
return TextEditor::C_OUTPUT_ARGUMENT;
|
||||
case HighlightingType::Operator:
|
||||
|
@@ -46,6 +46,10 @@ public:
|
||||
Format() = default;
|
||||
Format(const QColor &foreground, const QColor &background);
|
||||
|
||||
static Format createMixinFormat() {
|
||||
return Format(QColor(), QColor());
|
||||
}
|
||||
|
||||
QColor foreground() const { return m_foreground; }
|
||||
void setForeground(const QColor &foreground);
|
||||
|
||||
|
@@ -101,8 +101,9 @@ const char *nameForStyle(TextStyle style)
|
||||
case C_WARNING: return "Warning";
|
||||
case C_WARNING_CONTEXT: return "WarningContext";
|
||||
|
||||
case C_DECLARATION: return "Declaration";
|
||||
case C_OUTPUT_ARGUMENT: return "OutputArgument";
|
||||
case C_DECLARATION: return "Declaration";
|
||||
case C_FUNCTION_DEFINITION: return "FunctionDefinition";
|
||||
case C_OUTPUT_ARGUMENT: return "OutputArgument";
|
||||
|
||||
case C_LAST_STYLE_SENTINEL: return "LastStyleSentinel";
|
||||
}
|
||||
|
@@ -100,6 +100,7 @@ enum TextStyle : quint8 {
|
||||
C_ERROR_CONTEXT,
|
||||
|
||||
C_DECLARATION,
|
||||
C_FUNCTION_DEFINITION,
|
||||
C_OUTPUT_ARGUMENT,
|
||||
|
||||
C_LAST_STYLE_SENTINEL
|
||||
|
@@ -288,6 +288,8 @@ TextEditorSettings::TextEditorSettings(QObject *parent)
|
||||
tr("Applied to lines describing changes in VCS log."),
|
||||
Format(QColor(192, 0, 0), QColor()));
|
||||
|
||||
|
||||
// Mixin categories
|
||||
formatDescr.emplace_back(C_ERROR,
|
||||
tr("Error"),
|
||||
tr("Underline color of error diagnostics."),
|
||||
@@ -312,14 +314,19 @@ TextEditorSettings::TextEditorSettings(QObject *parent)
|
||||
QColor(255, 190, 0),
|
||||
QTextCharFormat::DotLine,
|
||||
FormatDescription::ShowUnderlineControl);
|
||||
Format declarationFormat;
|
||||
Format declarationFormat = Format::createMixinFormat();
|
||||
declarationFormat.setBold(true);
|
||||
formatDescr.emplace_back(C_DECLARATION,
|
||||
tr("Function Declaration"),
|
||||
tr("Style adjustments to function declarations."),
|
||||
tr("Style adjustments to (function) declarations."),
|
||||
declarationFormat,
|
||||
FormatDescription::ShowFontUnderlineAndRelativeControls);
|
||||
Format outputArgumentFormat;
|
||||
formatDescr.emplace_back(C_FUNCTION_DEFINITION,
|
||||
tr("Function Definition"),
|
||||
tr("Name of function at its definition."),
|
||||
Format::createMixinFormat(),
|
||||
FormatDescription::ShowFontUnderlineAndRelativeControls);
|
||||
Format outputArgumentFormat = Format::createMixinFormat();
|
||||
outputArgumentFormat.setItalic(true);
|
||||
formatDescr.emplace_back(C_OUTPUT_ARGUMENT,
|
||||
tr("Output Argument"),
|
||||
|
@@ -84,6 +84,10 @@ bool HighlightingMark::hasMainType(HighlightingType type) const
|
||||
return m_types.mainHighlightingType == type;
|
||||
}
|
||||
|
||||
unsigned HighlightingMark::mixinSize() const {
|
||||
return m_types.mixinHighlightingTypes.size();
|
||||
}
|
||||
|
||||
bool HighlightingMark::hasMixinType(HighlightingType type) const
|
||||
{
|
||||
auto found = std::find(m_types.mixinHighlightingTypes.begin(),
|
||||
@@ -93,6 +97,12 @@ bool HighlightingMark::hasMixinType(HighlightingType type) const
|
||||
return found != m_types.mixinHighlightingTypes.end();
|
||||
}
|
||||
|
||||
bool HighlightingMark::hasMixinTypeAt(uint position, HighlightingType type) const
|
||||
{
|
||||
return m_types.mixinHighlightingTypes.size() > position &&
|
||||
m_types.mixinHighlightingTypes.at(position) == type;
|
||||
}
|
||||
|
||||
bool HighlightingMark::hasOnlyType(HighlightingType type) const
|
||||
{
|
||||
return m_types.mixinHighlightingTypes.size() == 0 && hasMainType(type);
|
||||
@@ -191,17 +201,22 @@ void HighlightingMark::fieldKind(const Cursor &)
|
||||
m_types.mixinHighlightingTypes.push_back(HighlightingType::OutputArgument);
|
||||
}
|
||||
|
||||
bool HighlightingMark::isDefinition() const
|
||||
{
|
||||
return m_originalCursor.isDefinition();
|
||||
}
|
||||
|
||||
bool HighlightingMark::isVirtualMethodDeclarationOrDefinition(const Cursor &cursor) const
|
||||
{
|
||||
return cursor.isVirtualMethod()
|
||||
&& (m_originalCursor.isDeclaration() || m_originalCursor.isDefinition());
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool isNotFinalFunction(const Cursor &cursor)
|
||||
{
|
||||
return !cursor.hasFinalFunctionAttribute();
|
||||
}
|
||||
|
||||
}
|
||||
bool HighlightingMark::isRealDynamicCall(const Cursor &cursor) const
|
||||
{
|
||||
@@ -285,6 +300,9 @@ void HighlightingMark::functionKind(const Cursor &cursor, Recursion recursion)
|
||||
m_types.mixinHighlightingTypes.push_back(HighlightingType::OutputArgument);
|
||||
|
||||
addExtraTypeIfFirstPass(HighlightingType::Declaration, recursion);
|
||||
|
||||
if (isDefinition())
|
||||
addExtraTypeIfFirstPass(HighlightingType::FunctionDefinition, recursion);
|
||||
}
|
||||
|
||||
void HighlightingMark::identifierKind(const Cursor &cursor, Recursion recursion)
|
||||
|
@@ -53,7 +53,9 @@ public:
|
||||
|
||||
bool hasInvalidMainType() const;
|
||||
bool hasMainType(HighlightingType type) const;
|
||||
unsigned mixinSize() const;
|
||||
bool hasMixinType(HighlightingType type) const;
|
||||
bool hasMixinTypeAt(uint, HighlightingType type) const;
|
||||
bool hasOnlyType(HighlightingType type) const;
|
||||
bool hasFunctionArguments() const;
|
||||
|
||||
@@ -66,6 +68,7 @@ private:
|
||||
void variableKind(const Cursor &cursor);
|
||||
void fieldKind(const Cursor &cursor);
|
||||
bool isVirtualMethodDeclarationOrDefinition(const Cursor &cursor) const;
|
||||
bool isDefinition() const;
|
||||
void functionKind(const Cursor &cursor, Recursion recursion);
|
||||
void memberReferenceKind(const Cursor &cursor);
|
||||
HighlightingType punctuationKind(const Cursor &cursor);
|
||||
|
@@ -629,6 +629,7 @@ void ClangCodeModelServer::expectDocumentAnnotationsChangedForFileBWithSpecificH
|
||||
HighlightingTypes types;
|
||||
types.mainHighlightingType = ClangBackEnd::HighlightingType::Function;
|
||||
types.mixinHighlightingTypes.push_back(ClangBackEnd::HighlightingType::Declaration);
|
||||
types.mixinHighlightingTypes.push_back(ClangBackEnd::HighlightingType::FunctionDefinition);
|
||||
const HighlightingMarkContainer highlightingMark(1, 6, 8, types, true);
|
||||
|
||||
EXPECT_CALL(mockClangCodeModelClient,
|
||||
|
@@ -582,3 +582,9 @@ void f32()
|
||||
|
||||
namespace N { template <typename T> void SizeIs(); }
|
||||
using N::SizeIs;
|
||||
|
||||
void BaseClass::VirtualFunction() {}
|
||||
|
||||
class WithVirtualFunctionDefined {
|
||||
virtual void VirtualFunctionDefinition() {};
|
||||
};
|
||||
|
@@ -95,15 +95,27 @@ MATCHER_P2(HasTwoTypes, firstType, secondType,
|
||||
+ PrintToString(secondType)
|
||||
)
|
||||
{
|
||||
return arg.hasMainType(firstType) && arg.hasMixinType(secondType);
|
||||
return arg.hasMainType(firstType) && arg.hasMixinTypeAt(0, secondType) && arg.mixinSize() == 1;
|
||||
}
|
||||
|
||||
MATCHER_P(HasMixin, firstType,
|
||||
MATCHER_P3(HasThreeTypes, firstType, secondType, thirdType,
|
||||
std::string(negation ? "isn't " : "is ")
|
||||
+ PrintToString(firstType)
|
||||
+ ", "
|
||||
+ PrintToString(secondType)
|
||||
+ " and "
|
||||
+ PrintToString(thirdType)
|
||||
)
|
||||
{
|
||||
return arg.hasMainType(firstType) && arg.hasMixinTypeAt(0, secondType) && arg.hasMixinTypeAt(1, thirdType) && arg.mixinSize() == 2;
|
||||
}
|
||||
|
||||
MATCHER_P(HasMixin, mixinType,
|
||||
std::string(negation ? "isn't " : "is ")
|
||||
+ PrintToString(firstType)
|
||||
+ PrintToString(mixinType)
|
||||
)
|
||||
{
|
||||
return arg.hasMixinType(firstType);
|
||||
return arg.hasMixinType(mixinType);
|
||||
}
|
||||
|
||||
struct Data {
|
||||
@@ -244,14 +256,28 @@ TEST_F(HighlightingMarks, FunctionDefinition)
|
||||
{
|
||||
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(45, 20));
|
||||
|
||||
ASSERT_THAT(infos[1], HasTwoTypes(HighlightingType::Function, HighlightingType::Declaration));
|
||||
ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Function, HighlightingType::Declaration, HighlightingType::FunctionDefinition));
|
||||
}
|
||||
|
||||
TEST_F(HighlightingMarks, MemberFunctionDefinition)
|
||||
{
|
||||
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(52, 29));
|
||||
|
||||
ASSERT_THAT(infos[1], HasTwoTypes(HighlightingType::Function, HighlightingType::Declaration));
|
||||
ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Function, HighlightingType::Declaration, HighlightingType::FunctionDefinition));
|
||||
}
|
||||
|
||||
TEST_F(HighlightingMarks, VirtualMemberFunctionDefinitionOutsideOfClassBody)
|
||||
{
|
||||
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(586, 37));
|
||||
|
||||
ASSERT_THAT(infos[3], HasThreeTypes(HighlightingType::VirtualFunction, HighlightingType::Declaration, HighlightingType::FunctionDefinition));
|
||||
}
|
||||
|
||||
TEST_F(HighlightingMarks, VirtualMemberFunctionDefinitionInsideOfClassBody)
|
||||
{
|
||||
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(589, 47));
|
||||
|
||||
ASSERT_THAT(infos[2], HasThreeTypes(HighlightingType::VirtualFunction, HighlightingType::Declaration, HighlightingType::FunctionDefinition));
|
||||
}
|
||||
|
||||
TEST_F(HighlightingMarks, FunctionDeclaration)
|
||||
|
Reference in New Issue
Block a user