1 /*
2 SPDX-FileCopyrightText: 2007 Hamish Rodda <rodda@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
7 #ifndef KDEVPLATFORM_PROBLEM_H
8 #define KDEVPLATFORM_PROBLEM_H
9
10 #include <QExplicitlySharedDataPointer>
11
12 #include <language/languageexport.h>
13
14 #include "duchainbase.h"
15 #include <serialization/indexedstring.h>
16 #include "indexedtopducontext.h"
17 #include <interfaces/iproblem.h>
18 #include <interfaces/iassistant.h>
19
20 namespace KDevelop {
21 class IAssistant;
22 class Problem;
23
24 using ProblemPointer = QExplicitlySharedDataPointer<Problem>;
25
26 /**
27 * Represents a problem only by its index within the top-context
28 *
29 * Fixme: share code with the other LocalIndexed* classes
30 */
31 class KDEVPLATFORMLANGUAGE_EXPORT LocalIndexedProblem
32 {
33 public:
34 LocalIndexedProblem(const ProblemPointer& problem, const TopDUContext* top);
35 explicit LocalIndexedProblem(uint index = 0)
m_index(index)36 : m_index(index)
37 {}
38
39 /**
40 * \note Duchain must be read locked
41 */
42 ProblemPointer data(const TopDUContext* top) const;
43
44 bool operator==(const LocalIndexedProblem& rhs) const
45 {
46 return m_index == rhs.m_index;
47 }
48
isValid()49 bool isValid() const
50 {
51 return m_index;
52 }
53
54 /**
55 * Index of the Declaration within the top context
56 */
localIndex()57 uint localIndex() const
58 {
59 return m_index;
60 }
61
62 private:
63 uint m_index;
64 };
65
DECLARE_LIST_MEMBER_HASH(ProblemData,diagnostics,LocalIndexedProblem)66 KDEVPLATFORMLANGUAGE_EXPORT DECLARE_LIST_MEMBER_HASH(ProblemData, diagnostics, LocalIndexedProblem)
67
68 class KDEVPLATFORMLANGUAGE_EXPORT ProblemData
69 : public DUChainBaseData
70 {
71 public:
72 ProblemData()
73 {
74 initializeAppendedLists();
75 }
76
77 ProblemData(const ProblemData& rhs)
78 : DUChainBaseData(rhs)
79 , source(rhs.source)
80 , severity(rhs.severity)
81 , url(rhs.url)
82 , description(rhs.description)
83 , explanation(rhs.explanation)
84 {
85 initializeAppendedLists();
86 copyListsFrom(rhs);
87 }
88
89 ~ProblemData()
90 {
91 freeAppendedLists();
92 }
93
94 ProblemData& operator=(const ProblemData& rhs) = delete;
95
96 IProblem::Source source = IProblem::Unknown;
97 IProblem::Severity severity = IProblem::Error;
98 IndexedString url;
99 IndexedString description;
100 IndexedString explanation;
101 IProblem::FinalLocationMode finalLocationMode = IProblem::Range;
102
103 START_APPENDED_LISTS_BASE(ProblemData, DUChainBaseData);
104 APPENDED_LIST_FIRST(ProblemData, LocalIndexedProblem, diagnostics);
105 END_APPENDED_LISTS(ProblemData, diagnostics);
106 };
107
108 /**
109 * An object representing a problem in preprocessing, parsing, definition-use chain compilation, etc.
110 *
111 * You should always use ProblemPointer, because Problem may be subclassed.
112 * The subclass would be lost while copying.
113 *
114 * @warning Access to problems must be serialized through DUChainLock.
115 */
116 class KDEVPLATFORMLANGUAGE_EXPORT Problem
117 : public DUChainBase
118 , public IProblem
119 {
120 public:
121 using Ptr = QExplicitlySharedDataPointer<Problem>;
122
123 Problem();
124 explicit Problem(ProblemData& data);
125 ~Problem() override;
126
127 Source source() const override;
128 void setSource(IProblem::Source source) override;
129
130 /**
131 * Returns a string version of the problem source
132 */
133 QString sourceString() const override;
134
135 TopDUContext* topContext() const override;
136 KDevelop::IndexedString url() const override;
137
138 /**
139 * Location where this problem occurred
140 * @warning Must only be called from the foreground
141 * */
142 DocumentRange finalLocation() const override;
143 void setFinalLocation(const DocumentRange& location) override;
144
145 FinalLocationMode finalLocationMode() const override;
146 void setFinalLocationMode(FinalLocationMode mode) override;
147
148 /**
149 * Returns child diagnostics of this particular problem
150 *
151 * Example:
152 * @code
153 * void foo(unsigned int);
154 * void foo(const char*);
155 * int main() { foo(0); }
156 * @endcode
157 *
158 * => foo(0) is ambiguous. This will give us a ProblemPointer pointing to 'foo(0)'.
159 *
160 * Additionally, @p diagnostics may return the two locations to the ambiguous overloads,
161 * with descriptions such as 'test.cpp:1: candidate : ...'
162 */
163 void clearDiagnostics() override;
164
165 QVector<IProblem::Ptr> diagnostics() const override;
166 void setDiagnostics(const QVector<IProblem::Ptr>& diagnostics) override;
167 void addDiagnostic(const IProblem::Ptr& diagnostic) override;
168
169 /**
170 * A brief description of the problem.
171 */
172 QString description() const override;
173 void setDescription(const QString& description) override;
174
175 /**
176 * A (detailed) explanation of why the problem occurred.
177 */
178 QString explanation() const override;
179 void setExplanation(const QString& explanation) override;
180
181 /**
182 * Get the severity of this problem.
183 * This is used for example to decide for a highlighting color.
184 *
185 * @see setSeverity()
186 */
187 Severity severity() const override;
188
189 /**
190 * Set the severity of this problem.
191 */
192 void setSeverity(Severity severity) override;
193
194 /**
195 * Returns a string representation of the severity.
196 */
197 QString severityString() const override;
198
199 /**
200 * If this problem can be solved, this may return an assistant for the solution.
201 */
202 QExplicitlySharedDataPointer<IAssistant> solutionAssistant() const override;
203
204 enum {
205 Identity = 15
206 };
207
208 /**
209 * Returns a string representation of this problem, useful for debugging.
210 */
211 virtual QString toString() const;
212
213 private:
214 void rebuildDynamicData(DUContext* parent, uint ownIndex) override;
215
216 Q_DISABLE_COPY(Problem)
217
218 DUCHAIN_DECLARE_DATA(Problem)
219 friend class TopDUContext;
220 friend class TopDUContextDynamicData;
221 friend class LocalIndexedProblem;
222
223 //BEGIN dynamic data
224 TopDUContextPointer m_topContext;
225 mutable QList<Ptr> m_diagnostics;
226 uint m_indexInTopContext = 0;
227 //END dynamic data
228 };
229
230 class KDEVPLATFORMLANGUAGE_EXPORT StaticAssistantProblem
231 : public KDevelop::Problem
232 {
233 public:
solutionAssistant()234 KDevelop::IAssistant::Ptr solutionAssistant() const override
235 {
236 return m_solution;
237 }
setSolutionAssistant(const KDevelop::IAssistant::Ptr & p)238 void setSolutionAssistant(const KDevelop::IAssistant::Ptr& p)
239 {
240 m_solution = p;
241 }
242
243 private:
244 KDevelop::IAssistant::Ptr m_solution;
245 };
246 }
247
248 Q_DECLARE_TYPEINFO(KDevelop::LocalIndexedProblem, Q_MOVABLE_TYPE);
249
250 KDEVPLATFORMLANGUAGE_EXPORT QDebug operator<<(QDebug s, const KDevelop::Problem& problem);
251 KDEVPLATFORMLANGUAGE_EXPORT QDebug operator<<(QDebug s, const KDevelop::ProblemPointer& problem);
252
253 #endif // KDEVPLATFORM_PROBLEM_H
254