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