File: codehighlighting.h

package info (click to toggle)
kdevelop 4%3A22.12.2-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 70,096 kB
  • sloc: cpp: 284,635; javascript: 3,558; python: 3,422; sh: 1,319; ansic: 685; xml: 331; php: 95; lisp: 66; makefile: 39; sed: 12
file content (201 lines) | stat: -rw-r--r-- 6,632 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/*
    SPDX-FileCopyrightText: 2007-2010 David Nolden <david.nolden.kdevelop@art-master.de>
    SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org>
    SPDX-FileCopyrightText: 2009 Milian Wolff <mail@milianw.de>

    SPDX-License-Identifier: LGPL-2.0-or-later
*/

#ifndef KDEVPLATFORM_CODEHIGHLIGHTING_H
#define KDEVPLATFORM_CODEHIGHLIGHTING_H

#include <QObject>
#include <QHash>
#include <QRecursiveMutex>

#include <serialization/indexedstring.h>
#include <language/duchain/ducontext.h>
#include <language/interfaces/icodehighlighting.h>
#include <language/backgroundparser/documentchangetracker.h>

#include <KTextEditor/Attribute>
#include <KTextEditor/MovingRange>

namespace KDevelop {
class DUContext;
class Declaration;

using ColorMap = QVector<KDevelop::Declaration*>;

class CodeHighlighting;

enum class CodeHighlightingType {
    Error,

    LocalClassMember,
    LocalMemberFunction,
    InheritedClassMember,
    InheritedMemberFunction,
    LocalVariable,
    MemberVariable,
    NamespaceVariable,
    GlobalVariable,
    FunctionVariable,

    Class,
    Namespace,
    Function,
    ForwardDeclaration,
    Enum,
    Enumerator,
    TypeAlias,
    Macro, ///< Declaration of a macro such as "#define FOO"
    MacroFunctionLike, ///< Declaration of a function like macro such as "#define FOO()"
    HighlightUses,
};

inline uint qHash(CodeHighlightingType type, uint seed = 0) noexcept
{
    return ::qHash(static_cast<int>(type), seed);
}

enum class CodeHighlightingContext {
    Definition,
    Declaration,
    Reference,
};

struct HighlightedRange
{
    RangeInRevision range;
    KTextEditor::Attribute::Ptr attribute;
    bool operator<(const HighlightedRange& rhs) const
    {
        return range.start < rhs.range.start;
    }
};

/**
 * Code highlighting instance that is used to apply code highlighting to one specific top context
 * */

class KDEVPLATFORMLANGUAGE_EXPORT CodeHighlightingInstance
{
public:
    explicit CodeHighlightingInstance(const CodeHighlighting* highlighting) : m_useClassCache(false)
        , m_highlighting(highlighting)
    {
    }
    virtual ~CodeHighlightingInstance()
    {
    }

    virtual void highlightDeclaration(KDevelop::Declaration* declaration, const QColor& color);
    virtual void highlightUse(KDevelop::DUContext* context, int index, const QColor& color);
    virtual void highlightUses(KDevelop::DUContext* context);

    void highlightDUChain(KDevelop::TopDUContext* context);
    void highlightDUChain(KDevelop::DUContext* context, QHash<KDevelop::Declaration*, uint> colorsForDeclarations,
        ColorMap);

    KDevelop::Declaration* localClassFromCodeContext(KDevelop::DUContext* context) const;
    /**
     * @param context Should be the context from where the declaration is used, if a use is highlighted.
     * */
    virtual CodeHighlightingType typeForDeclaration(KDevelop::Declaration* dec, KDevelop::DUContext* context) const;
    /**
     * Decides whether to apply auto-generated rainbow colors to @p dec.
     * Default implementation only applies that to local variables in functions.
     */
    virtual bool useRainbowColor(KDevelop::Declaration* dec) const;

    //A temporary hash for speedup
    mutable QHash<KDevelop::DUContext*, KDevelop::Declaration*> m_contextClasses;

    //Here the colors of function context are stored until they are merged into the function body
    mutable QHash<KDevelop::IndexedDUContext, QHash<KDevelop::Declaration*, uint>> m_functionColorsForDeclarations;
    mutable QHash<KDevelop::IndexedDUContext, ColorMap> m_functionDeclarationsForColors;

    mutable bool m_useClassCache;
    const CodeHighlighting* m_highlighting;

    QVector<HighlightedRange> m_highlight;
};

/**
 * General class representing the code highlighting for one language
 * */
class KDEVPLATFORMLANGUAGE_EXPORT CodeHighlighting : public QObject, public KDevelop::ICodeHighlighting
{
    Q_OBJECT
    Q_INTERFACES(KDevelop::ICodeHighlighting)

public:

    explicit CodeHighlighting(QObject* parent);
    ~CodeHighlighting() override;

    /// This function is thread-safe
    /// @warning The duchain must not be locked when this is called (->possible deadlock)
    void highlightDUChain(ReferencedTopDUContext context) override;

    //color should be zero when undecided
    KTextEditor::Attribute::Ptr attributeForType(CodeHighlightingType type, CodeHighlightingContext context,
                                                 const QColor& color) const;
    KTextEditor::Attribute::Ptr attributeForDepth(int depth) const;

    /// This function is thread-safe
    /// Returns whether a highlighting is already given for the given url
    bool hasHighlighting(IndexedString url) const override;

private:
    //Returns whether the given attribute was set by the code highlighting, and not by something else
    //Always returns true when the attribute is zero
    bool isCodeHighlight(KTextEditor::Attribute::Ptr attr) const;

protected:
    //Can be overridden to create an own instance type
    virtual CodeHighlightingInstance* createInstance() const;

private:

    /// Highlighting of one specific document
    struct DocumentHighlighting
    {
        IndexedString m_document;
        qint64 m_waitingRevision;
        // The ranges are sorted by range start, so they can easily be matched
        QVector<HighlightedRange> m_waiting;
        QVector<KTextEditor::MovingRange*> m_highlightedRanges;
    };

    QHash<DocumentChangeTracker*, DocumentHighlighting*> m_highlights;

    friend class CodeHighlightingInstance;

    mutable QHash<CodeHighlightingType, KTextEditor::Attribute::Ptr> m_definitionAttributes;
    mutable QHash<CodeHighlightingType, KTextEditor::Attribute::Ptr> m_declarationAttributes;
    mutable QHash<CodeHighlightingType, KTextEditor::Attribute::Ptr> m_referenceAttributes;
    mutable QList<KTextEditor::Attribute::Ptr> m_depthAttributes;
    // Should be used to enable/disable the colorization of local variables and their uses
    bool m_localColorization;
    // Should be used to enable/disable the colorization of global types and their uses
    bool m_globalColorization;

    mutable QRecursiveMutex m_dataMutex;

private Q_SLOTS:
    void clearHighlightingForDocument(const KDevelop::IndexedString& document);
    void applyHighlighting(void* highlighting);

    /// when the colors change we must invalidate our local caches
    void adaptToColorChanges();

    void aboutToInvalidateMovingInterfaceContent(KTextEditor::Document*);
    void aboutToRemoveText(const KTextEditor::Range&);
};
}

Q_DECLARE_TYPEINFO(KDevelop::HighlightedRange, Q_MOVABLE_TYPE);

#endif