forked from qt-creator/qt-creator
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:
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user