Designer: take tab settings into account when generating qml code

Task-number: QTCREATORBUG-24523
Change-Id: I1e02c781fbbde8114dd4570460756ce796275379
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
David Schulz
2021-05-06 12:21:08 +02:00
parent c17c805e43
commit 39921ce7bd
13 changed files with 86 additions and 104 deletions

View File

@@ -33,7 +33,6 @@
#include <typeinfo>
static Q_LOGGING_CATEGORY(qmlRewriter, "qtc.rewriter.qmlrewriter", QtWarningMsg)
using namespace QmlDesigner::Internal;
@@ -73,24 +72,18 @@ QString QMLRewriter::textAt(const QmlJS::SourceLocation &location) const
return m_textModifier->text().mid(location.offset, location.length);
}
int QMLRewriter::indentDepth() const
{
return textModifier()->tabSettings().m_indentSize;
}
unsigned QMLRewriter::calculateIndentDepth(const QmlJS::SourceLocation &position) const
{
QTextDocument *doc = m_textModifier->textDocument();
QTextCursor tc(doc);
tc.setPosition(position.offset);
const int lineOffset = tc.block().position();
unsigned indentDepth = 0;
forever {
const QChar ch = doc->characterAt(lineOffset + indentDepth);
if (ch.isNull() || !ch.isSpace())
break;
else
++indentDepth;
}
return indentDepth;
return textModifier()->tabSettings().indentationColumn(tc.block().text());
}
QString QMLRewriter::addIndentation(const QString &text, unsigned depth)
@@ -98,56 +91,20 @@ QString QMLRewriter::addIndentation(const QString &text, unsigned depth)
if (depth == 0)
return text;
const QString indentation(depth, QLatin1Char(' '));
if (text.isEmpty())
return indentation;
const QLatin1Char lineSep('\n');
const QStringList lines = text.split(lineSep);
TextEditor::TabSettings tabSettings = textModifier()->tabSettings();
QString result;
for (int i = 0; i < lines.size(); ++i) {
if (i > 0)
result += lineSep;
const QString &line = lines.at(i);
if (!line.isEmpty()) {
result += indentation;
result += line;
}
}
return result;
}
QString QMLRewriter::removeIndentationFromLine(const QString &text, int depth)
{
int charsToRemove = 0;
for (int i = 0; i < depth && i < text.length(); ++i) {
if (text.at(i).isSpace())
charsToRemove++;
else
break;
}
if (charsToRemove == 0)
return text;
else
return text.mid(charsToRemove);
}
QString QMLRewriter::removeIndentation(const QString &text, unsigned depth)
{
const QLatin1Char lineSep('\n');
constexpr char lineSep('\n');
const QStringList lines = text.split(lineSep);
QString result;
for (int i = 0; i < lines.size(); ++i) {
if (i > 0)
for (const QString &line : lines) {
if (!result.isEmpty())
result += lineSep;
result += removeIndentationFromLine(lines.at(i), depth);
if (line.isEmpty())
continue;
const int firstNoneSpace = TextEditor::TabSettings::firstNonSpace(line);
const int lineIndentColumn = tabSettings.indentationColumn(line) + int(depth);
result.append(tabSettings.indentationString(0, lineIndentColumn, 0));
result.append(line.midRef(firstNoneSpace));
}
return result;
}

View File

@@ -59,12 +59,9 @@ protected:
QString textBetween(int startPosition, int endPosition) const;
QString textAt(const QmlJS::SourceLocation &location) const;
int indentDepth() const
{ return textModifier()->indentDepth(); }
int indentDepth() const;
unsigned calculateIndentDepth(const QmlJS::SourceLocation &position) const;
static QString addIndentation(const QString &text, unsigned depth);
static QString removeIndentation(const QString &text, unsigned depth);
static QString removeIndentationFromLine(const QString &text, int depth);
QString addIndentation(const QString &text, unsigned depth);
static QmlJS::SourceLocation calculateLocation(QmlJS::AST::UiQualifiedId *id);
static bool isMissingSemicolon(QmlJS::AST::UiObjectMember *member);

View File

@@ -44,7 +44,7 @@ public:
void indentLines(int startLine, int endLine) override;
void indent(int offset, int length) override;
int indentDepth() const override;
TextEditor::TabSettings tabSettings() const override;
bool renameId(const QString &oldId, const QString &newId) override;
bool moveToComponent(int nodeOffset) override;

View File

@@ -41,7 +41,7 @@ public:
void indent(int offset, int length) override;
void indentLines(int startLine, int endLine) override;
int indentDepth() const override;
TextEditor::TabSettings tabSettings() const override;
void startGroup() override;
void flushGroup() override;

View File

@@ -59,8 +59,6 @@ public:
void indent(int offset, int length) override = 0;
void indentLines(int startLine, int endLine) override = 0;
int indentDepth() const override = 0;
void startGroup() override;
void flushGroup() override;
void commitGroup() override;
@@ -95,19 +93,28 @@ class QMLDESIGNERCORE_EXPORT NotIndentingTextEditModifier: public PlainTextEditM
public:
NotIndentingTextEditModifier(QPlainTextEdit *textEdit)
: PlainTextEditModifier(textEdit)
{}
{
m_tabSettings.m_tabSize = 0;
m_tabSettings.m_indentSize = 0;
}
NotIndentingTextEditModifier(QTextDocument *document, const QTextCursor &textCursor)
: PlainTextEditModifier{document, textCursor}
{}
{
m_tabSettings.m_tabSize = 0;
m_tabSettings.m_indentSize = 0;
}
void indent(int /*offset*/, int /*length*/) override
{}
void indentLines(int /*offset*/, int /*length*/) override
{}
int indentDepth() const override
{ return 0; }
TextEditor::TabSettings tabSettings() const override
{ return m_tabSettings; }
private:
TextEditor::TabSettings m_tabSettings;
};
}

View File

@@ -28,11 +28,15 @@
#include "qmldesignercorelib_global.h"
#include <qmljs/qmljsdocument.h>
#include <texteditor/tabsettings.h>
#include <utils/optional.h>
#include <QObject>
#include <QTextCursor>
#include <QTextDocument>
namespace TextEditor { class TabSettings; }
namespace QmlDesigner {
class QMLDESIGNERCORE_EXPORT TextModifier: public QObject
@@ -66,7 +70,7 @@ public:
virtual void indent(int offset, int length) = 0;
virtual void indentLines(int startLine, int endLine) = 0;
virtual int indentDepth() const = 0;
virtual TextEditor::TabSettings tabSettings() const = 0;
virtual void startGroup() = 0;
virtual void flushGroup() = 0;

View File

@@ -31,7 +31,9 @@
#include <qmljseditor/qmljseditordocument.h>
#include <qmljseditor/qmljscomponentfromobjectdef.h>
#include <qmljseditor/qmljscompletionassist.h>
#include <qmljstools/qmljstoolssettings.h>
#include <texteditor/tabsettings.h>
#include <texteditor/simplecodestylepreferences.h>
#include <utils/changeset.h>
#include <typeinfo>
@@ -80,12 +82,11 @@ void BaseTextEditModifier::indent(int offset, int length)
indentLines(startLine, endLine);
}
int BaseTextEditModifier::indentDepth() const
TextEditor::TabSettings BaseTextEditModifier::tabSettings() const
{
if (m_textEdit)
return m_textEdit->textDocument()->tabSettings().m_indentSize;
else
return 0;
return m_textEdit->textDocument()->tabSettings();
return QmlJSTools::QmlJSToolsSettings::globalCodeStyle()->tabSettings();
}
bool BaseTextEditModifier::renameId(const QString &oldId, const QString &newId)

View File

@@ -83,9 +83,9 @@ void ComponentTextModifier::indentLines(int startLine, int endLine)
m_originalModifier->indentLines(startLine, endLine);
}
int ComponentTextModifier::indentDepth() const
TextEditor::TabSettings ComponentTextModifier::tabSettings() const
{
return m_originalModifier->indentDepth();
return m_originalModifier->tabSettings();
}
void ComponentTextModifier::startGroup()

View File

@@ -81,12 +81,13 @@ void ModelToTextMerger::propertiesRemoved(const QList<AbstractProperty>& propert
void ModelToTextMerger::propertiesChanged(const QList<AbstractProperty>& propertyList, PropertyChangeFlags propertyChange)
{
const TextEditor::TabSettings tabSettings = m_rewriterView->textModifier()->tabSettings();
foreach (const AbstractProperty &property, propertyList) {
ModelNode containedModelNode;
const int indentDepth = m_rewriterView->textModifier()->indentDepth();
const QString propertyTextValue = QmlTextGenerator(propertyOrder(),
indentDepth)(property);
tabSettings,
tabSettings.m_indentSize)(property);
switch (propertyChange) {
case AbstractView::PropertiesAdded:
@@ -162,14 +163,18 @@ void ModelToTextMerger::nodeReparented(const ModelNode &node, const NodeAbstract
switch (propertyChange) {
case AbstractView::PropertiesAdded:
schedule(new AddPropertyRewriteAction(newPropertyParent,
QmlTextGenerator(propertyOrder())(node),
QmlTextGenerator(propertyOrder(),
m_rewriterView->textModifier()
->tabSettings())(node),
propertyType(newPropertyParent),
node));
break;
case AbstractView::NoAdditionalChanges:
schedule(new ChangePropertyRewriteAction(newPropertyParent,
QmlTextGenerator(propertyOrder())(node),
QmlTextGenerator(propertyOrder(),
m_rewriterView->textModifier()
->tabSettings())(node),
propertyType(newPropertyParent),
node));
break;
@@ -213,7 +218,7 @@ void ModelToTextMerger::applyChanges()
dumpRewriteActions(QStringLiteral("Before compression"));
RewriteActionCompressor compress(propertyOrder());
compress(m_rewriteActions);
compress(m_rewriteActions, m_rewriterView->textModifier()->tabSettings());
dumpRewriteActions(QStringLiteral("After compression"));
if (m_rewriteActions.isEmpty())

View File

@@ -85,9 +85,12 @@ static QString unicodeEscape(const QString &stringValue)
return stringValue;
}
QmlTextGenerator::QmlTextGenerator(const PropertyNameList &propertyOrder, int indentDepth):
m_propertyOrder(propertyOrder),
m_indentDepth(indentDepth)
QmlTextGenerator::QmlTextGenerator(const PropertyNameList &propertyOrder,
const TextEditor::TabSettings &tabSettings,
const int startIndentDepth)
: m_propertyOrder(propertyOrder)
, m_tabSettings(tabSettings)
, m_startIndentDepth(startIndentDepth)
{
}
@@ -106,13 +109,13 @@ QString QmlTextGenerator::toQml(const AbstractProperty &property, int indentDept
for (int i = 0; i < nodes.length(); ++i) {
if (i > 0)
result += QStringLiteral("\n\n");
result += QString(indentDepth, QLatin1Char(' '));
result += m_tabSettings.indentationString(0, indentDepth, 0);
result += toQml(nodes.at(i), indentDepth);
}
return result;
} else {
QString result = QStringLiteral("[");
const int arrayContentDepth = indentDepth + 4;
const int arrayContentDepth = indentDepth + m_tabSettings.m_indentSize;
const QString arrayContentIndentation(arrayContentDepth, QLatin1Char(' '));
for (int i = 0; i < nodes.length(); ++i) {
if (i > 0)
@@ -208,11 +211,12 @@ QString QmlTextGenerator::toQml(const ModelNode &node, int indentDepth) const
result += type;
result += QStringLiteral(" {\n");
const int propertyIndentDepth = indentDepth + 4;
const int propertyIndentDepth = indentDepth + m_tabSettings.m_indentSize;
const QString properties = propertiesToQml(node, propertyIndentDepth);
return result + properties + QString(indentDepth, QLatin1Char(' ')) + QLatin1Char('}');
return result + properties + m_tabSettings.indentationString(0, indentDepth, 0)
+ QLatin1Char('}');
}
QString QmlTextGenerator::propertiesToQml(const ModelNode &node, int indentDepth) const
@@ -227,7 +231,7 @@ QString QmlTextGenerator::propertiesToQml(const ModelNode &node, int indentDepth
if (propertyName == "id") {
// the model handles the id property special, so:
if (!node.id().isEmpty()) {
QString idLine(indentDepth, QLatin1Char(' '));
QString idLine = m_tabSettings.indentationString(0, indentDepth, 0);
idLine += QStringLiteral("id: ");
idLine += node.id();
idLine += QLatin1Char('\n');
@@ -264,7 +268,7 @@ QString QmlTextGenerator::propertyToQml(const AbstractProperty &property, int in
result = toQml(property, indentDepth);
} else {
if (property.isDynamic()) {
result = QString(indentDepth, QLatin1Char(' '))
result = m_tabSettings.indentationString(0, indentDepth, 0)
+ QStringLiteral("property ")
+ QString::fromUtf8(property.dynamicTypeName())
+ QStringLiteral(" ")
@@ -272,7 +276,7 @@ QString QmlTextGenerator::propertyToQml(const AbstractProperty &property, int in
+ QStringLiteral(": ")
+ toQml(property, indentDepth);
} else {
result = QString(indentDepth, QLatin1Char(' '))
result = m_tabSettings.indentationString(0, indentDepth, 0)
+ QString::fromUtf8(property.name())
+ QStringLiteral(": ")
+ toQml(property, indentDepth);

View File

@@ -27,6 +27,8 @@
#include <QString>
#include <texteditor/tabsettings.h>
#include "abstractproperty.h"
#include "modelnode.h"
@@ -36,13 +38,15 @@ namespace Internal {
class QmlTextGenerator
{
public:
explicit QmlTextGenerator(const PropertyNameList &propertyOrder, int indentDepth = 0);
explicit QmlTextGenerator(const PropertyNameList &propertyOrder,
const TextEditor::TabSettings &tabSettings,
const int startIndentDepth = 0);
QString operator()(const AbstractProperty &property) const
{ return toQml(property, m_indentDepth); }
{ return toQml(property, m_startIndentDepth); }
QString operator()(const ModelNode &modelNode) const
{ return toQml(modelNode, m_indentDepth); }
{ return toQml(modelNode, m_startIndentDepth); }
private:
QString toQml(const AbstractProperty &property, int indentDepth) const;
@@ -54,7 +58,8 @@ private:
private:
PropertyNameList m_propertyOrder;
int m_indentDepth;
TextEditor::TabSettings m_tabSettings;
const int m_startIndentDepth;
};
} // namespace Internal

View File

@@ -50,14 +50,15 @@ static bool nodeOrParentInSet(const ModelNode &modelNode, const QSet<ModelNode>
return false;
}
void RewriteActionCompressor::operator()(QList<RewriteAction *> &actions) const
void RewriteActionCompressor::operator()(QList<RewriteAction *> &actions,
const TextEditor::TabSettings &tabSettings) const
{
compressImports(actions);
compressRereparentActions(actions);
compressReparentIntoSamePropertyActions(actions);
compressPropertyActions(actions);
compressAddEditRemoveNodeActions(actions);
compressAddEditActions(actions);
compressAddEditActions(actions, tabSettings);
compressAddReparentActions(actions);
}
@@ -256,7 +257,8 @@ void RewriteActionCompressor::compressPropertyActions(QList<RewriteAction *> &ac
}
}
void RewriteActionCompressor::compressAddEditActions(QList<RewriteAction *> &actions) const
void RewriteActionCompressor::compressAddEditActions(
QList<RewriteAction *> &actions, const TextEditor::TabSettings &tabSettings) const
{
QList<RewriteAction *> actionsToRemove;
QSet<ModelNode> addedNodes;
@@ -303,7 +305,7 @@ void RewriteActionCompressor::compressAddEditActions(QList<RewriteAction *> &act
delete action;
}
QmlTextGenerator gen(m_propertyOrder);
QmlTextGenerator gen(m_propertyOrder, tabSettings);
foreach (RewriteAction *action, dirtyActions) {
RewriteAction *newAction = nullptr;
if (AddPropertyRewriteAction *addAction = action->asAddPropertyRewriteAction()) {

View File

@@ -35,7 +35,7 @@ class RewriteActionCompressor
public:
RewriteActionCompressor(const PropertyNameList &propertyOrder): m_propertyOrder(propertyOrder) {}
void operator()(QList<RewriteAction *> &actions) const;
void operator()(QList<RewriteAction *> &actions, const TextEditor::TabSettings &tabSettings) const;
private:
void compressImports(QList<RewriteAction *> &actions) const;
@@ -44,7 +44,7 @@ private:
void compressReparentIntoSamePropertyActions(QList<RewriteAction *> &actions) const;
void compressAddEditRemoveNodeActions(QList<RewriteAction *> &actions) const;
void compressPropertyActions(QList<RewriteAction *> &actions) const;
void compressAddEditActions(QList<RewriteAction *> &actions) const;
void compressAddEditActions(QList<RewriteAction *> &actions, const TextEditor::TabSettings &tabSettings) const;
void compressAddReparentActions(QList<RewriteAction *> &actions) const;
private: