aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qmljseditor/qmljseditingsettingspage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/qmljseditor/qmljseditingsettingspage.cpp')
-rw-r--r--src/plugins/qmljseditor/qmljseditingsettingspage.cpp243
1 files changed, 224 insertions, 19 deletions
diff --git a/src/plugins/qmljseditor/qmljseditingsettingspage.cpp b/src/plugins/qmljseditor/qmljseditingsettingspage.cpp
index 2a0ecb41771..bfb5a002cfa 100644
--- a/src/plugins/qmljseditor/qmljseditingsettingspage.cpp
+++ b/src/plugins/qmljseditor/qmljseditingsettingspage.cpp
@@ -7,18 +7,24 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
+#include <qmljs/qmljscheck.h>
+#include <qmljs/qmljsstaticanalysismessage.h>
+#include <qmljstools/qmljstoolsconstants.h>
+#include <utils/algorithm.h>
#include <utils/layoutbuilder.h>
#include <utils/macroexpander.h>
#include <utils/qtcsettings.h>
+#include <utils/treemodel.h>
#include <utils/variablechooser.h>
-#include <qmljstools/qmljstoolsconstants.h>
#include <QCheckBox>
#include <QComboBox>
#include <QLabel>
#include <QLineEdit>
+#include <QMenu>
#include <QSettings>
#include <QTextStream>
+#include <QTreeView>
const char AUTO_FORMAT_ON_SAVE[] = "QmlJSEditor.AutoFormatOnSave";
const char AUTO_FORMAT_ONLY_CURRENT_PROJECT[] = "QmlJSEditor.AutoFormatOnlyCurrentProject";
@@ -31,11 +37,30 @@ const char UIQML_OPEN_MODE[] = "QmlJSEditor.openUiQmlMode";
const char FORMAT_COMMAND[] = "QmlJSEditor.formatCommand";
const char FORMAT_COMMAND_OPTIONS[] = "QmlJSEditor.formatCommandOptions";
const char CUSTOM_COMMAND[] = "QmlJSEditor.useCustomFormatCommand";
+const char CUSTOM_ANALYZER[] = "QmlJSEditor.useCustomAnalyzer";
+const char DISABLED_MESSAGES[] = "QmlJSEditor.disabledMessages";
+const char DISABLED_MESSAGES_NONQUICKUI[] = "QmlJSEditor.disabledMessagesNonQuickUI";
const char DEFAULT_CUSTOM_FORMAT_COMMAND[] = "%{CurrentDocument:Project:QT_HOST_BINS}/qmlformat";
using namespace QmlJSEditor;
using namespace QmlJSEditor::Internal;
+static QList<int> defaultDisabledMessages()
+{
+ static const QList<int> disabledByDefault = Utils::transform(
+ QmlJS::Check::defaultDisabledMessages(),
+ [](QmlJS::StaticAnalysis::Type t) { return int(t); });
+ return disabledByDefault;
+}
+
+static QList<int> defaultDisabledMessagesNonQuickUi()
+{
+ static const QList<int> disabledForNonQuickUi = Utils::transform(
+ QmlJS::Check::defaultDisabledMessagesForNonQuickUi(),
+ [](QmlJS::StaticAnalysis::Type t){ return int(t); });
+ return disabledForNonQuickUi;
+}
+
void QmlJsEditingSettings::set()
{
if (get() != *this)
@@ -57,6 +82,17 @@ void QmlJsEditingSettings::fromSettings(QSettings *settings)
m_formatCommand = settings->value(FORMAT_COMMAND, {}).toString();
m_formatCommandOptions = settings->value(FORMAT_COMMAND_OPTIONS, {}).toString();
m_useCustomFormatCommand = settings->value(CUSTOM_COMMAND, QVariant(false)).toBool();
+ m_useCustomAnalyzer = settings->value(CUSTOM_ANALYZER, QVariant(false)).toBool();
+
+ m_disabledMessages = Utils::transform<QSet>(
+ settings->value(DISABLED_MESSAGES,
+ QVariant::fromValue(defaultDisabledMessages())).toList(),
+ [](const QVariant &v){ return v.toInt(); });
+ m_disabledMessagesForNonQuickUi = Utils::transform<QSet>(
+ settings->value(DISABLED_MESSAGES_NONQUICKUI,
+ QVariant::fromValue(defaultDisabledMessagesNonQuickUi())).toList(),
+ [](const QVariant &v) { return v.toInt(); });
+
settings->endGroup();
}
@@ -80,6 +116,18 @@ void QmlJsEditingSettings::toSettings(QSettings *settings) const
CUSTOM_COMMAND,
m_useCustomFormatCommand,
false);
+ Utils::QtcSettings::setValueWithDefault(settings,
+ CUSTOM_ANALYZER,
+ m_useCustomAnalyzer,
+ false);
+ Utils::QtcSettings::setValueWithDefault(settings,
+ DISABLED_MESSAGES,
+ Utils::sorted(Utils::toList(m_disabledMessages)),
+ defaultDisabledMessages());
+ Utils::QtcSettings::setValueWithDefault(settings,
+ DISABLED_MESSAGES_NONQUICKUI,
+ Utils::sorted(Utils::toList(m_disabledMessagesForNonQuickUi)),
+ defaultDisabledMessagesNonQuickUi());
settings->endGroup();
QmllsSettingsManager::instance()->checkForChanges();
}
@@ -93,7 +141,10 @@ bool QmlJsEditingSettings::equals(const QmlJsEditingSettings &other) const
&& m_foldAuxData == other.m_foldAuxData && m_qmllsSettings == other.m_qmllsSettings
&& m_uiQmlOpenMode == other.m_uiQmlOpenMode && m_formatCommand == other.m_formatCommand
&& m_formatCommandOptions == other.m_formatCommandOptions
- && m_useCustomFormatCommand == other.m_useCustomFormatCommand;
+ && m_useCustomFormatCommand == other.m_useCustomFormatCommand
+ && m_useCustomAnalyzer == other.m_useCustomAnalyzer
+ && m_disabledMessages == other.m_disabledMessages
+ && m_disabledMessagesForNonQuickUi == other.m_disabledMessagesForNonQuickUi;
}
bool QmlJsEditingSettings::enableContextPane() const
@@ -181,12 +232,12 @@ void QmlJsEditingSettings::setUseCustomFormatCommand(bool customCommand)
m_useCustomFormatCommand = customCommand;
}
-QmllsSettings &QmlJsEditingSettings::qmllsSettigs()
+QmllsSettings &QmlJsEditingSettings::qmllsSettings()
{
return m_qmllsSettings;
}
-const QmllsSettings &QmlJsEditingSettings::qmllsSettigs() const
+const QmllsSettings &QmlJsEditingSettings::qmllsSettings() const
{
return m_qmllsSettings;
}
@@ -201,6 +252,92 @@ void QmlJsEditingSettings::setUiQmlOpenMode(const QString &mode)
m_uiQmlOpenMode = mode;
}
+bool QmlJsEditingSettings::useCustomAnalyzer() const
+{
+ return m_useCustomAnalyzer;
+}
+
+void QmlJsEditingSettings::setUseCustomAnalyzer(bool customAnalyzer)
+{
+ m_useCustomAnalyzer = customAnalyzer;
+}
+
+QSet<int> QmlJsEditingSettings::disabledMessages() const
+{
+ return m_disabledMessages;
+}
+
+void QmlJsEditingSettings::setDisabledMessages(const QSet<int> &disabled)
+{
+ m_disabledMessages = disabled;
+}
+
+QSet<int> QmlJsEditingSettings::disabledMessagesForNonQuickUi() const
+{
+ return m_disabledMessagesForNonQuickUi;
+}
+
+void QmlJsEditingSettings::setDisabledMessagesForNonQuickUi(const QSet<int> &disabled)
+{
+ m_disabledMessagesForNonQuickUi = disabled;
+}
+
+class AnalyzerMessageItem final : public Utils::TreeItem
+{
+public:
+ AnalyzerMessageItem() = default;
+ AnalyzerMessageItem(int number, const QString &message)
+ : m_messageNumber(number)
+ , m_message(message)
+ {}
+
+ QVariant data(int column, int role) const final
+ {
+ if (role == Qt::DisplayRole) {
+ if (column == 0)
+ return QString("M%1").arg(m_messageNumber);
+ if (column == 2)
+ return m_message.split('\n').first();
+ } else if (role == Qt::CheckStateRole) {
+ if (column == 0)
+ return m_checked ? Qt::Checked : Qt::Unchecked;
+ if (column == 1)
+ return m_disabledInNonQuickUi ? Qt::Checked : Qt::Unchecked;
+ }
+ return TreeItem::data(column, role);
+ }
+
+ bool setData(int column, const QVariant &value, int role) final
+ {
+ if (role == Qt::CheckStateRole) {
+ if (column == 0) {
+ m_checked = value.toBool();
+ return true;
+ }
+ if (column == 1) {
+ m_disabledInNonQuickUi = value.toBool();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ Qt::ItemFlags flags(int column) const final
+ {
+ if (column == 0 || column == 1)
+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
+ else
+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ }
+
+ int messageNumber() const { return m_messageNumber; }
+private:
+ int m_messageNumber = -1;
+ QString m_message;
+ bool m_checked = true;
+ bool m_disabledInNonQuickUi = false;
+};
+
class QmlJsEditingSettingsPageWidget final : public Core::IOptionsPageWidget
{
public:
@@ -239,17 +376,38 @@ public:
uiQmlOpenComboBox->setSizeAdjustPolicy(QComboBox::QComboBox::AdjustToContents);
useQmlls = new QCheckBox(Tr::tr("Use qmlls (EXPERIMENTAL!)"));
- useQmlls->setChecked(s.qmllsSettigs().useQmlls);
+ useQmlls->setChecked(s.qmllsSettings().useQmlls);
useLatestQmlls = new QCheckBox(Tr::tr("Always use latest qmlls"));
- useLatestQmlls->setChecked(s.qmllsSettigs().useLatestQmlls);
- useLatestQmlls->setEnabled(s.qmllsSettigs().useQmlls);
+ useLatestQmlls->setChecked(s.qmllsSettings().useLatestQmlls);
+ useLatestQmlls->setEnabled(s.qmllsSettings().useQmlls);
QObject::connect(useQmlls, &QCheckBox::stateChanged, this, [this](int checked) {
useLatestQmlls->setEnabled(checked != Qt::Unchecked);
});
- using namespace Utils::Layouting;
+
+ useCustomAnalyzer = new QCheckBox(Tr::tr("Use customized static analyzer"));
+ useCustomAnalyzer->setChecked(s.useCustomAnalyzer());
+ analyzerMessageModel = new Utils::TreeModel<AnalyzerMessageItem>(this);
+ analyzerMessageModel->setHeader({Tr::tr("Enabled"),
+ Tr::tr("Disabled for non Qt Quick UI"),
+ Tr::tr("Message")});
+ analyzerMessagesView = new QTreeView;
+ analyzerMessagesView->setModel(analyzerMessageModel);
+ analyzerMessagesView->setEnabled(s.useCustomAnalyzer());
+ QObject::connect(useCustomAnalyzer, &QCheckBox::stateChanged, this, [this](int checked){
+ analyzerMessagesView->setEnabled(checked != Qt::Unchecked);
+ });
+ analyzerMessagesView->setToolTip(Tr::tr("Enabled checks can be disabled for non Qt Quick UI"
+ " files,\nbut disabled checks cannot get explicitly"
+ " enabled for non Qt Quick UI files."));
+ analyzerMessagesView->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(analyzerMessagesView, &QTreeView::customContextMenuRequested,
+ this, &QmlJsEditingSettingsPageWidget::showContextMenu);
+ using namespace Layouting;
// clang-format off
- const auto formattingGroup =
+ QWidget *formattingGroup = nullptr;
+ Column {
Group {
+ bindTo(&formattingGroup),
title(Tr::tr("Automatic Formatting on File Save")),
Column {
autoFormatOnSave,
@@ -260,10 +418,7 @@ public:
formatCommandOptionsLabel, formatCommandOptions
}
},
- };
-
- Column {
- formattingGroup,
+ },
Group {
title(Tr::tr("Qt Quick Toolbars")),
Column { pinContextPane, enableContextPane },
@@ -279,16 +434,19 @@ public:
title(Tr::tr("Language Server")),
Column{useQmlls, useLatestQmlls},
},
+ Group {
+ title(Tr::tr("Static Analyzer")),
+ Column{ useCustomAnalyzer, analyzerMessagesView },
+ },
st,
}.attachTo(this);
// clang-format on
- Utils::VariableChooser::addSupportForChildWidgets(formattingGroup.widget,
+ Utils::VariableChooser::addSupportForChildWidgets(formattingGroup,
Utils::globalMacroExpander());
const auto updateFormatCommandState = [&, formatCommandLabel, formatCommandOptionsLabel] {
- const bool enabled = useCustomFormatCommand->isChecked()
- && autoFormatOnSave->isChecked();
+ const bool enabled = useCustomFormatCommand->isChecked();
formatCommandLabel->setEnabled(enabled);
formatCommand->setEnabled(enabled);
formatCommandOptionsLabel->setEnabled(enabled);
@@ -298,10 +456,11 @@ public:
connect(autoFormatOnSave, &QCheckBox::toggled, this, [&, updateFormatCommandState]() {
autoFormatOnlyCurrentProject->setEnabled(autoFormatOnSave->isChecked());
- useCustomFormatCommand->setEnabled(autoFormatOnSave->isChecked());
updateFormatCommandState();
});
connect(useCustomFormatCommand, &QCheckBox::toggled, this, updateFormatCommandState);
+
+ populateAnalyzerMessages(s.disabledMessages(), s.disabledMessagesForNonQuickUi());
}
void apply() final
@@ -316,12 +475,55 @@ public:
s.setFormatCommandOptions(formatCommandOptions->text());
s.setFoldAuxData(foldAuxData->isChecked());
s.setUiQmlOpenMode(uiQmlOpenComboBox->currentData().toString());
- s.qmllsSettigs().useQmlls = useQmlls->isChecked();
- s.qmllsSettigs().useLatestQmlls = useLatestQmlls->isChecked();
+ s.qmllsSettings().useQmlls = useQmlls->isChecked();
+ s.qmllsSettings().useLatestQmlls = useLatestQmlls->isChecked();
+ s.setUseCustomAnalyzer(useCustomAnalyzer->isChecked());
+ QSet<int> disabled;
+ QSet<int> disabledForNonQuickUi;
+ analyzerMessageModel->forAllItems(
+ [&disabled, &disabledForNonQuickUi](AnalyzerMessageItem *item){
+ if (item->data(0, Qt::CheckStateRole) == Qt::Unchecked)
+ disabled.insert(item->messageNumber());
+ if (item->data(1, Qt::CheckStateRole) == Qt::Checked)
+ disabledForNonQuickUi.insert(item->messageNumber());
+ });
+ s.setDisabledMessages(disabled);
+ s.setDisabledMessagesForNonQuickUi(disabledForNonQuickUi);
s.set();
}
private:
+ void populateAnalyzerMessages(const QSet<int> &disabled, const QSet<int> &disabledForNonQuickUi)
+ {
+ using namespace QmlJS::StaticAnalysis;
+ auto knownMessages = Utils::sorted(Message::allMessageTypes());
+ auto root = analyzerMessageModel->rootItem();
+ for (auto msgType : knownMessages) {
+ const QString msg = Message::prototypeForMessageType(msgType).message;
+ auto item = new AnalyzerMessageItem(msgType, msg);
+ item->setData(0, !disabled.contains(msgType), Qt::CheckStateRole);
+ item->setData(1, disabledForNonQuickUi.contains(msgType), Qt::CheckStateRole);
+ root->appendChild(item);
+ }
+
+ for (int column = 0; column < 3; ++column)
+ analyzerMessagesView->resizeColumnToContents(column);
+ }
+
+ void showContextMenu(const QPoint &position)
+ {
+ QMenu menu;
+ QAction *reset = new QAction(Tr::tr("Reset to Default"), &menu);
+ menu.addAction(reset);
+ connect(reset, &QAction::triggered, this, [this](){
+ analyzerMessageModel->clear();
+ populateAnalyzerMessages(Utils::toSet(defaultDisabledMessages()),
+ Utils::toSet(defaultDisabledMessagesNonQuickUi()));
+
+ });
+ menu.exec(analyzerMessagesView->mapToGlobal(position));
+ }
+
QCheckBox *autoFormatOnSave;
QCheckBox *autoFormatOnlyCurrentProject;
QCheckBox *useCustomFormatCommand;
@@ -333,6 +535,9 @@ private:
QCheckBox *useQmlls;
QCheckBox *useLatestQmlls;
QComboBox *uiQmlOpenComboBox;
+ QCheckBox *useCustomAnalyzer;
+ QTreeView *analyzerMessagesView;
+ Utils::TreeModel<AnalyzerMessageItem> *analyzerMessageModel;
};