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);