QmlJS checks: Suppression of static analysis messages.

* Use '// @disable M123' to suppress
* Add quick fix to add these comments

Change-Id: I499f5a6004148afbb346218c6fb01c9ca77b9f73
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
This commit is contained in:
Christian Kamm
2011-10-19 14:27:40 +02:00
parent cf156cd2ea
commit 0ed824762c
9 changed files with 139 additions and 4 deletions

View File

@@ -851,6 +851,45 @@ static void appendExtraSelectionsForMessages(
}
}
static void appendExtraSelectionsForMessages(
QList<QTextEdit::ExtraSelection> *selections,
const QList<StaticAnalysis::Message> &messages,
const QTextDocument *document)
{
foreach (const StaticAnalysis::Message &d, messages) {
const int line = d.location.startLine;
const int column = qMax(1U, d.location.startColumn);
QTextEdit::ExtraSelection sel;
QTextCursor c(document->findBlockByNumber(line - 1));
sel.cursor = c;
sel.cursor.setPosition(c.position() + column - 1);
if (d.location.length == 0) {
if (sel.cursor.atBlockEnd())
sel.cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
else
sel.cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
} else {
sel.cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, d.location.length);
}
if (d.severity == StaticAnalysis::Warning || d.severity == StaticAnalysis::MaybeWarning) {
sel.format.setUnderlineColor(Qt::darkYellow);
} else if (d.severity == StaticAnalysis::Error || d.severity == StaticAnalysis::MaybeError) {
sel.format.setUnderlineColor(Qt::red);
} else if (d.severity == StaticAnalysis::Hint) {
sel.format.setUnderlineColor(Qt::darkGreen);
}
sel.format.setUnderlineStyle(QTextCharFormat::WaveUnderline);
sel.format.setToolTip(d.message);
selections->append(sel);
}
}
void QmlJSTextEditorWidget::onDocumentUpdated(QmlJS::Document::Ptr doc)
{
if (file()->fileName() != doc->fileName()
@@ -1543,6 +1582,7 @@ void QmlJSTextEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo)
QList<QTextEdit::ExtraSelection> selections;
appendExtraSelectionsForMessages(&selections, doc->diagnosticMessages(), document());
appendExtraSelectionsForMessages(&selections, m_semanticInfo.semanticMessages, document());
appendExtraSelectionsForMessages(&selections, m_semanticInfo.staticAnalysisMessages, document());
setExtraSelections(CodeWarningsSelection, selections);
Core::EditorManager *editorManager = Core::EditorManager::instance();

View File

@@ -38,6 +38,7 @@
#include <qmljs/qmljsdocument.h>
#include <qmljs/qmljsscanner.h>
#include <qmljs/qmljsscopechain.h>
#include <qmljs/qmljsstaticanalysismessage.h>
#include <texteditor/basetexteditor.h>
#include <texteditor/quickfix.h>
@@ -136,6 +137,7 @@ public: // attributes
// these are in addition to the parser messages in the document
QList<QmlJS::DiagnosticMessage> semanticMessages;
QList<QmlJS::StaticAnalysis::Message> staticAnalysisMessages;
private:
QSharedPointer<const QmlJS::ScopeChain> m_rootScopeChain;

View File

@@ -133,6 +133,53 @@ private:
};
};
/*
Adds a comment to suppress a static analysis message
*/
class AddAnalysisMessageSuppressionComment: public QmlJSQuickFixFactory
{
public:
virtual QList<QmlJSQuickFixOperation::Ptr> match(
const QSharedPointer<const QmlJSQuickFixAssistInterface> &interface)
{
const QList<StaticAnalysis::Message> &messages = interface->semanticInfo().staticAnalysisMessages;
foreach (const StaticAnalysis::Message &message, messages) {
if (interface->currentFile()->isCursorOn(message.location)) {
return singleResult(new Operation(interface, message));
}
}
return noResult();
}
private:
class Operation: public QmlJSQuickFixOperation
{
StaticAnalysis::Message _message;
public:
Operation(const QSharedPointer<const QmlJSQuickFixAssistInterface> &interface,
const StaticAnalysis::Message &message)
: QmlJSQuickFixOperation(interface, 0)
, _message(message)
{
setDescription(AddAnalysisMessageSuppressionComment::tr("Add a comment to suppress this message"));
}
virtual void performChanges(QmlJSRefactoringFilePtr currentFile,
const QmlJSRefactoringChanges &)
{
Utils::ChangeSet changes;
const int insertLoc = _message.location.begin() - _message.location.startColumn + 1;
changes.insert(insertLoc, QString("// %1\n").arg(_message.suppressionString()));
currentFile->setChangeSet(changes);
currentFile->appendIndentRange(Range(insertLoc, insertLoc + 1));
currentFile->apply();
}
};
};
} // end of anonymous namespace
void registerQuickFixes(ExtensionSystem::IPlugin *plugIn)
@@ -140,4 +187,5 @@ void registerQuickFixes(ExtensionSystem::IPlugin *plugIn)
plugIn->addAutoReleasedObject(new SplitInitializerOp);
plugIn->addAutoReleasedObject(new ComponentFromObjectDef);
plugIn->addAutoReleasedObject(new WrapInLoader);
plugIn->addAutoReleasedObject(new AddAnalysisMessageSuppressionComment);
}

View File

@@ -148,9 +148,7 @@ SemanticInfo SemanticInfoUpdater::semanticInfo(const SemanticInfoUpdaterSource &
if (doc->language() != QmlJS::Document::JsonLanguage) {
QmlJS::Check checker(doc, semanticInfo.context);
foreach (const QmlJS::StaticAnalysis::Message &msg, checker()) {
semanticInfo.semanticMessages += msg.toDiagnosticMessage();
}
semanticInfo.staticAnalysisMessages = checker();
}
return semanticInfo;