diff --git a/shell/problem.cpp b/shell/problem.cpp index 3aafaed61d..1db8ca3534 100644 --- a/shell/problem.cpp +++ b/shell/problem.cpp @@ -1,188 +1,192 @@ /* * Copyright 2015 Laszlo Kis-Adam * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include struct DetectedProblemPrivate { - DetectedProblemPrivate() - : m_severity(KDevelop::IProblem::Error) + DetectedProblemPrivate(const QString& pluginName) + : m_pluginName(pluginName) + , m_severity(KDevelop::IProblem::Error) , m_source(KDevelop::IProblem::Unknown) , m_finalLocationMode(KDevelop::IProblem::Range) { } QString m_description; QString m_explanation; + QString m_pluginName; KDevelop::IProblem::Severity m_severity; KDevelop::IProblem::Source m_source; KDevelop::DocumentRange m_range; QVector m_diagnostics; KDevelop::IProblem::FinalLocationMode m_finalLocationMode; }; namespace KDevelop { DetectedProblem::DetectedProblem() - :d(new DetectedProblemPrivate()) + : d(new DetectedProblemPrivate(i18n("Plugin"))) { } +DetectedProblem::DetectedProblem(const QString& pluginName) + : d(new DetectedProblemPrivate(pluginName)) +{ + setSource(Plugin); +} + DetectedProblem::~DetectedProblem() { clearDiagnostics(); } IProblem::Source DetectedProblem::source() const { return d->m_source; } void DetectedProblem::setSource(Source source) { d->m_source = source; } QString DetectedProblem::sourceString() const { - QString s; - switch(d->m_source) { - case Unknown: s = i18n("Unknown"); break; - case Disk: s = i18n("Disk"); break; - case Preprocessor: s = i18n("Preprocessor"); break; - case Lexer: s = i18n("Lexer"); break; - case Parser: s = i18n("Parser"); break; - case DUChainBuilder: s = i18n("DuchainBuilder"); break; - case SemanticAnalysis: s = i18n("Semantic analysis"); break; - case ToDo: s = i18n("Todo"); break; - case Plugin: s = i18n("Plugin"); break; + case Unknown: return i18n("Unknown"); + case Disk: return i18n("Disk"); + case Preprocessor: return i18n("Preprocessor"); + case Lexer: return i18n("Lexer"); + case Parser: return i18n("Parser"); + case DUChainBuilder: return i18n("DuchainBuilder"); + case SemanticAnalysis: return i18n("Semantic analysis"); + case ToDo: return i18n("Todo"); + case Plugin: return d->m_pluginName; } - return s; + return {}; } DocumentRange DetectedProblem::finalLocation() const { return d->m_range; } void DetectedProblem::setFinalLocation(const DocumentRange &location) { d->m_range = location; } - IProblem::FinalLocationMode DetectedProblem::finalLocationMode() const { return d->m_finalLocationMode; } void DetectedProblem::setFinalLocationMode(IProblem::FinalLocationMode mode) { d->m_finalLocationMode = mode; } QString DetectedProblem::description() const { return d->m_description; } void DetectedProblem::setDescription(const QString &description) { d->m_description = description; } QString DetectedProblem::explanation() const { return d->m_explanation; } void DetectedProblem::setExplanation(const QString &explanation) { d->m_explanation = explanation; } IProblem::Severity DetectedProblem::severity() const { return d->m_severity; } void DetectedProblem::setSeverity(Severity severity) { d->m_severity = severity; } QString DetectedProblem::severityString() const { QString s; switch(d->m_severity) { case Hint: s = i18n("Hint"); break; case Warning: s = i18n("Warning"); break; case Error: s = i18n("Error"); break; default: break; } return s; } - QVector DetectedProblem::diagnostics() const { return d->m_diagnostics; } void DetectedProblem::setDiagnostics(const QVector &diagnostics) { clearDiagnostics(); foreach (const Ptr &diagnostic, diagnostics) { addDiagnostic(diagnostic); } } void DetectedProblem::addDiagnostic(const Ptr &diagnostic) { DetectedProblem *dp = dynamic_cast(diagnostic.data()); Q_ASSERT(dp); d->m_diagnostics.push_back(diagnostic); } void DetectedProblem::clearDiagnostics() { d->m_diagnostics.clear(); } QExplicitlySharedDataPointer DetectedProblem::solutionAssistant() const { return {}; } } diff --git a/shell/problem.h b/shell/problem.h index 61c4c0a68e..f9a438cff6 100644 --- a/shell/problem.h +++ b/shell/problem.h @@ -1,98 +1,112 @@ /* * Copyright 2015 Laszlo Kis-Adam * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PROBLEM_H #define PROBLEM_H #include #include #include #include #include struct DetectedProblemPrivate; namespace KDevelop { /** * @brief Represents a problem as one unit with the IProblem interface so can be used with anything that can handle IProblem. * * You should have it wrapped in an IProblem::Ptr which is a shared pointer for it. * It is basically a mirror of DUChain's Problem class. * However that class is strongly coupled with DUChain's internals due to DUChain's needs (special serialization). * * Usage example: * @code * IProblem::Ptr problem(new DetectedProblem()); * problem->setSource(IProblem::Plugin); - * problem->setSeverity(IProblem::Error); - * problem->setDescription(QStringLiteral("Error message")); - * problem->setExplanation(QStringLiteral("Error explanation")); + * problem->setSeverity(IProblem::Warning); + * problem->setDescription(QStringLiteral("Warning message")); + * problem->setExplanation(QStringLiteral("Warning explanation")); * * DocumentRange range; * range.document = IndexedString("/path/to/source/file"); * range.setBothLines(1337); * range.setBothColumns(12); * problem->setFinalLocation(range); * @endcode * */ class KDEVPLATFORMSHELL_EXPORT DetectedProblem : public IProblem { public: + /// Creates new empty DetectedProblem with default properties: + /// severity - KDevelop::IProblem::Error; + /// source - KDevelop::IProblem::Unknown; + /// finalLocationMode - KDevelop::IProblem::Range. DetectedProblem(); - virtual ~DetectedProblem(); + + /// Creates new DetectedProblem, produced by some plugin, for example by analyzer plugins + /// like cppcheck/clang-tydy/valgrind/etc. + /// Default values of problem properties are: + /// severity - KDevelop::IProblem::Error; + /// source - KDevelop::IProblem::Plugin; + /// sourceString - passed pluginName parameter; + /// finalLocationMode - KDevelop::IProblem::Range. + DetectedProblem(const QString& pluginName); + + ~DetectedProblem() override; Source source() const override; void setSource(Source source) override; QString sourceString() const override; DocumentRange finalLocation() const override; void setFinalLocation(const DocumentRange& location) override; FinalLocationMode finalLocationMode() const override; void setFinalLocationMode(FinalLocationMode mode) override; QString description() const override; void setDescription(const QString& description) override; QString explanation() const override; void setExplanation(const QString& explanation) override; Severity severity() const override; void setSeverity(Severity severity) override; QString severityString() const override; QVector diagnostics() const override; void setDiagnostics(const QVector &diagnostics) override; void addDiagnostic(const Ptr &diagnostic) override; void clearDiagnostics() override; QExplicitlySharedDataPointer solutionAssistant() const override; private: QScopedPointer d; }; } #endif diff --git a/shell/tests/test_detectedproblem.cpp b/shell/tests/test_detectedproblem.cpp index fd9cceab76..ae45400b32 100644 --- a/shell/tests/test_detectedproblem.cpp +++ b/shell/tests/test_detectedproblem.cpp @@ -1,199 +1,221 @@ /* * Copyright 2015 Laszlo Kis-Adam * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include using namespace KDevelop; class TestDetectedProblem : public QObject { Q_OBJECT private slots: void initTestCase(); void cleanupTestCase(); void testSource(); void testSeverity(); void testDescription(); void testExplanation(); void testFinalLocation(); void testDiagnostics(); + void testPluginName(); private: IProblem::Ptr m_problem; }; void TestDetectedProblem::initTestCase() { AutoTestShell::init(); TestCore::initialize(Core::NoUi); m_problem = new DetectedProblem(); } void TestDetectedProblem::cleanupTestCase() { TestCore::shutdown(); } struct Source { IProblem::Source source; QString sourceString; }; void TestDetectedProblem::testSource() { static Source sources[] = { { IProblem::Unknown, i18n("Unknown") }, { IProblem::Disk, i18n("Disk") }, { IProblem::Preprocessor, i18n("Preprocessor") }, { IProblem::Lexer, i18n("Lexer") }, { IProblem::Parser, i18n("Parser") }, { IProblem::DUChainBuilder, i18n("DuchainBuilder") }, { IProblem::SemanticAnalysis, i18n("Semantic analysis") }, { IProblem::ToDo, i18n("Todo") }, { IProblem::Plugin, i18n("Plugin") } }; int c = sizeof(sources) / sizeof(Source); for (int i = 0; i < c; i++) { m_problem->setSource(sources[i].source); QCOMPARE(sources[i].source, m_problem->source()); QCOMPARE(sources[i].sourceString, m_problem->sourceString()); } } struct Severity { IProblem::Severity severity; QString severityString; }; void TestDetectedProblem::testSeverity() { static Severity severities[] = { { IProblem::Error, i18n("Error") }, { IProblem::Warning, i18n("Warning") }, { IProblem::Hint, i18n("Hint") }, }; int c = sizeof(severities) / sizeof(Severity); for (int i = 0; i < c; i++) { m_problem->setSeverity(severities[i].severity); QCOMPARE(severities[i].severity, m_problem->severity()); QCOMPARE(severities[i].severityString, m_problem->severityString()); } } void TestDetectedProblem::testDescription() { QString TESTDESCRIPTION = QStringLiteral("Just a test description"); m_problem->setDescription(TESTDESCRIPTION); QCOMPARE(TESTDESCRIPTION, m_problem->description()); } void TestDetectedProblem::testExplanation() { QString TESTEXPLANATION = QStringLiteral("Just a test explanation"); m_problem->setExplanation(TESTEXPLANATION); QCOMPARE(TESTEXPLANATION, m_problem->explanation()); } void TestDetectedProblem::testFinalLocation() { QString TESTPATH = QStringLiteral("/just/a/bogus/path/to/a/fake/document"); int TESTLINE = 9001; int TESTCOLUMN = 1337; DocumentRange range; range.document = IndexedString(TESTPATH); range.setBothLines(TESTLINE); range.setBothColumns(TESTCOLUMN); m_problem->setFinalLocation(range); QCOMPARE(TESTPATH, m_problem->finalLocation().document.str()); QCOMPARE(TESTLINE, m_problem->finalLocation().start().line()); QCOMPARE(TESTLINE, m_problem->finalLocation().end().line()); QCOMPARE(TESTCOLUMN, m_problem->finalLocation().start().column()); QCOMPARE(TESTCOLUMN, m_problem->finalLocation().end().column()); } void TestDetectedProblem::testDiagnostics() { QString one = QStringLiteral("One"); QString two = QStringLiteral("Two"); QString three = QStringLiteral("Three"); IProblem::Ptr p1(new DetectedProblem()); IProblem::Ptr p2(new DetectedProblem()); IProblem::Ptr p3(new DetectedProblem()); p1->setDescription(one); p2->setDescription(two); p3->setDescription(three); QCOMPARE(m_problem->diagnostics().size(), 0); m_problem->addDiagnostic(p1); m_problem->addDiagnostic(p2); m_problem->addDiagnostic(p3); QCOMPARE(m_problem->diagnostics().size(), 3); QCOMPARE(m_problem->diagnostics().at(0)->description(), one); QCOMPARE(m_problem->diagnostics().at(1)->description(), two); QCOMPARE(m_problem->diagnostics().at(2)->description(), three); m_problem->clearDiagnostics(); QCOMPARE(0, m_problem->diagnostics().size()); QVector diags; diags.push_back(p3); diags.push_back(p2); diags.push_back(p1); m_problem->setDiagnostics(diags); QCOMPARE(m_problem->diagnostics().size(), 3); QCOMPARE(m_problem->diagnostics().at(2)->description(), one); QCOMPARE(m_problem->diagnostics().at(1)->description(), two); QCOMPARE(m_problem->diagnostics().at(0)->description(), three); m_problem->clearDiagnostics(); QCOMPARE(m_problem->diagnostics().size(), 0); } +void TestDetectedProblem::testPluginName() +{ + DetectedProblem p1(QStringLiteral("Plugin1")); + DetectedProblem p2(QStringLiteral("Plugin2")); + DetectedProblem p3(QStringLiteral("")); + DetectedProblem p4; + + QCOMPARE(p1.source(), IProblem::Plugin); + QCOMPARE(p2.source(), IProblem::Plugin); + QCOMPARE(p3.source(), IProblem::Plugin); + QCOMPARE(p4.source(), IProblem::Unknown); + + QCOMPARE(p1.sourceString(), QStringLiteral("Plugin1")); + QCOMPARE(p2.sourceString(), QStringLiteral("Plugin2")); + QCOMPARE(p3.sourceString(), QStringLiteral("")); + QCOMPARE(p4.sourceString(), i18n("Unknown")); + + p4.setSource(IProblem::Plugin); + QCOMPARE(p4.source(), IProblem::Plugin); + QCOMPARE(p4.sourceString(), i18n("Plugin")); +} QTEST_MAIN(TestDetectedProblem) #include "test_detectedproblem.moc"