File indexing completed on 2024-05-12 04:38:06
0001 /* 0002 SPDX-FileCopyrightText: 2007-2010 David Nolden <david.nolden.kdevelop@art-master.de> 0003 SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org> 0004 SPDX-FileCopyrightText: 2009 Milian Wolff <mail@milianw.de> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #ifndef KDEVPLATFORM_CODEHIGHLIGHTING_H 0010 #define KDEVPLATFORM_CODEHIGHLIGHTING_H 0011 0012 #include <QObject> 0013 #include <QHash> 0014 #include <QRecursiveMutex> 0015 0016 #include <serialization/indexedstring.h> 0017 #include <language/duchain/ducontext.h> 0018 #include <language/interfaces/icodehighlighting.h> 0019 #include <language/backgroundparser/documentchangetracker.h> 0020 0021 #include <KTextEditor/Attribute> 0022 #include <KTextEditor/MovingRange> 0023 0024 namespace KDevelop { 0025 class DUContext; 0026 class Declaration; 0027 0028 using ColorMap = QVector<KDevelop::Declaration*>; 0029 0030 class CodeHighlighting; 0031 0032 enum class CodeHighlightingType { 0033 Error, 0034 0035 LocalClassMember, 0036 LocalMemberFunction, 0037 InheritedClassMember, 0038 InheritedMemberFunction, 0039 LocalVariable, 0040 MemberVariable, 0041 NamespaceVariable, 0042 GlobalVariable, 0043 FunctionVariable, 0044 0045 Class, 0046 Namespace, 0047 Function, 0048 ForwardDeclaration, 0049 Enum, 0050 Enumerator, 0051 TypeAlias, 0052 Macro, ///< Declaration of a macro such as "#define FOO" 0053 MacroFunctionLike, ///< Declaration of a function like macro such as "#define FOO()" 0054 HighlightUses, 0055 }; 0056 0057 inline uint qHash(CodeHighlightingType type, uint seed = 0) noexcept 0058 { 0059 return ::qHash(static_cast<int>(type), seed); 0060 } 0061 0062 enum class CodeHighlightingContext { 0063 Definition, 0064 Declaration, 0065 Reference, 0066 }; 0067 0068 struct HighlightedRange 0069 { 0070 RangeInRevision range; 0071 KTextEditor::Attribute::Ptr attribute; 0072 bool operator<(const HighlightedRange& rhs) const 0073 { 0074 return range.start < rhs.range.start; 0075 } 0076 }; 0077 0078 /** 0079 * Code highlighting instance that is used to apply code highlighting to one specific top context 0080 * */ 0081 0082 class KDEVPLATFORMLANGUAGE_EXPORT CodeHighlightingInstance 0083 { 0084 public: 0085 explicit CodeHighlightingInstance(const CodeHighlighting* highlighting) : m_useClassCache(false) 0086 , m_highlighting(highlighting) 0087 { 0088 } 0089 virtual ~CodeHighlightingInstance() 0090 { 0091 } 0092 0093 virtual void highlightDeclaration(KDevelop::Declaration* declaration, const QColor& color); 0094 virtual void highlightUse(KDevelop::DUContext* context, int index, const QColor& color); 0095 virtual void highlightUses(KDevelop::DUContext* context); 0096 0097 void highlightDUChain(KDevelop::TopDUContext* context); 0098 void highlightDUChain(KDevelop::DUContext* context, QHash<KDevelop::Declaration*, uint> colorsForDeclarations, 0099 ColorMap); 0100 0101 KDevelop::Declaration* localClassFromCodeContext(KDevelop::DUContext* context) const; 0102 /** 0103 * @param context Should be the context from where the declaration is used, if a use is highlighted. 0104 * */ 0105 virtual CodeHighlightingType typeForDeclaration(KDevelop::Declaration* dec, KDevelop::DUContext* context) const; 0106 /** 0107 * Decides whether to apply auto-generated rainbow colors to @p dec. 0108 * Default implementation only applies that to local variables in functions. 0109 */ 0110 virtual bool useRainbowColor(KDevelop::Declaration* dec) const; 0111 0112 //A temporary hash for speedup 0113 mutable QHash<KDevelop::DUContext*, KDevelop::Declaration*> m_contextClasses; 0114 0115 //Here the colors of function context are stored until they are merged into the function body 0116 mutable QHash<KDevelop::IndexedDUContext, QHash<KDevelop::Declaration*, uint>> m_functionColorsForDeclarations; 0117 mutable QHash<KDevelop::IndexedDUContext, ColorMap> m_functionDeclarationsForColors; 0118 0119 mutable bool m_useClassCache; 0120 const CodeHighlighting* m_highlighting; 0121 0122 QVector<HighlightedRange> m_highlight; 0123 }; 0124 0125 /** 0126 * General class representing the code highlighting for one language 0127 * */ 0128 class KDEVPLATFORMLANGUAGE_EXPORT CodeHighlighting : public QObject, public KDevelop::ICodeHighlighting 0129 { 0130 Q_OBJECT 0131 Q_INTERFACES(KDevelop::ICodeHighlighting) 0132 0133 public: 0134 0135 explicit CodeHighlighting(QObject* parent); 0136 ~CodeHighlighting() override; 0137 0138 /// This function is thread-safe 0139 /// @warning The duchain must not be locked when this is called (->possible deadlock) 0140 void highlightDUChain(ReferencedTopDUContext context) override; 0141 0142 //color should be zero when undecided 0143 KTextEditor::Attribute::Ptr attributeForType(CodeHighlightingType type, CodeHighlightingContext context, 0144 const QColor& color) const; 0145 KTextEditor::Attribute::Ptr attributeForDepth(int depth) const; 0146 0147 /// This function is thread-safe 0148 /// Returns whether a highlighting is already given for the given url 0149 bool hasHighlighting(IndexedString url) const override; 0150 0151 private: 0152 //Returns whether the given attribute was set by the code highlighting, and not by something else 0153 //Always returns true when the attribute is zero 0154 bool isCodeHighlight(KTextEditor::Attribute::Ptr attr) const; 0155 0156 protected: 0157 //Can be overridden to create an own instance type 0158 virtual CodeHighlightingInstance* createInstance() const; 0159 0160 private: 0161 0162 /// Highlighting of one specific document 0163 struct DocumentHighlighting 0164 { 0165 IndexedString m_document; 0166 qint64 m_waitingRevision; 0167 // The ranges are sorted by range start, so they can easily be matched 0168 QVector<HighlightedRange> m_waiting; 0169 QVector<KTextEditor::MovingRange*> m_highlightedRanges; 0170 }; 0171 0172 QHash<DocumentChangeTracker*, DocumentHighlighting*> m_highlights; 0173 0174 friend class CodeHighlightingInstance; 0175 0176 mutable QHash<CodeHighlightingType, KTextEditor::Attribute::Ptr> m_definitionAttributes; 0177 mutable QHash<CodeHighlightingType, KTextEditor::Attribute::Ptr> m_declarationAttributes; 0178 mutable QHash<CodeHighlightingType, KTextEditor::Attribute::Ptr> m_referenceAttributes; 0179 mutable QList<KTextEditor::Attribute::Ptr> m_depthAttributes; 0180 // Should be used to enable/disable the colorization of local variables and their uses 0181 bool m_localColorization; 0182 // Should be used to enable/disable the colorization of global types and their uses 0183 bool m_globalColorization; 0184 0185 mutable QRecursiveMutex m_dataMutex; 0186 0187 private Q_SLOTS: 0188 void clearHighlightingForDocument(const KDevelop::IndexedString& document); 0189 void applyHighlighting(void* highlighting); 0190 0191 /// when the colors change we must invalidate our local caches 0192 void adaptToColorChanges(); 0193 0194 void aboutToInvalidateMovingInterfaceContent(KTextEditor::Document*); 0195 void aboutToRemoveText(const KTextEditor::Range&); 0196 }; 0197 } 0198 0199 Q_DECLARE_TYPEINFO(KDevelop::HighlightedRange, Q_MOVABLE_TYPE); 0200 0201 #endif