KDevelop5/Problem Checker Framework

    From KDE TechBase

    KDevelop Problem Checker Framework

    The basic idea behind the framework is to free checker plugin developers from having to implement models, views for each and every tool just to show problems in KDevelop. Instead of this, the developer just has to instantiate a ProblemModel and give it to KDevPlatform, which will show the problems added to it in the problems toolview, in it's own tab. There's also a status class so that the user can get feedback about the problem checker's progress.

    Note
    Status is not neccessary it's just for convenience, to show the progress to the user.

    It makes no sense in case of runtime checkers like Valgrind, since you have no way of knowing how long it will be running, or how many problems it will find.

    Using the framework

    For using the framework the following steps must be taken

    • Instantiate a ProblemModel
    • (optional) Instantiate a CheckerStatus
    • Give the model to KDevPlatform
    • (optional) Give the status to KDevPlatform

    Header

     // QScopedPointer is a Qt smart pointer which deletes the pointer when execution goes out of scope.
     QScopedPointer<KDevelop::ProblemModel> m_model;
     QScopedPointer<KDevelop::CheckerStatus> m_status;
    

    Constructor

     #include <interfaces/icore.h>
     #include <interfaces/ilanguagecontroller.h>
     #include <interfaces/iuicontroller.h>
     #include <shell/problemmodelset.h>
     #include <shell/problemmodel.h>
     #include <shell/checkerstatus.h>
     
     ...
     
     Plugin::Plugin(parameters)
     	:m_model(new ProblemModel(parent))
     	,m_status(new CheckerStatus())
     {
     	m_status->setCheckerName(QStringLiteral("CHECKER")); // CHECKER is the name/label of the tool
     	ProblemModelSet *problemModelSet = ICore::self()->languageController()->problemModelSet();
     	problemModelSet->addModel(QStringLiteral("CHECKER"), m_model.data());
     	ICore::self()->uiController()->registerStatus(m_status.data());
     }
    

    On shutdown

     Plugin::unload()
     {
     	ProblemModelSet *problemModelSet = ICore::self()->languageController()->problemModelSet();
     	problemModelSet->removeModel(QStringLiteral("CHECKER"));
     }
    

    During runtime the checker tool will find problems, and you will want to add those to the model.

    • For every issue found, a Problem instance has to be created and filled with data
    • The problem(s) have to be added to the model


    Creating problem instances

     #include <shell/problem.h>
     
     ...
     
     IProblem::Ptr problem(new DetectedProblem());
     problem->setDescription(shortMessage);
     problem->setExplanation(longMessage);
     problem->setSeverity(IProblem::Error);
     problem->setSource(IProblem::Plugin);
     
     DocumentRange range;
     range.document = IndexedString(filePath);
     range.setBothLines(lineNumber);
     range.setBothColumns(columnNumber);
     problem->setFinalLocation(range);
    

    Adding problems

     // Typically with run-time checkers like Valgrind
     m_model->addProblem(problem);
    

    or

     // Typically static checkers like cppcheck, clang-check, pylint, jshint, etc.
     QVector<IProblem::Ptr> problems;
     m_model->setProblems(problems);