forked from qt-creator/qt-creator
Optionally use qmlformat for Qt Quick auto format on save
Task-number: QTCREATORBUG-28192 Task-number: QTCREATORBUG-26602 Change-Id: I22a3917e8a4de4aaf297e9d9d622bdede782c6a6 Reviewed-by: Xavier BESSON <developer@xavi-b.fr> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -7,11 +7,16 @@
|
|||||||
|
|
||||||
#include <coreplugin/coreconstants.h>
|
#include <coreplugin/coreconstants.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <qmljstools/qmljstoolsconstants.h>
|
|
||||||
#include <utils/layoutbuilder.h>
|
#include <utils/layoutbuilder.h>
|
||||||
|
#include <utils/macroexpander.h>
|
||||||
|
#include <utils/qtcsettings.h>
|
||||||
|
#include <utils/variablechooser.h>
|
||||||
|
#include <qmljstools/qmljstoolsconstants.h>
|
||||||
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
|
|
||||||
@@ -23,6 +28,10 @@ const char FOLD_AUX_DATA[] = "QmlJSEditor.FoldAuxData";
|
|||||||
const char USE_QMLLS[] = "QmlJSEditor.UseQmlls";
|
const char USE_QMLLS[] = "QmlJSEditor.UseQmlls";
|
||||||
const char USE_LATEST_QMLLS[] = "QmlJSEditor.UseLatestQmlls";
|
const char USE_LATEST_QMLLS[] = "QmlJSEditor.UseLatestQmlls";
|
||||||
const char UIQML_OPEN_MODE[] = "QmlJSEditor.openUiQmlMode";
|
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 DEFAULT_CUSTOM_FORMAT_COMMAND[] = "%{CurrentDocument:Project:QT_HOST_BINS}/qmlformat";
|
||||||
|
|
||||||
using namespace QmlJSEditor;
|
using namespace QmlJSEditor;
|
||||||
using namespace QmlJSEditor::Internal;
|
using namespace QmlJSEditor::Internal;
|
||||||
@@ -45,6 +54,9 @@ void QmlJsEditingSettings::fromSettings(QSettings *settings)
|
|||||||
m_uiQmlOpenMode = settings->value(UIQML_OPEN_MODE, "").toString();
|
m_uiQmlOpenMode = settings->value(UIQML_OPEN_MODE, "").toString();
|
||||||
m_qmllsSettings.useQmlls = settings->value(USE_QMLLS, QVariant(false)).toBool();
|
m_qmllsSettings.useQmlls = settings->value(USE_QMLLS, QVariant(false)).toBool();
|
||||||
m_qmllsSettings.useLatestQmlls = settings->value(USE_LATEST_QMLLS, QVariant(false)).toBool();
|
m_qmllsSettings.useLatestQmlls = settings->value(USE_LATEST_QMLLS, QVariant(false)).toBool();
|
||||||
|
m_formatCommand = settings->value(FORMAT_COMMAND, {}).toString();
|
||||||
|
m_formatCommandOptions = settings->value(FORMAT_COMMAND_OPTIONS, {}).toString();
|
||||||
|
m_useCustomFormatCommand = settings->value(CUSTOM_COMMAND, QVariant(false)).toBool();
|
||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,6 +71,15 @@ void QmlJsEditingSettings::toSettings(QSettings *settings) const
|
|||||||
settings->setValue(UIQML_OPEN_MODE, m_uiQmlOpenMode);
|
settings->setValue(UIQML_OPEN_MODE, m_uiQmlOpenMode);
|
||||||
settings->setValue(USE_QMLLS, m_qmllsSettings.useQmlls);
|
settings->setValue(USE_QMLLS, m_qmllsSettings.useQmlls);
|
||||||
settings->setValue(USE_LATEST_QMLLS, m_qmllsSettings.useLatestQmlls);
|
settings->setValue(USE_LATEST_QMLLS, m_qmllsSettings.useLatestQmlls);
|
||||||
|
Utils::QtcSettings::setValueWithDefault(settings, FORMAT_COMMAND, m_formatCommand, {});
|
||||||
|
Utils::QtcSettings::setValueWithDefault(settings,
|
||||||
|
FORMAT_COMMAND_OPTIONS,
|
||||||
|
m_formatCommandOptions,
|
||||||
|
{});
|
||||||
|
Utils::QtcSettings::setValueWithDefault(settings,
|
||||||
|
CUSTOM_COMMAND,
|
||||||
|
m_useCustomFormatCommand,
|
||||||
|
false);
|
||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
QmllsSettingsManager::instance()->checkForChanges();
|
QmllsSettingsManager::instance()->checkForChanges();
|
||||||
}
|
}
|
||||||
@@ -69,9 +90,10 @@ bool QmlJsEditingSettings::equals(const QmlJsEditingSettings &other) const
|
|||||||
&& m_pinContextPane == other.m_pinContextPane
|
&& m_pinContextPane == other.m_pinContextPane
|
||||||
&& m_autoFormatOnSave == other.m_autoFormatOnSave
|
&& m_autoFormatOnSave == other.m_autoFormatOnSave
|
||||||
&& m_autoFormatOnlyCurrentProject == other.m_autoFormatOnlyCurrentProject
|
&& m_autoFormatOnlyCurrentProject == other.m_autoFormatOnlyCurrentProject
|
||||||
&& m_foldAuxData == other.m_foldAuxData
|
&& m_foldAuxData == other.m_foldAuxData && m_qmllsSettings == other.m_qmllsSettings
|
||||||
&& m_qmllsSettings == other.m_qmllsSettings
|
&& m_uiQmlOpenMode == other.m_uiQmlOpenMode && m_formatCommand == other.m_formatCommand
|
||||||
&& m_uiQmlOpenMode == other.m_uiQmlOpenMode;
|
&& m_formatCommandOptions == other.m_formatCommandOptions
|
||||||
|
&& m_useCustomFormatCommand == other.m_useCustomFormatCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlJsEditingSettings::enableContextPane() const
|
bool QmlJsEditingSettings::enableContextPane() const
|
||||||
@@ -124,6 +146,41 @@ void QmlJsEditingSettings::setFoldAuxData(const bool foldAuxData)
|
|||||||
m_foldAuxData = foldAuxData;
|
m_foldAuxData = foldAuxData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString QmlJsEditingSettings::defaultFormatCommand() const
|
||||||
|
{
|
||||||
|
return DEFAULT_CUSTOM_FORMAT_COMMAND;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QmlJsEditingSettings::formatCommand() const
|
||||||
|
{
|
||||||
|
return m_formatCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlJsEditingSettings::setFormatCommand(const QString &formatCommand)
|
||||||
|
{
|
||||||
|
m_formatCommand = formatCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QmlJsEditingSettings::formatCommandOptions() const
|
||||||
|
{
|
||||||
|
return m_formatCommandOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlJsEditingSettings::setFormatCommandOptions(const QString &formatCommandOptions)
|
||||||
|
{
|
||||||
|
m_formatCommandOptions = formatCommandOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlJsEditingSettings::useCustomFormatCommand() const
|
||||||
|
{
|
||||||
|
return m_useCustomFormatCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlJsEditingSettings::setUseCustomFormatCommand(bool customCommand)
|
||||||
|
{
|
||||||
|
m_useCustomFormatCommand = customCommand;
|
||||||
|
}
|
||||||
|
|
||||||
QmllsSettings &QmlJsEditingSettings::qmllsSettigs()
|
QmllsSettings &QmlJsEditingSettings::qmllsSettigs()
|
||||||
{
|
{
|
||||||
return m_qmllsSettings;
|
return m_qmllsSettings;
|
||||||
@@ -156,6 +213,16 @@ public:
|
|||||||
new QCheckBox(Tr::tr("Restrict to files contained in the current project"));
|
new QCheckBox(Tr::tr("Restrict to files contained in the current project"));
|
||||||
autoFormatOnlyCurrentProject->setChecked(s.autoFormatOnlyCurrentProject());
|
autoFormatOnlyCurrentProject->setChecked(s.autoFormatOnlyCurrentProject());
|
||||||
autoFormatOnlyCurrentProject->setEnabled(autoFormatOnSave->isChecked());
|
autoFormatOnlyCurrentProject->setEnabled(autoFormatOnSave->isChecked());
|
||||||
|
useCustomFormatCommand = new QCheckBox(
|
||||||
|
Tr::tr("Use custom command instead of built-in formatter"));
|
||||||
|
useCustomFormatCommand->setChecked(s.useCustomFormatCommand());
|
||||||
|
auto formatCommandLabel = new QLabel(Tr::tr("Command:"));
|
||||||
|
formatCommand = new QLineEdit();
|
||||||
|
formatCommand->setText(s.formatCommand());
|
||||||
|
formatCommand->setPlaceholderText(s.defaultFormatCommand());
|
||||||
|
auto formatCommandOptionsLabel = new QLabel(Tr::tr("Arguments:"));
|
||||||
|
formatCommandOptions = new QLineEdit();
|
||||||
|
formatCommandOptions->setText(s.formatCommandOptions());
|
||||||
pinContextPane = new QCheckBox(Tr::tr("Pin Qt Quick Toolbar"));
|
pinContextPane = new QCheckBox(Tr::tr("Pin Qt Quick Toolbar"));
|
||||||
pinContextPane->setChecked(s.pinContextPane());
|
pinContextPane->setChecked(s.pinContextPane());
|
||||||
enableContextPane = new QCheckBox(Tr::tr("Always show Qt Quick Toolbar"));
|
enableContextPane = new QCheckBox(Tr::tr("Always show Qt Quick Toolbar"));
|
||||||
@@ -180,11 +247,23 @@ public:
|
|||||||
useLatestQmlls->setEnabled(checked != Qt::Unchecked);
|
useLatestQmlls->setEnabled(checked != Qt::Unchecked);
|
||||||
});
|
});
|
||||||
using namespace Utils::Layouting;
|
using namespace Utils::Layouting;
|
||||||
Column {
|
// clang-format off
|
||||||
|
const auto formattingGroup =
|
||||||
Group {
|
Group {
|
||||||
title(Tr::tr("Automatic Formatting on File Save")),
|
title(Tr::tr("Automatic Formatting on File Save")),
|
||||||
Column { autoFormatOnSave, autoFormatOnlyCurrentProject },
|
Column {
|
||||||
},
|
autoFormatOnSave,
|
||||||
|
autoFormatOnlyCurrentProject,
|
||||||
|
useCustomFormatCommand,
|
||||||
|
Form {
|
||||||
|
formatCommandLabel, formatCommand, br,
|
||||||
|
formatCommandOptionsLabel, formatCommandOptions
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Column {
|
||||||
|
formattingGroup,
|
||||||
Group {
|
Group {
|
||||||
title(Tr::tr("Qt Quick Toolbars")),
|
title(Tr::tr("Qt Quick Toolbars")),
|
||||||
Column { pinContextPane, enableContextPane },
|
Column { pinContextPane, enableContextPane },
|
||||||
@@ -201,11 +280,28 @@ public:
|
|||||||
Column{useQmlls, useLatestQmlls},
|
Column{useQmlls, useLatestQmlls},
|
||||||
},
|
},
|
||||||
st,
|
st,
|
||||||
}
|
}.attachTo(this);
|
||||||
.attachTo(this);
|
// clang-format on
|
||||||
|
|
||||||
connect(autoFormatOnSave, &QCheckBox::toggled,
|
Utils::VariableChooser::addSupportForChildWidgets(formattingGroup.widget,
|
||||||
autoFormatOnlyCurrentProject, &QWidget::setEnabled);
|
Utils::globalMacroExpander());
|
||||||
|
|
||||||
|
const auto updateFormatCommandState = [&, formatCommandLabel, formatCommandOptionsLabel] {
|
||||||
|
const bool enabled = useCustomFormatCommand->isChecked()
|
||||||
|
&& autoFormatOnSave->isChecked();
|
||||||
|
formatCommandLabel->setEnabled(enabled);
|
||||||
|
formatCommand->setEnabled(enabled);
|
||||||
|
formatCommandOptionsLabel->setEnabled(enabled);
|
||||||
|
formatCommandOptions->setEnabled(enabled);
|
||||||
|
};
|
||||||
|
updateFormatCommandState();
|
||||||
|
|
||||||
|
connect(autoFormatOnSave, &QCheckBox::toggled, this, [&, updateFormatCommandState]() {
|
||||||
|
autoFormatOnlyCurrentProject->setEnabled(autoFormatOnSave->isChecked());
|
||||||
|
useCustomFormatCommand->setEnabled(autoFormatOnSave->isChecked());
|
||||||
|
updateFormatCommandState();
|
||||||
|
});
|
||||||
|
connect(useCustomFormatCommand, &QCheckBox::toggled, this, updateFormatCommandState);
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply() final
|
void apply() final
|
||||||
@@ -215,6 +311,9 @@ public:
|
|||||||
s.setPinContextPane(pinContextPane->isChecked());
|
s.setPinContextPane(pinContextPane->isChecked());
|
||||||
s.setAutoFormatOnSave(autoFormatOnSave->isChecked());
|
s.setAutoFormatOnSave(autoFormatOnSave->isChecked());
|
||||||
s.setAutoFormatOnlyCurrentProject(autoFormatOnlyCurrentProject->isChecked());
|
s.setAutoFormatOnlyCurrentProject(autoFormatOnlyCurrentProject->isChecked());
|
||||||
|
s.setUseCustomFormatCommand(useCustomFormatCommand->isChecked());
|
||||||
|
s.setFormatCommand(formatCommand->text());
|
||||||
|
s.setFormatCommandOptions(formatCommandOptions->text());
|
||||||
s.setFoldAuxData(foldAuxData->isChecked());
|
s.setFoldAuxData(foldAuxData->isChecked());
|
||||||
s.setUiQmlOpenMode(uiQmlOpenComboBox->currentData().toString());
|
s.setUiQmlOpenMode(uiQmlOpenComboBox->currentData().toString());
|
||||||
s.qmllsSettigs().useQmlls = useQmlls->isChecked();
|
s.qmllsSettigs().useQmlls = useQmlls->isChecked();
|
||||||
@@ -225,6 +324,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
QCheckBox *autoFormatOnSave;
|
QCheckBox *autoFormatOnSave;
|
||||||
QCheckBox *autoFormatOnlyCurrentProject;
|
QCheckBox *autoFormatOnlyCurrentProject;
|
||||||
|
QCheckBox *useCustomFormatCommand;
|
||||||
|
QLineEdit *formatCommand;
|
||||||
|
QLineEdit *formatCommandOptions;
|
||||||
QCheckBox *pinContextPane;
|
QCheckBox *pinContextPane;
|
||||||
QCheckBox *enableContextPane;
|
QCheckBox *enableContextPane;
|
||||||
QCheckBox *foldAuxData;
|
QCheckBox *foldAuxData;
|
||||||
|
@@ -42,6 +42,16 @@ public:
|
|||||||
bool foldAuxData() const;
|
bool foldAuxData() const;
|
||||||
void setFoldAuxData(const bool foldAuxData);
|
void setFoldAuxData(const bool foldAuxData);
|
||||||
|
|
||||||
|
QString defaultFormatCommand() const;
|
||||||
|
QString formatCommand() const;
|
||||||
|
void setFormatCommand(const QString &formatCommand);
|
||||||
|
|
||||||
|
QString formatCommandOptions() const;
|
||||||
|
void setFormatCommandOptions(const QString &formatCommandOptions);
|
||||||
|
|
||||||
|
bool useCustomFormatCommand() const;
|
||||||
|
void setUseCustomFormatCommand(bool customCommand);
|
||||||
|
|
||||||
QmllsSettings &qmllsSettigs();
|
QmllsSettings &qmllsSettigs();
|
||||||
const QmllsSettings &qmllsSettigs() const;
|
const QmllsSettings &qmllsSettigs() const;
|
||||||
|
|
||||||
@@ -59,8 +69,11 @@ private:
|
|||||||
bool m_autoFormatOnSave = false;
|
bool m_autoFormatOnSave = false;
|
||||||
bool m_autoFormatOnlyCurrentProject = false;
|
bool m_autoFormatOnlyCurrentProject = false;
|
||||||
bool m_foldAuxData = true;
|
bool m_foldAuxData = true;
|
||||||
|
bool m_useCustomFormatCommand = false;
|
||||||
QmllsSettings m_qmllsSettings;
|
QmllsSettings m_qmllsSettings;
|
||||||
QString m_uiQmlOpenMode = {};
|
QString m_uiQmlOpenMode;
|
||||||
|
QString m_formatCommand;
|
||||||
|
QString m_formatCommandOptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
@@ -30,12 +30,15 @@
|
|||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <projectexplorer/projecttree.h>
|
#include <projectexplorer/projecttree.h>
|
||||||
#include <projectexplorer/taskhub.h>
|
#include <projectexplorer/taskhub.h>
|
||||||
|
#include <texteditor/command.h>
|
||||||
#include <texteditor/formattexteditor.h>
|
#include <texteditor/formattexteditor.h>
|
||||||
#include <texteditor/snippets/snippetprovider.h>
|
#include <texteditor/snippets/snippetprovider.h>
|
||||||
#include <texteditor/tabsettings.h>
|
#include <texteditor/tabsettings.h>
|
||||||
|
#include <texteditor/texteditor.h>
|
||||||
#include <texteditor/texteditorconstants.h>
|
#include <texteditor/texteditorconstants.h>
|
||||||
#include <utils/fsengine/fileiconprovider.h>
|
#include <utils/fsengine/fileiconprovider.h>
|
||||||
#include <utils/json.h>
|
#include <utils/json.h>
|
||||||
|
#include <utils/macroexpander.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QTextDocument>
|
#include <QTextDocument>
|
||||||
@@ -237,6 +240,35 @@ void QmlJSEditorPluginPrivate::renameUsages()
|
|||||||
void QmlJSEditorPluginPrivate::reformatFile()
|
void QmlJSEditorPluginPrivate::reformatFile()
|
||||||
{
|
{
|
||||||
if (m_currentDocument) {
|
if (m_currentDocument) {
|
||||||
|
if (QmlJsEditingSettings::get().useCustomFormatCommand()) {
|
||||||
|
QString formatCommand = QmlJsEditingSettings::get().formatCommand();
|
||||||
|
if (formatCommand.isEmpty())
|
||||||
|
formatCommand = QmlJsEditingSettings::get().defaultFormatCommand();
|
||||||
|
const auto exe = FilePath::fromUserInput(globalMacroExpander()->expand(formatCommand));
|
||||||
|
const QString args = globalMacroExpander()->expand(
|
||||||
|
QmlJsEditingSettings::get().formatCommandOptions());
|
||||||
|
const CommandLine commandLine(exe, args, CommandLine::Raw);
|
||||||
|
TextEditor::Command command;
|
||||||
|
command.setExecutable(commandLine.executable().toString());
|
||||||
|
command.setProcessing(TextEditor::Command::FileProcessing);
|
||||||
|
command.addOptions(commandLine.splitArguments());
|
||||||
|
command.addOption("--inplace");
|
||||||
|
command.addOption("%file");
|
||||||
|
|
||||||
|
if (!command.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QList<Core::IEditor *> editors = Core::DocumentModel::editorsForDocument(m_currentDocument);
|
||||||
|
if (editors.isEmpty())
|
||||||
|
return;
|
||||||
|
IEditor *currentEditor = EditorManager::currentEditor();
|
||||||
|
IEditor *editor = editors.contains(currentEditor) ? currentEditor : editors.first();
|
||||||
|
if (auto widget = TextEditor::TextEditorWidget::fromEditor(editor))
|
||||||
|
TextEditor::formatEditor(widget, command);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QmlJS::Document::Ptr document = m_currentDocument->semanticInfo().document;
|
QmlJS::Document::Ptr document = m_currentDocument->semanticInfo().document;
|
||||||
QmlJS::Snapshot snapshot = QmlJS::ModelManagerInterface::instance()->snapshot();
|
QmlJS::Snapshot snapshot = QmlJS::ModelManagerInterface::instance()->snapshot();
|
||||||
|
|
||||||
|
@@ -30,6 +30,11 @@ void Command::addOption(const QString &option)
|
|||||||
m_options << option;
|
m_options << option;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Command::addOptions(const QStringList &options)
|
||||||
|
{
|
||||||
|
m_options += options;
|
||||||
|
}
|
||||||
|
|
||||||
Command::Processing Command::processing() const
|
Command::Processing Command::processing() const
|
||||||
{
|
{
|
||||||
return m_processing;
|
return m_processing;
|
||||||
|
@@ -25,6 +25,7 @@ public:
|
|||||||
|
|
||||||
QStringList options() const;
|
QStringList options() const;
|
||||||
void addOption(const QString &option);
|
void addOption(const QString &option);
|
||||||
|
void addOptions(const QStringList &options);
|
||||||
|
|
||||||
Processing processing() const;
|
Processing processing() const;
|
||||||
void setProcessing(const Processing &processing);
|
void setProcessing(const Processing &processing);
|
||||||
|
Reference in New Issue
Block a user