File indexing completed on 2024-05-12 04:38:04

0001 /*
0002     SPDX-FileCopyrightText: 2007 Hamish Rodda <rodda@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #ifndef KDEVPLATFORM_PROBLEM_H
0008 #define KDEVPLATFORM_PROBLEM_H
0009 
0010 #include <QExplicitlySharedDataPointer>
0011 
0012 #include <language/languageexport.h>
0013 
0014 #include "duchainbase.h"
0015 #include <serialization/indexedstring.h>
0016 #include "indexedtopducontext.h"
0017 #include <interfaces/iproblem.h>
0018 #include <interfaces/iassistant.h>
0019 
0020 namespace KDevelop {
0021 class IAssistant;
0022 class Problem;
0023 
0024 using ProblemPointer = QExplicitlySharedDataPointer<Problem>;
0025 
0026 /**
0027  * Represents a problem only by its index within the top-context
0028  *
0029  * Fixme: share code with the other LocalIndexed* classes
0030  */
0031 class KDEVPLATFORMLANGUAGE_EXPORT LocalIndexedProblem
0032 {
0033 public:
0034     LocalIndexedProblem(const ProblemPointer& problem, const TopDUContext* top);
0035     explicit LocalIndexedProblem(uint index = 0)
0036         : m_index(index)
0037     {}
0038 
0039     /**
0040      * \note Duchain must be read locked
0041      */
0042     ProblemPointer data(const TopDUContext* top) const;
0043 
0044     bool operator==(const LocalIndexedProblem& rhs) const
0045     {
0046         return m_index == rhs.m_index;
0047     }
0048 
0049     bool isValid() const
0050     {
0051         return m_index;
0052     }
0053 
0054     /**
0055      * Index of the Declaration within the top context
0056      */
0057     uint localIndex() const
0058     {
0059         return m_index;
0060     }
0061 
0062 private:
0063     uint m_index;
0064 };
0065 
0066 KDEVPLATFORMLANGUAGE_EXPORT DECLARE_LIST_MEMBER_HASH(ProblemData, diagnostics, LocalIndexedProblem)
0067 
0068 class KDEVPLATFORMLANGUAGE_EXPORT ProblemData
0069     : public DUChainBaseData
0070 {
0071 public:
0072     ProblemData()
0073     {
0074         initializeAppendedLists();
0075     }
0076 
0077     ProblemData(const ProblemData& rhs)
0078         : DUChainBaseData(rhs)
0079         , source(rhs.source)
0080         , severity(rhs.severity)
0081         , url(rhs.url)
0082         , description(rhs.description)
0083         , explanation(rhs.explanation)
0084     {
0085         initializeAppendedLists();
0086         copyListsFrom(rhs);
0087     }
0088 
0089     ~ProblemData()
0090     {
0091         freeAppendedLists();
0092     }
0093 
0094     ProblemData& operator=(const ProblemData& rhs) = delete;
0095 
0096     IProblem::Source source = IProblem::Unknown;
0097     IProblem::Severity severity = IProblem::Error;
0098     IndexedString url;
0099     IndexedString description;
0100     IndexedString explanation;
0101     IProblem::FinalLocationMode finalLocationMode = IProblem::Range;
0102 
0103     START_APPENDED_LISTS_BASE(ProblemData, DUChainBaseData);
0104     APPENDED_LIST_FIRST(ProblemData, LocalIndexedProblem, diagnostics);
0105     END_APPENDED_LISTS(ProblemData, diagnostics);
0106 };
0107 
0108 /**
0109  * An object representing a problem in preprocessing, parsing, definition-use chain compilation, etc.
0110  *
0111  * You should always use ProblemPointer, because Problem may be subclassed.
0112  * The subclass would be lost while copying.
0113  *
0114  * @warning Access to problems must be serialized through DUChainLock.
0115  */
0116 class KDEVPLATFORMLANGUAGE_EXPORT Problem
0117     : public DUChainBase
0118     , public IProblem
0119 {
0120 public:
0121     using Ptr = QExplicitlySharedDataPointer<Problem>;
0122 
0123     Problem();
0124     explicit Problem(ProblemData& data);
0125     ~Problem() override;
0126 
0127     Source source() const override;
0128     void setSource(IProblem::Source source) override;
0129 
0130     /**
0131      * Returns a string version of the problem source
0132      */
0133     QString sourceString() const override;
0134 
0135     TopDUContext* topContext() const override;
0136     KDevelop::IndexedString url() const override;
0137 
0138     /**
0139      * Location where this problem occurred
0140      * @warning Must only be called from the foreground
0141      * */
0142     DocumentRange finalLocation() const override;
0143     void setFinalLocation(const DocumentRange& location) override;
0144 
0145     FinalLocationMode finalLocationMode() const override;
0146     void setFinalLocationMode(FinalLocationMode mode) override;
0147 
0148     /**
0149      * Returns child diagnostics of this particular problem
0150      *
0151      * Example:
0152      * @code
0153      * void foo(unsigned int);
0154      * void foo(const char*);
0155      * int main() { foo(0); }
0156      * @endcode
0157      *
0158      * => foo(0) is ambiguous. This will give us a ProblemPointer pointing to 'foo(0)'.
0159      *
0160      * Additionally, @p diagnostics may return the two locations to the ambiguous overloads,
0161      * with descriptions such as 'test.cpp:1: candidate : ...'
0162      */
0163     void clearDiagnostics() override;
0164 
0165     QVector<IProblem::Ptr> diagnostics() const override;
0166     void setDiagnostics(const QVector<IProblem::Ptr>& diagnostics) override;
0167     void addDiagnostic(const IProblem::Ptr& diagnostic) override;
0168 
0169     /**
0170      * A brief description of the problem.
0171      */
0172     QString description() const override;
0173     void setDescription(const QString& description) override;
0174 
0175     /**
0176      * A (detailed) explanation of why the problem occurred.
0177      */
0178     QString explanation() const override;
0179     void setExplanation(const QString& explanation) override;
0180 
0181     /**
0182      * Get the severity of this problem.
0183      * This is used for example to decide for a highlighting color.
0184      *
0185      * @see setSeverity()
0186      */
0187     Severity severity() const override;
0188 
0189     /**
0190      * Set the severity of this problem.
0191      */
0192     void setSeverity(Severity severity) override;
0193 
0194     /**
0195      * Returns a string representation of the severity.
0196      */
0197     QString severityString() const override;
0198 
0199     /**
0200      * If this problem can be solved, this may return an assistant for the solution.
0201      */
0202     QExplicitlySharedDataPointer<IAssistant> solutionAssistant() const override;
0203 
0204     enum {
0205         Identity = 15
0206     };
0207 
0208     /**
0209      * Returns a string representation of this problem, useful for debugging.
0210      */
0211     virtual QString toString() const;
0212 
0213 private:
0214     void rebuildDynamicData(DUContext* parent, uint ownIndex) override;
0215 
0216     Q_DISABLE_COPY(Problem)
0217 
0218     DUCHAIN_DECLARE_DATA(Problem)
0219     friend class TopDUContext;
0220     friend class TopDUContextDynamicData;
0221     friend class LocalIndexedProblem;
0222 
0223     //BEGIN dynamic data
0224     TopDUContextPointer m_topContext;
0225     mutable QList<Ptr> m_diagnostics;
0226     uint m_indexInTopContext = 0;
0227     //END dynamic data
0228 };
0229 
0230 class KDEVPLATFORMLANGUAGE_EXPORT StaticAssistantProblem
0231     : public KDevelop::Problem
0232 {
0233 public:
0234     KDevelop::IAssistant::Ptr solutionAssistant() const override
0235     {
0236         return m_solution;
0237     }
0238     void setSolutionAssistant(const KDevelop::IAssistant::Ptr& p)
0239     {
0240         m_solution = p;
0241     }
0242 
0243 private:
0244     KDevelop::IAssistant::Ptr m_solution;
0245 };
0246 }
0247 
0248 Q_DECLARE_TYPEINFO(KDevelop::LocalIndexedProblem, Q_MOVABLE_TYPE);
0249 
0250 KDEVPLATFORMLANGUAGE_EXPORT QDebug operator<<(QDebug s, const KDevelop::Problem& problem);
0251 KDEVPLATFORMLANGUAGE_EXPORT QDebug operator<<(QDebug s, const KDevelop::ProblemPointer& problem);
0252 
0253 #endif // KDEVPLATFORM_PROBLEM_H