File indexing completed on 2024-04-28 04:37:21

0001 /*
0002     SPDX-FileCopyrightText: 2015 Laszlo Kis-Adam <laszlo.kis-adam@kdemail.net>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "problemstore.h"
0008 
0009 #include <language/editor/documentrange.h>
0010 #include <shell/problem.h>
0011 #include <shell/watcheddocumentset.h>
0012 #include "problemstorenode.h"
0013 
0014 namespace KDevelop
0015 {
0016 
0017 class ProblemStorePrivate
0018 {
0019 public:
0020     ProblemStorePrivate()
0021         : m_severities(KDevelop::IProblem::Error | KDevelop::IProblem::Warning | KDevelop::IProblem::Hint)
0022         , m_rootNode(new KDevelop::ProblemStoreNode())
0023     {
0024     }
0025 
0026     /// Watched document set. Only problems that are in files in this set are stored.
0027     KDevelop::WatchedDocumentSet *m_documents = nullptr;
0028 
0029     /// The severity filter setting
0030     KDevelop::IProblem::Severities m_severities;
0031 
0032     /// The problems list
0033     KDevelop::ProblemStoreNode *m_rootNode;
0034 
0035     /// Path of the currently open document
0036     KDevelop::IndexedString m_currentDocument;
0037 
0038     /// Path for the DocumentsInPath scope
0039     QString m_pathForDocumentsInPathScope;
0040 
0041     /// All stored problems
0042     QVector<KDevelop::IProblem::Ptr> m_allProblems;
0043 };
0044 
0045 
0046 ProblemStore::ProblemStore(QObject *parent)
0047     : QObject(parent),
0048       d_ptr(new ProblemStorePrivate)
0049 {
0050     setScope(BypassScopeFilter);
0051 }
0052 
0053 ProblemStore::~ProblemStore()
0054 {
0055     Q_D(ProblemStore);
0056 
0057     clear();
0058 
0059     delete d->m_rootNode;
0060 }
0061 
0062 void ProblemStore::addProblem(const IProblem::Ptr &problem)
0063 {
0064     Q_D(ProblemStore);
0065 
0066     auto* node = new ProblemNode(d->m_rootNode);
0067     node->setProblem(problem);
0068     d->m_rootNode->addChild(node);
0069 
0070     d->m_allProblems += problem;
0071     emit problemsChanged();
0072 }
0073 
0074 void ProblemStore::setProblems(const QVector<IProblem::Ptr> &problems)
0075 {
0076     Q_D(ProblemStore);
0077 
0078     int oldSize = d->m_allProblems.size();
0079 
0080     // set signals block to prevent problemsChanged() emitting during clean
0081     {
0082         QSignalBlocker blocker(this);
0083         clear();
0084     }
0085 
0086     for (const IProblem::Ptr& problem : problems) {
0087         d->m_rootNode->addChild(new ProblemNode(d->m_rootNode, problem));
0088     }
0089 
0090     rebuild();
0091 
0092     if (d->m_allProblems.size() != oldSize || d->m_allProblems != problems) {
0093         d->m_allProblems = problems;
0094         emit problemsChanged();
0095     }
0096 }
0097 
0098 QVector<IProblem::Ptr> ProblemStore::problems(const KDevelop::IndexedString& document) const
0099 {
0100     Q_D(const ProblemStore);
0101 
0102     QVector<IProblem::Ptr> documentProblems;
0103 
0104     for (auto& problem : qAsConst(d->m_allProblems)) {
0105         if (problem->finalLocation().document == document)
0106             documentProblems += problem;
0107     }
0108 
0109     return documentProblems;
0110 }
0111 
0112 const ProblemStoreNode* ProblemStore::findNode(int row, ProblemStoreNode *parent) const
0113 {
0114     Q_D(const ProblemStore);
0115 
0116     Q_UNUSED(parent);
0117     return d->m_rootNode->child(row);
0118 }
0119 
0120 int ProblemStore::count(ProblemStoreNode *parent) const
0121 {
0122     Q_D(const ProblemStore);
0123 
0124     if(parent)
0125         return parent->count();
0126     else
0127         return d->m_rootNode->count();
0128 }
0129 
0130 void ProblemStore::clear()
0131 {
0132     Q_D(ProblemStore);
0133 
0134     d->m_rootNode->clear();
0135 
0136     if (!d->m_allProblems.isEmpty()) {
0137         d->m_allProblems.clear();
0138         emit problemsChanged();
0139     }
0140 }
0141 
0142 void ProblemStore::rebuild()
0143 {
0144 }
0145 
0146 void ProblemStore::setSeverity(int severity)
0147 {
0148     switch (severity)
0149     {
0150         case KDevelop::IProblem::Error:
0151             setSeverities(KDevelop::IProblem::Error);
0152             break;
0153         case KDevelop::IProblem::Warning:
0154             setSeverities(KDevelop::IProblem::Error | KDevelop::IProblem::Warning);
0155             break;
0156         case KDevelop::IProblem::Hint:
0157             setSeverities(KDevelop::IProblem::Error | KDevelop::IProblem::Warning | KDevelop::IProblem::Hint);
0158             break;
0159     }
0160 }
0161 
0162 void ProblemStore::setSeverities(KDevelop::IProblem::Severities severities)
0163 {
0164     Q_D(ProblemStore);
0165 
0166     if(severities != d->m_severities)
0167     {
0168         d->m_severities = severities;
0169         rebuild();
0170         emit changed();
0171     }
0172 }
0173 
0174 int ProblemStore::severity() const
0175 {
0176     Q_D(const ProblemStore);
0177 
0178     if (d->m_severities.testFlag(KDevelop::IProblem::Hint))
0179         return KDevelop::IProblem::Hint;
0180     if (d->m_severities.testFlag(KDevelop::IProblem::Warning))
0181         return KDevelop::IProblem::Warning;
0182     if (d->m_severities.testFlag(KDevelop::IProblem::Error))
0183         return KDevelop::IProblem::Error;
0184     return 0;
0185 }
0186 
0187 KDevelop::IProblem::Severities ProblemStore::severities() const
0188 {
0189     Q_D(const ProblemStore);
0190 
0191     return d->m_severities;
0192 }
0193 
0194 WatchedDocumentSet* ProblemStore::documents() const
0195 {
0196     Q_D(const ProblemStore);
0197 
0198     return d->m_documents;
0199 }
0200 
0201 void ProblemStore::setScope(ProblemScope scope)
0202 {
0203     Q_D(ProblemStore);
0204 
0205     bool showImports = false;
0206 
0207     if (d->m_documents) {
0208         if (scope == d->m_documents->scope())
0209             return;
0210 
0211         showImports = d->m_documents->showImports();
0212         delete d->m_documents;
0213     }
0214 
0215     switch (scope) {
0216     case CurrentDocument:
0217         d->m_documents = new CurrentDocumentSet(d->m_currentDocument, this);
0218         break;
0219     case OpenDocuments:
0220         d->m_documents = new OpenDocumentSet(this);
0221         break;
0222     case CurrentProject:
0223         d->m_documents = new CurrentProjectSet(d->m_currentDocument, this);
0224         break;
0225     case AllProjects:
0226         d->m_documents = new AllProjectSet(this);
0227         break;
0228     case DocumentsInPath:
0229         d->m_documents = new DocumentsInPathSet(d->m_pathForDocumentsInPathScope, this);
0230         break;
0231     case DocumentsInCurrentPath:
0232         d->m_documents = new DocumentsInCurrentPathSet(d->m_currentDocument, this);
0233         break;
0234     case BypassScopeFilter:
0235         d->m_documents = new BypassSet(this);
0236         break;
0237     }
0238 
0239     d->m_documents->setShowImports(showImports);
0240 
0241     rebuild();
0242 
0243     connect(d->m_documents, &WatchedDocumentSet::changed, this, &ProblemStore::onDocumentSetChanged);
0244 
0245     emit changed();
0246 }
0247 
0248 ProblemScope ProblemStore::scope() const
0249 {
0250     Q_D(const ProblemStore);
0251 
0252     Q_ASSERT(d->m_documents);
0253 
0254     return d->m_documents->scope();
0255 }
0256 
0257 void ProblemStore::setGrouping(int grouping)
0258 {
0259     Q_UNUSED(grouping);
0260 }
0261 
0262 void ProblemStore::setShowImports(bool showImports)
0263 {
0264     Q_D(ProblemStore);
0265 
0266     d->m_documents->setShowImports(showImports);
0267 }
0268 
0269 int ProblemStore::showImports() const
0270 {
0271     Q_D(const ProblemStore);
0272 
0273     return d->m_documents->showImports();
0274 }
0275 
0276 void ProblemStore::setCurrentDocument(const IndexedString &doc)
0277 {
0278     Q_D(ProblemStore);
0279 
0280     d->m_currentDocument = doc;
0281     d->m_documents->setCurrentDocument(doc);
0282 }
0283 
0284 
0285 const KDevelop::IndexedString& ProblemStore::currentDocument() const
0286 {
0287     Q_D(const ProblemStore);
0288 
0289     return d->m_currentDocument;
0290 }
0291 
0292 void ProblemStore::setPathForDocumentsInPathScope(const QString& path)
0293 {
0294     Q_D(ProblemStore);
0295 
0296     d->m_pathForDocumentsInPathScope = path;
0297 
0298     if (d->m_documents->scope() == DocumentsInPath) {
0299         static_cast<DocumentsInPathSet*>(d->m_documents)->setPath(path);
0300     }
0301 }
0302 
0303 QString ProblemStore::pathForDocumentsInPathScope() const
0304 {
0305     Q_D(const ProblemStore);
0306 
0307     return d->m_pathForDocumentsInPathScope;
0308 }
0309 
0310 void ProblemStore::onDocumentSetChanged()
0311 {
0312     rebuild();
0313 
0314     emit changed();
0315 }
0316 
0317 ProblemStoreNode* ProblemStore::rootNode() const
0318 {
0319     Q_D(const ProblemStore);
0320 
0321     return d->m_rootNode;
0322 }
0323 
0324 }
0325 
0326 #include "moc_problemstore.cpp"