diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index 4ff6750751f..5cf2a86341e 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -34,6 +34,7 @@ #include "qmljshighlighter.h" #include "qmljshoverhandler.h" #include "qmljsquickfixassist.h" +#include "qmljstextmark.h" #include "qmloutlinemodel.h" #include @@ -68,6 +69,7 @@ #include #include #include +#include #include #include @@ -201,12 +203,14 @@ static void appendExtraSelectionsForMessages( void QmlJSEditorWidget::updateCodeWarnings(Document::Ptr doc) { + cleanDiagnosticMarks(); if (doc->ast()) { setExtraSelections(CodeWarningsSelection, QList()); } else if (doc->language().isFullySupportedLanguage()) { // show parsing errors QList selections; appendExtraSelectionsForMessages(&selections, doc->diagnosticMessages(), document()); + createTextMarks(doc->diagnosticMessages()); setExtraSelections(CodeWarningsSelection, selections); } else { setExtraSelections(CodeWarningsSelection, QList()); @@ -923,6 +927,8 @@ void QmlJSEditorWidget::semanticInfoUpdated(const SemanticInfo &semanticInfo) } } + createTextMarks(semanticInfo); + updateUses(); } @@ -964,6 +970,61 @@ bool QmlJSEditorWidget::hideContextPane() return b; } +void QmlJSEditorWidget::createTextMarks(const QList &diagnostics) +{ + for (const DiagnosticMessage &diagnostic : diagnostics) { + const auto onMarkRemoved = [this](QmlJSTextMark *mark) { + m_diagnosticMarks.removeAll(mark); + delete mark; + }; + + auto mark = new QmlJSTextMark(textDocument()->filePath().toString(), + diagnostic, onMarkRemoved); + m_diagnosticMarks.append(mark); + textDocument()->addMark(mark); + } +} + +static void cleanMarks(QVector *marks, TextDocument *doc) +{ + for (TextEditor::TextMark *mark : *marks) { + doc->removeMark(mark); + delete mark; + } + marks->clear(); +} + +void QmlJSEditorWidget::cleanDiagnosticMarks() +{ + cleanMarks(&m_diagnosticMarks, textDocument()); +} + +void QmlJSEditorWidget::createTextMarks(const SemanticInfo &info) +{ + cleanSemanticMarks(); + const auto onMarkRemoved = [this](QmlJSTextMark *mark) { + m_semanticMarks.removeAll(mark); + delete mark; + }; + for (const DiagnosticMessage &diagnostic : info.semanticMessages) { + auto mark = new QmlJSTextMark(textDocument()->filePath().toString(), + diagnostic, onMarkRemoved); + m_semanticMarks.append(mark); + textDocument()->addMark(mark); + } + for (const QmlJS::StaticAnalysis::Message &message : info.staticAnalysisMessages) { + auto mark = new QmlJSTextMark(textDocument()->filePath().toString(), + message, onMarkRemoved); + m_semanticMarks.append(mark); + textDocument()->addMark(mark); + } +} + +void QmlJSEditorWidget::cleanSemanticMarks() +{ + cleanMarks(&m_semanticMarks, textDocument()); +} + AssistInterface *QmlJSEditorWidget::createAssistInterface( AssistKind assistKind, AssistReason reason) const diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h index f05ee185760..9a16b13354f 100644 --- a/src/plugins/qmljseditor/qmljseditor.h +++ b/src/plugins/qmljseditor/qmljseditor.h @@ -47,6 +47,8 @@ namespace QmlJS { namespace AST { class UiObjectMember; } } +namespace TextEditor { class TextMark; } + namespace QmlJSEditor { class QmlJSEditorDocument; @@ -127,6 +129,14 @@ private: QmlJS::IContextPane *m_contextPane = nullptr; int m_oldCursorPosition = -1; + void createTextMarks(const QList &diagnostics); + void cleanDiagnosticMarks(); + QVector m_diagnosticMarks; + + void createTextMarks(const QmlJSTools::SemanticInfo &info); + void cleanSemanticMarks(); + QVector m_semanticMarks; + FindReferences *m_findReferences; }; diff --git a/src/plugins/qmljseditor/qmljseditor.pro b/src/plugins/qmljseditor/qmljseditor.pro index b7b373820a9..a4f79166118 100644 --- a/src/plugins/qmljseditor/qmljseditor.pro +++ b/src/plugins/qmljseditor/qmljseditor.pro @@ -30,7 +30,8 @@ HEADERS += \ qmljssemantichighlighter.h \ qmljswrapinloader.h \ qmljseditordocument.h \ - qmljseditordocument_p.h + qmljseditordocument_p.h \ + qmljstextmark.h SOURCES += \ qmljseditor.cpp \ @@ -57,7 +58,8 @@ SOURCES += \ qmljssemanticinfoupdater.cpp \ qmljssemantichighlighter.cpp \ qmljswrapinloader.cpp \ - qmljseditordocument.cpp + qmljseditordocument.cpp \ + qmljstextmark.cpp FORMS += \ qmljseditingsettingspage.ui \ diff --git a/src/plugins/qmljseditor/qmljseditor.qbs b/src/plugins/qmljseditor/qmljseditor.qbs index ef68060ece4..9459876c9f9 100644 --- a/src/plugins/qmljseditor/qmljseditor.qbs +++ b/src/plugins/qmljseditor/qmljseditor.qbs @@ -61,6 +61,8 @@ QtcPlugin { "qmljssemantichighlighter.h", "qmljssemanticinfoupdater.cpp", "qmljssemanticinfoupdater.h", + "qmljstextmark.cpp", + "qmljstextmark.h", "qmljswrapinloader.cpp", "qmljswrapinloader.h", "qmloutlinemodel.cpp", diff --git a/src/plugins/qmljseditor/qmljstextmark.cpp b/src/plugins/qmljseditor/qmljstextmark.cpp new file mode 100644 index 00000000000..1cf93453a94 --- /dev/null +++ b/src/plugins/qmljseditor/qmljstextmark.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "qmljstextmark.h" + +#include +#include + +#include + +using namespace QmlJSEditor; +using namespace QmlJSEditor::Internal; + +using namespace TextEditor; + +const char QMLJS_ERROR[] = "QmlJS.Error"; +const char QMLJS_WARNING[] = "QmlJS.Warning"; + +static bool isWarning(QmlJS::Severity::Enum kind) +{ + switch (kind) { + case QmlJS::Severity::Hint: + case QmlJS::Severity::MaybeWarning: + case QmlJS::Severity::Warning: + case QmlJS::Severity::ReadingTypeInfoWarning: + return true; + case QmlJS::Severity::MaybeError: + case QmlJS::Severity::Error: + break; + } + return false; +} + +static Core::Id cartegoryForSeverity(QmlJS::Severity::Enum kind) +{ + return isWarning(kind) ? QMLJS_WARNING : QMLJS_ERROR; +} + +QmlJSTextMark::QmlJSTextMark(const QString &fileName, + const QmlJS::DiagnosticMessage &diagnostic, + const QmlJSTextMark::RemovedFromEditorHandler &removedHandler) + : TextEditor::TextMark(fileName, int(diagnostic.loc.startLine), + cartegoryForSeverity(diagnostic.kind)) + , m_removedFromEditorHandler(removedHandler) + +{ + init(isWarning(diagnostic.kind), diagnostic.message); +} + +QmlJSTextMark::QmlJSTextMark(const QString &fileName, + const QmlJS::StaticAnalysis::Message &message, + const QmlJSTextMark::RemovedFromEditorHandler &removedHandler) + : TextEditor::TextMark(fileName, int(message.location.startLine), + cartegoryForSeverity(message.severity)) + , m_removedFromEditorHandler(removedHandler) +{ + init(isWarning(message.severity), message.message); +} + +void QmlJSTextMark::removedFromEditor() +{ + QTC_ASSERT(m_removedFromEditorHandler, return); + m_removedFromEditorHandler(this); +} + +void QmlJSTextMark::init(bool warning, const QString message) +{ + setIcon(warning ? Utils::Icons::CODEMODEL_WARNING.icon() + : Utils::Icons::CODEMODEL_ERROR.icon()); + setColor(warning ? Utils::Theme::ClangCodeModel_Warning_TextMarkColor + : Utils::Theme::ClangCodeModel_Error_TextMarkColor); + setDefaultToolTip(warning ? QApplication::translate("QmlJS Code Model Marks", "Code Model Warning") + : QApplication::translate("QmlJS Code Model Marks", "Code Model Error")); + setToolTip(message); + setPriority(warning ? TextEditor::TextMark::NormalPriority + : TextEditor::TextMark::HighPriority); + setLineAnnotation(message); +} diff --git a/src/plugins/qmljseditor/qmljstextmark.h b/src/plugins/qmljseditor/qmljstextmark.h new file mode 100644 index 00000000000..52e5ea60523 --- /dev/null +++ b/src/plugins/qmljseditor/qmljstextmark.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include +#include + +#include + +namespace QmlJSEditor { +namespace Internal { + +class QmlJSTextMark : public TextEditor::TextMark +{ +public: + using RemovedFromEditorHandler = std::function; + + QmlJSTextMark(const QString &fileName, + const QmlJS::DiagnosticMessage &diagnostic, + const RemovedFromEditorHandler &removedHandler); + QmlJSTextMark(const QString &fileName, + const QmlJS::StaticAnalysis::Message &message, + const RemovedFromEditorHandler &removedHandler); + +private: + void removedFromEditor() override; + void init(bool warning, const QString message); + +private: + RemovedFromEditorHandler m_removedFromEditorHandler; +}; + +} // namespace Internal +} // namespace QmlJSEditor