qmlformat: Remove import sorting

Remove import sorting due to the fact that sorting imports can break code.

[ChangeLog][QML Tooling][qmlformat] Remove import sorting and the (now obsolete) -n parameter to disable it

Fixes: QTBUG-89295
Pick-to: 6.0
Change-Id: I5ff13d0ae3c715db7645b412152aadb31811ce5a
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
Maximilian Goldstein 2020-12-10 15:58:36 +01:00
parent 4db8926608
commit cf3e0559b0
10 changed files with 33 additions and 340 deletions

View File

@ -1,106 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Charts module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** 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 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
//![2]
import QtQuick 2.0
//![2]
import QtCharts 2.0
@Pippo {
atg1: 3
}
@Annotation2 {
}
Item {
//![1]
@AnnotateMore {
property int x: 5
}
@AnnotateALot {
}
property variant othersSlice: 0
@Annotate {
}
anchors.fill: parent
@SuperComplete {
binding: late
}
Component.onCompleted: {
// You can also manipulate slices dynamically, like append a slice or set a slice exploded
othersSlice = pieSeries.append("Others", 52);
pieSeries.find("Volkswagen").exploded = true;
}
//![1]
ChartView {
id: chart
title: "Top-5 car brand shares in Finland"
anchors.fill: parent
legend.alignment: Qt.AlignBottom
antialiasing: true
@ExtraAnnotation {
signal pippo()
}
PieSeries {
id: pieSeries
PieSlice {
label: "Volkswagen"
value: 13.5
}
PieSlice {
label: "Toyota"
value: 10.9
}
PieSlice {
label: "Ford"
value: 8.6
}
PieSlice {
label: "Skoda"
value: 8.2
}
PieSlice {
label: "Volvo"
value: 6.8
}
}
}
}

View File

@ -27,10 +27,10 @@
**
****************************************************************************/
//![2]
import QtCharts 2.0
//![2]
import QtQuick 2.0
//![2]
import QtCharts 2.0
@Pippo {
atg1: 3

View File

@ -3,19 +3,19 @@
2. Goodbye
*/
import A.B.B.A
import A.LLOHA
// Importing this is very important
import QtQuick 5.15
// Muddling the waters!
import QtQuick.Models 3.14 as muddle
import That
import This // THIS IS VERY IMPORTANT!
import X.Y
import X.Z
import Y
// Importing that is important too
import Z
import That
import This // THIS IS VERY IMPORTANT!
import Y
import X.Z
import X.Y
import A.LLOHA
import A.B.B.A
// This comment is related to Item
Item {

View File

@ -1,151 +0,0 @@
/* This file is licensed under the not a license license
1. You may not comply
2. Goodbye
*/
// Importing this is very important
import QtQuick 5.15
// Muddling the waters!
import QtQuick.Models 3.14 as muddle
// Importing that is important too
import Z
import That
import This // THIS IS VERY IMPORTANT!
import Y
import X.Z
import X.Y
import A.LLOHA
import A.B.B.A
// This comment is related to Item
Item {
// Orphan comment
// Another orphan
// More orphans
// This to id
// Also id. (line 2)
// This is the third id
// fourth id comment
id: foo
// This to enum
enum Foo {
A = 3, // This is A
B, // This is B
C = 4, // This is C
D // This is D
}
property bool some_bool: false
property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
property bool something_computed: function(x) {
// This is an orphan inside something_computed
// Are these getting duplicated?
// Another orphan inside something_computed
const PI = 3, DAYS_PER_YEAR = 365.25;
var x = 3 + 2;
x["bla"] = 50;
// This one to var few!
var few = new WhatEver();
x += Math.sin(3);
x--;
--x;
x++;
++x;
for (var x = 0; x < 100; x++) {
x++;
console.log("Foo");
}
for (var x in [3, 2, 1]) {
y++;
console.log("Bar");
}
while (true)
console.log("Wee");
with (foo) {
bar;
x += 5;
} // This is related to with!
x3:
do {
console.log("Hello");
} while (3 == 0);
try {
dangerous();
} catch (e) {
console.log(e);
} finally {
dangerous();
}
switch (x) {
case 0:
x = 1;
break;
case 1:
x = 5;
break;
case 4:
x = 100;
break;
}
if (x == 50)
console.log("true");
else if (x == 50)
console.log("other thing");
else
console.log("false");
if (x == 50) {
console.log("true");
} else if (x == 50) {
console.log("other thing");
x--;
} else {
console.log("false");
}
return "foobar";
}()
default property bool some_default_bool: 500 % 5 !== 0 // some_default_bool
// some_read_only_bool
readonly property bool some_read_only_bool: Math.sin(3) && (aFunc()[30] + 5) | 2 != 0
signal say(string name, bool caps)
// This one to aFunc()
function aFunc() {
var x = 3;
return x;
}
x: 3 // Very cool
Component.onCompleted: console.log("Foo!")
myFavouriteThings: [
// This is an orphan
// This is a cool text
Text {
},
// This is a cool rectangle
Rectangle {
}
]
Text {
required property string batman
signal boo(int count, int times, real duration)
text: "Bla"
}
// This comment is related to the property animation
PropertyAnimation on x {
id: foo
x: 3
y: x + 3
}
}

View File

@ -3,19 +3,19 @@
2. Goodbye
*/
import A.B.B.A
import A.LLOHA
// Importing this is very important
import QtQuick 5.15
// Muddling the waters!
import QtQuick.Models 3.14 as muddle
import That
import This // THIS IS VERY IMPORTANT!
import X.Y
import X.Z
import Y
// Importing that is important too
import Z
import That
import This // THIS IS VERY IMPORTANT!
import Y
import X.Z
import X.Y
import A.LLOHA
import A.B.B.A
// This comment is related to Item
Item {

View File

@ -3,19 +3,19 @@
2. Goodbye
*/
import A.B.B.A
import A.LLOHA
// Importing this is very important
import QtQuick 5.15
// Muddling the waters!
import QtQuick.Models 3.14 as muddle
import That
import This // THIS IS VERY IMPORTANT!
import X.Y
import X.Z
import Y
// Importing that is important too
import Z
import That
import This // THIS IS VERY IMPORTANT!
import Y
import X.Z
import X.Y
import A.LLOHA
import A.B.B.A
// This comment is related to Item
Item {

View File

@ -201,21 +201,17 @@ void TestQmlformat::testFormat_data()
QTest::addColumn<QString>("fileFormatted");
QTest::addColumn<QStringList>("args");
QTest::newRow("example1 (sorted)") << "Example1.qml"
<< "Example1.formatted.qml" << QStringList {};
QTest::newRow("example1 (not sorted)")
QTest::newRow("example1")
<< "Example1.qml"
<< "Example1.formatted.nosort.qml" << QStringList { "-n" };
<< "Example1.formatted.qml" << QStringList {};
QTest::newRow("example1 (tabs)") << "Example1.qml"
<< "Example1.formatted.tabs.qml" << QStringList { "-t" };
QTest::newRow("example1 (two spaces)")
<< "Example1.qml"
<< "Example1.formatted.2spaces.qml" << QStringList { "-w", "2" };
QTest::newRow("annotation (sorted)") << "Annotations.qml"
<< "Annotations.formatted.qml" << QStringList {};
QTest::newRow("annotation (not sorted)")
QTest::newRow("annotation")
<< "Annotations.qml"
<< "Annotations.formatted.nosort.qml" << QStringList { "-n" };
<< "Annotations.formatted.qml" << QStringList {};
QTest::newRow("front inline") << "FrontInline.qml"
<< "FrontInline.formatted.qml" << QStringList {};
QTest::newRow("if blocks") << "IfBlocks.qml"

View File

@ -44,7 +44,7 @@
#include "dumpastvisitor.h"
#include "restructureastvisitor.h"
bool parseFile(const QString &filename, bool inplace, bool verbose, bool sortImports, bool force,
bool parseFile(const QString &filename, bool inplace, bool verbose, bool force,
int indentWidth, bool tabs, const QString &newline)
{
QFile file(filename);
@ -91,11 +91,8 @@ bool parseFile(const QString &filename, bool inplace, bool verbose, bool sortImp
qWarning().noquote() << orphaned << "comments are orphans.";
}
if (verbose && sortImports)
qWarning().noquote() << "Sorting imports";
// Do the actual restructuring
RestructureAstVisitor restructure(parser.rootNode(), sortImports);
RestructureAstVisitor restructure(parser.rootNode());
// Turn AST back into source code
if (verbose)
@ -185,9 +182,6 @@ int main(int argc, char *argv[])
parser.addOption(QCommandLineOption({"V", "verbose"},
QStringLiteral("Verbose mode. Outputs more detailed information.")));
parser.addOption(QCommandLineOption({"n", "no-sort"},
QStringLiteral("Do not sort imports.")));
parser.addOption(QCommandLineOption({"i", "inplace"},
QStringLiteral("Edit file in-place instead of outputting to stdout.")));
@ -248,7 +242,7 @@ int main(int argc, char *argv[])
if (file.isEmpty())
continue;
if (!parseFile(file, true, parser.isSet("verbose"), !parser.isSet("no-sort"),
if (!parseFile(file, true, parser.isSet("verbose"),
parser.isSet("force"), indentWidth, parser.isSet("tabs"),
parser.value("newline")))
success = false;
@ -256,7 +250,7 @@ int main(int argc, char *argv[])
} else {
for (const QString &file : parser.positionalArguments()) {
if (!parseFile(file, parser.isSet("inplace"), parser.isSet("verbose"),
!parser.isSet("no-sort"), parser.isSet("force"), indentWidth,
parser.isSet("force"), indentWidth,
parser.isSet("tabs"), parser.value("newline")))
success = false;
}

View File

@ -30,7 +30,7 @@
#include <QList>
RestructureAstVisitor::RestructureAstVisitor(Node *rootNode, bool sortImports) : m_sortImports(sortImports)
RestructureAstVisitor::RestructureAstVisitor(Node *rootNode)
{
rootNode->accept(this);
}
@ -69,43 +69,6 @@ static QString parseUiQualifiedId(UiQualifiedId *id)
return name;
}
void RestructureAstVisitor::endVisit(UiHeaderItemList *node)
{
QList<Node *> correctOrder;
auto imports = findKind<UiImport>(node);
if (!m_sortImports)
return;
// Sort imports
std::sort(imports.begin(), imports.end(), [](UiImport *a, UiImport *b)
{
auto nameA = a->fileName.isEmpty() ? parseUiQualifiedId(a->importUri)
: a->fileName.toString();
auto nameB = b->fileName.isEmpty() ? parseUiQualifiedId(b->importUri)
: b->fileName.toString();
return nameA < nameB;
});
// Add imports
for (auto *import : imports)
correctOrder.append(import);
// Add all the other items
for (auto *item = node; item != nullptr; item = item->next) {
if (!correctOrder.contains(item->headerItem))
correctOrder.append(item->headerItem);
}
// Rebuild member list from correctOrder
for (auto *item = node; item != nullptr; item = item->next) {
item->headerItem = correctOrder.front();
correctOrder.pop_front();
}
}
void RestructureAstVisitor::endVisit(UiObjectMemberList *node)
{
QList<UiObjectMember*> correctOrder;

View File

@ -37,14 +37,11 @@ using namespace QQmlJS::AST;
class RestructureAstVisitor : protected Visitor
{
public:
RestructureAstVisitor(Node *rootNode, bool sortImports);
RestructureAstVisitor(Node *rootNode);
void throwRecursionDepthError() override {}
void endVisit(UiObjectMemberList *node) override;
void endVisit(UiHeaderItemList *node) override;
private:
bool m_sortImports = false;
};
#endif // RESTRUCTUREASTVISITOR_H