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