diff options
12 files changed, 65 insertions, 12 deletions
diff --git a/src/qml/parser/qqmljsengine_p.h b/src/qml/parser/qqmljsengine_p.h index 568bf4d35b..37f78a30e1 100644 --- a/src/qml/parser/qqmljsengine_p.h +++ b/src/qml/parser/qqmljsengine_p.h @@ -71,8 +71,8 @@ public: void addComment(int pos, int len, int line, int col) { - if (len > 0) - _comments.append(QQmlJS::SourceLocation(pos, len, line, col)); + Q_ASSERT(len >= 0); + _comments.append(QQmlJS::SourceLocation(pos, len, line, col)); } QList<SourceLocation> comments() const { return _comments; } diff --git a/src/qmldom/qqmldomcomments.cpp b/src/qmldom/qqmldomcomments.cpp index 559f7c0d73..b9fc3e9ed5 100644 --- a/src/qmldom/qqmldomcomments.cpp +++ b/src/qmldom/qqmldomcomments.cpp @@ -99,8 +99,6 @@ CommentInfo::CommentInfo(QStringView rawComment) : rawComment(rawComment) } commentEnd = commentBegin + commentStartStr.size(); quint32 rawEnd = quint32(rawComment.size()); - while (commentEnd < rawEnd && rawComment.at(commentEnd).isSpace()) - ++commentEnd; commentContentEnd = commentContentBegin = commentEnd; QChar e1 = ((expectedEnd.isEmpty()) ? QChar::fromLatin1(0) : expectedEnd.at(0)); while (commentEnd < rawEnd) { @@ -115,7 +113,8 @@ CommentInfo::CommentInfo(QStringView rawComment) : rawComment(rawComment) commentContentEnd = commentEnd; } } else { - commentEndStr = rawComment.mid(++commentEnd - 1, 1); + // Comment ends with \n, treat as it is not part of the comment but post whitespace + commentEndStr = rawComment.mid(commentEnd - 1, 1); break; } } else if (!c.isSpace()) { @@ -503,6 +502,7 @@ void AstComments::collectComments(std::shared_ptr<Engine> engine, AST::Node *n, // do not add newline before, but add the one after quint32 iPre = cLoc.begin(); int preNewline = 0; + int postNewline = 0; QStringView commentStartStr; while (iPre > 0) { QChar c = code.at(iPre - 1); @@ -531,8 +531,10 @@ void AstComments::collectComments(std::shared_ptr<Engine> engine, AST::Node *n, } --iPre; } + if (iPre == 0) preNewline = 1; + qsizetype iPost = cLoc.end(); while (iPost < code.size()) { QChar c = code.at(iPost); @@ -545,16 +547,25 @@ void AstComments::collectComments(std::shared_ptr<Engine> engine, AST::Node *n, } else { break; } + } else { + if (c == QLatin1Char('\n')) { + ++postNewline; + if (iPost + 1 < code.size() && code.at(iPost + 1) == QLatin1Char('\n')) { + ++iPost; + ++postNewline; + } + } else if (c == QLatin1Char('\r')) { + if (iPost + 1 < code.size() && code.at(iPost + 1) == QLatin1Char('\n')) { + ++iPost; + ++postNewline; + } + } } ++iPost; - if (c == QLatin1Char('\n')) - break; - if (c == QLatin1Char('\r')) { - if (iPost < code.size() && code.at(iPost) == QLatin1Char('\n')) - ++iPost; + if (postNewline > 1) break; - } } + ElementRef commentEl; bool pre = true; auto iStart = ranges.starts.lowerBound(cLoc.begin()); @@ -653,6 +664,7 @@ void AstComments::collectComments(std::shared_ptr<Engine> engine, AST::Node *n, commentEl.size = n->lastSourceLocation().end() - n->firstSourceLocation().begin(); } } + Comment comment(code.mid(iPre, iPost - iPre), preNewline); if (commentEl.element.index() == 0 && std::get<0>(commentEl.element)) { CommentedElement &cEl = commentedElements[std::get<0>(commentEl.element)]; diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml index 8b181f607e..7166861184 100644 --- a/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml +++ b/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml @@ -54,6 +54,7 @@ Item { // Another orphan // More orphans + property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3] property bool something_computed: function (x) { const PI = 3, DAYS_PER_YEAR = 365.25; @@ -124,6 +125,7 @@ Item { } // Another orphan inside something_computed + return "foobar"; }() diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.qml index cb8865d94e..f558707a69 100644 --- a/tests/auto/qml/qmlformat/data/Example1.formatted.qml +++ b/tests/auto/qml/qmlformat/data/Example1.formatted.qml @@ -54,6 +54,7 @@ Item { // Another orphan // More orphans + property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3] property bool something_computed: function (x) { const PI = 3, DAYS_PER_YEAR = 365.25; @@ -124,6 +125,7 @@ Item { } // Another orphan inside something_computed + return "foobar"; }() diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml index ef964f6f60..46af0313e7 100644 --- a/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml +++ b/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml @@ -54,6 +54,7 @@ Item { // Another orphan // More orphans + property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3] property bool something_computed: function (x) { const PI = 3, DAYS_PER_YEAR = 365.25; @@ -124,6 +125,7 @@ Item { } // Another orphan inside something_computed + return "foobar"; }() diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted2.qml b/tests/auto/qml/qmlformat/data/Example1.formatted2.qml index aa662a3d5f..22cfd113b4 100644 --- a/tests/auto/qml/qmlformat/data/Example1.formatted2.qml +++ b/tests/auto/qml/qmlformat/data/Example1.formatted2.qml @@ -39,6 +39,7 @@ Item { // Another orphan // More orphans + property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3] property bool some_bool: false default property bool some_default_bool: 500 % 5 !== 0 // some_default_bool @@ -114,6 +115,7 @@ Item { } // Another orphan inside something_computed + return "foobar"; }() diff --git a/tests/auto/qml/qmlformat/data/blanklinesAfterComment.formatted.qml b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.formatted.qml new file mode 100644 index 0000000000..a7e70d70ea --- /dev/null +++ b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.formatted.qml @@ -0,0 +1,13 @@ +/* comment with spaces */ + +/* + another comment + */ +// + +// another comment /*test */ + +import QtQml + +QtObject { +} diff --git a/tests/auto/qml/qmlformat/data/blanklinesAfterComment.qml b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.qml new file mode 100644 index 0000000000..c99415aeed --- /dev/null +++ b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.qml @@ -0,0 +1,15 @@ +/* comment with spaces */ + +/* + another comment + */ +// + + +// another comment /*test */ + + + +import QtQml + +QtObject {} diff --git a/tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml b/tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml index b9bcc34e8c..ae4fd4a167 100644 --- a/tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml +++ b/tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml @@ -1 +1 @@ -/* 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 {
// 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
}
// Orphan comment
// Another orphan
// More orphans
property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
property bool some_bool: false
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
property bool something_computed: function (x) {
const PI = 3, DAYS_PER_YEAR = 365.25;
var x = 3 + 2;
x["bla"] = 50;
// This is an orphan inside something_computed
// Are these getting duplicated?
// 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 {
console.log("What else?");
}
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");
}
// Another orphan inside something_computed
return "foobar";
}()
signal say(string name, bool caps)
// This one to aFunc()
function aFunc() {
var x = 3;
return x;
}
x: 3 // Very cool
myFavouriteThings: [
// This is an orphan
// This is a cool text
Text {
},
// This is a cool rectangle
Rectangle {
}
]
// This comment is related to the property animation
PropertyAnimation on x {
id: foo2
x: 3
y: x + 3
}
Component.onCompleted: console.log("Foo!")
Text {
required property string batman
signal boo(int count, int times, real duration)
text: "Bla"
}
}
\ No newline at end of file +/* 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 {
// 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
}
// Orphan comment
// Another orphan
// More orphans
property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
property bool some_bool: false
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
property bool something_computed: function (x) {
const PI = 3, DAYS_PER_YEAR = 365.25;
var x = 3 + 2;
x["bla"] = 50;
// This is an orphan inside something_computed
// Are these getting duplicated?
// 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 {
console.log("What else?");
}
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");
}
// Another orphan inside something_computed
return "foobar";
}()
signal say(string name, bool caps)
// This one to aFunc()
function aFunc() {
var x = 3;
return x;
}
x: 3 // Very cool
myFavouriteThings: [
// This is an orphan
// This is a cool text
Text {
},
// This is a cool rectangle
Rectangle {
}
]
// This comment is related to the property animation
PropertyAnimation on x {
id: foo2
x: 3
y: x + 3
}
Component.onCompleted: console.log("Foo!")
Text {
required property string batman
signal boo(int count, int times, real duration)
text: "Bla"
}
}
\ No newline at end of file diff --git a/tests/auto/qml/qmlformat/tst_qmlformat.cpp b/tests/auto/qml/qmlformat/tst_qmlformat.cpp index e22919e305..58644566b3 100644 --- a/tests/auto/qml/qmlformat/tst_qmlformat.cpp +++ b/tests/auto/qml/qmlformat/tst_qmlformat.cpp @@ -324,6 +324,9 @@ void TestQmlformat::testFormat_data() QTest::newRow("arrowFunctionWithBinding") << "arrowFunctionWithBinding.qml" << "arrowFunctionWithBinding.formatted.qml" << QStringList{} << RunOption::OnCopy; + QTest::newRow("blanklinesAfterComment") + << "blanklinesAfterComment.qml" + << "blanklinesAfterComment.formatted.qml" << QStringList{} << RunOption::OnCopy; } void TestQmlformat::testFormat() diff --git a/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted.qml b/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted.qml index 0911f0e102..fe3403cef1 100644 --- a/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted.qml +++ b/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted.qml @@ -26,6 +26,7 @@ Item { // before zz zz - // after z + zz /*before (a b)*/(/* before a */ a * /* after a */ b * /*after b*/ c); // after (a * b * c) + if (y == 6) // if comment console.log("pippo"); a + b; // comment diff --git a/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted2.qml b/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted2.qml index 522cbbc777..9a5aba106e 100644 --- a/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted2.qml +++ b/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted2.qml @@ -26,6 +26,7 @@ Item { // before zz zz - // after z + zz /*before (a b)*/(/* before a */ a * /* after a */ b * /*after b*/ c); // after (a * b * c) + if (y == 6) // if comment console.log("pippo"); a + b; // comment |