aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qmlls
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qmlls')
-rw-r--r--tests/auto/qmlls/cli/tst_qmlls_cli.cpp2
-rw-r--r--tests/auto/qmlls/modules/data/highlighting/basic.qml11
-rw-r--r--tests/auto/qmlls/modules/data/highlighting/bigFile.qml351
-rw-r--r--tests/auto/qmlls/modules/data/renameUsages/RenameMe.qml5
-rw-r--r--tests/auto/qmlls/modules/data/renameUsages/RenameMe2.ui.qml5
-rw-r--r--tests/auto/qmlls/modules/data/renameUsages/main.qml6
-rw-r--r--tests/auto/qmlls/modules/tst_qmlls_modules.cpp390
-rw-r--r--tests/auto/qmlls/modules/tst_qmlls_modules.h9
-rw-r--r--tests/auto/qmlls/qmlls/tst_qmlls.cpp8
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/FileA.qml5
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/FileA2.qml5
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/FileB.qml5
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp54
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.h2
-rw-r--r--tests/auto/qmlls/utils/CMakeLists.txt30
-rw-r--r--tests/auto/qmlls/utils/data/highlights/Identifiers.qml37
-rw-r--r--tests/auto/qmlls/utils/data/highlights/bindings.qml12
-rw-r--r--tests/auto/qmlls/utils/data/highlights/comments.qml19
-rw-r--r--tests/auto/qmlls/utils/data/highlights/enums.qml11
-rw-r--r--tests/auto/qmlls/utils/data/highlights/identifiers.qml37
-rw-r--r--tests/auto/qmlls/utils/data/highlights/imports.qml9
-rw-r--r--tests/auto/qmlls/utils/data/highlights/literals.qml14
-rw-r--r--tests/auto/qmlls/utils/data/highlights/methodAndSignal.qml11
-rw-r--r--tests/auto/qmlls/utils/data/highlights/objectAndComponent.qml11
-rw-r--r--tests/auto/qmlls/utils/data/highlights/pragmas.qml10
-rw-r--r--tests/auto/qmlls/utils/data/highlights/properties.qml13
-rw-r--r--tests/auto/qmlls/utils/data/highlights/scriptExpressions.qml116
-rw-r--r--tests/auto/qmlls/utils/data/renaming/RenameMe.qml5
-rw-r--r--tests/auto/qmlls/utils/data/renaming/RenameMe2.ui.qml5
-rw-r--r--tests/auto/qmlls/utils/data/renaming/RenamedByQmldir.qml4
-rw-r--r--tests/auto/qmlls/utils/data/renaming/UnrelatedFile.qml0
-rw-r--r--tests/auto/qmlls/utils/data/renaming/main.qml7
-rw-r--r--tests/auto/qmlls/utils/data/renaming/qmldir6
-rw-r--r--tests/auto/qmlls/utils/tst_qmlls_documentationHints.cpp125
-rw-r--r--tests/auto/qmlls/utils/tst_qmlls_documentationHints.h24
-rw-r--r--tests/auto/qmlls/utils/tst_qmlls_highlighting.cpp650
-rw-r--r--tests/auto/qmlls/utils/tst_qmlls_highlighting.h37
-rw-r--r--tests/auto/qmlls/utils/tst_qmlls_utils.cpp976
-rw-r--r--tests/auto/qmlls/utils/tst_qmlls_utils.h3
39 files changed, 2531 insertions, 499 deletions
diff --git a/tests/auto/qmlls/cli/tst_qmlls_cli.cpp b/tests/auto/qmlls/cli/tst_qmlls_cli.cpp
index f871decec1..344ed48e64 100644
--- a/tests/auto/qmlls/cli/tst_qmlls_cli.cpp
+++ b/tests/auto/qmlls/cli/tst_qmlls_cli.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2024 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_qmlls_cli.h"
diff --git a/tests/auto/qmlls/modules/data/highlighting/basic.qml b/tests/auto/qmlls/modules/data/highlighting/basic.qml
new file mode 100644
index 0000000000..264f553b22
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/highlighting/basic.qml
@@ -0,0 +1,11 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ id: rootId
+ function a() {
+
+ }
+}
diff --git a/tests/auto/qmlls/modules/data/highlighting/bigFile.qml b/tests/auto/qmlls/modules/data/highlighting/bigFile.qml
new file mode 100644
index 0000000000..9832e8e98a
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/highlighting/bigFile.qml
@@ -0,0 +1,351 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ id: rootId
+ function f() {
+ let sum = 0, sum2 = 0;
+ for (let i = 1; i < 42; i = i + 2) {
+ sum = sum + i;
+ {
+ let sum = 42; // another unrelated sum
+ }
+ }
+ }
+
+ readonly property int helloProperty: 0
+ property int p2: 1
+
+ function withProperty() {
+ let sum = 0, sum2 = 0;
+ for (const i = 1; i < 42; i = i + 2) {
+ sum = sum + i;
+ helloProperty = helloProperty + sum - i * p2;
+ {
+ let helloProperty = "evil";
+ }
+ }
+ }
+ Item {
+ function f() {
+ return helloProperty + p2;
+ }
+ property string helloProperty
+ }
+ component IC: Item {
+ property var helloProperty
+ function f() {
+ return helloProperty + p2;
+ }
+ }
+ component NestedComponent: Item {
+ property NestedComponent2 inner: NestedComponent2 {}
+ property int p2
+ }
+ component NestedComponent2: Item {
+ property NestedComponent3 inner
+ property int p2
+ inner: NestedComponent3 {}
+ }
+ component NestedComponent3: Item {
+ property NestedComponent4 inner
+ property int p2
+ inner: NestedComponent4 {}
+ }
+ component NestedComponent4: Item {
+ property int helloProperty
+ property int p2
+ }
+ NestedComponent {
+ id: myNested
+ }
+ function nestedUsages() {
+ let x = myNested.inner.inner.inner.helloProperty + helloProperty;
+ let a = myNested.p2 + p2;
+ let b = myNested.inner.p2 + p2;
+ let c = myNested.inner.inner.p2 + p2;
+ let d = myNested.inner.inner.inner.p2 + p2;
+ }
+
+ function recursive(n: int): int {
+ if (n > 3)
+ return 1 + recursive(recursive(x - 1) + recursive(x - 2) - recursive(x - 3));
+ else
+ return recursive(0);
+ }
+
+ property int helloRecursive: recursive(42)
+ Rectangle {
+ function f() {
+ return rootId.recursive(123);
+ }
+ }
+
+ signal helloSignal
+
+ function callSignals() {
+ helloSignal();
+ if (false) {
+ helloSignal();
+ } else {
+ // helloSignal() // not a usage btw
+ if (true)
+ helloSignal();
+ }
+ }
+ function callSignals2() {
+ helloSignal();
+ if (false) {
+ widthChanged();
+ } else {
+ // helloSignal() // not a usage btw
+ if (true)
+ widthChanged();
+ rootId.widthChanged();
+ }
+ }
+ Item {
+ function callSignalsInChild() {
+ widthChanged();
+ rootId.widthChanged();
+ }
+ }
+
+ function myHelloHandler() {
+ let x = 32;
+ }
+ onHelloSignal: myHelloHandler
+
+ property int helloPropertyBinding
+ helloPropertyBinding: 123
+
+ property int checkHandlers
+ onCheckHandlersChanged: myHelloHandler
+ onChildrenChanged: myHelloHandler
+ function callChanged() {
+ checkHandlersChanged();
+ childrenChanged();
+ }
+ property int _: 48
+ property int ______42: 48
+ property int _123a: 48
+ on_Changed: myHelloHandler
+ on______42Changed: myHelloHandler
+ on_123AChanged: myHelloHandler
+ function weirdPropertynames() {
+ _Changed();
+ ______42Changed();
+ _123aChanged();
+ }
+
+ TapHandler {
+ onTapped: myHelloHandler
+ function f() {
+ tapped();
+ }
+ }
+
+ function anotherF() {
+ helloPropertyChanged();
+ }
+ onHelloPropertyChanged: myHelloHandler
+ // Type {}
+ function foo(mouse) {
+ }
+
+ MouseArea {
+ id: area1
+ onClicked: foo
+ property int insideMouseArea1
+ }
+
+ MouseArea {
+ id: area2
+ Connections {
+ function onClicked(mouse) {
+ area1.clicked();
+ area3.clicked();
+ }
+ }
+ property int insideMouseArea2
+
+ MouseArea {
+ id: area3
+ }
+ }
+
+ property Connections c: Connections {
+ target: area3
+ onClicked: function (mouse) {}
+ }
+ function useMouseAreas() {
+ area1.clicked();
+ area2.clicked();
+ area3.clicked();
+ }
+
+ function checkParameters(a: int, b: double, {
+ x,
+ y = {},
+ z = [x, y]
+ }) {
+ return a + b + c + x + y + z;
+ }
+
+ function deconstructingUsages(xxx) {
+ let {
+ a,
+ b
+ } = xxx;
+ let c = a + b;
+ }
+
+ function k() {
+ }
+
+ function mafik() {
+ var patron = 34;
+ const upperLimit = 42;
+ do {
+ ++patron;
+ if (patron < 2)
+ continue;
+ else
+ ++patron;
+ } while (patron < upperLimit)
+ switch (patron) {
+ case 1:
+ return 23;
+ default:
+ break;
+ }
+ try {
+ {}
+ } catch (error) {
+ {}
+ } finally {}
+ for (const a in [1, 2, 3]) {
+ throw 2;
+ }
+ }
+
+ enum Test {
+ LOG
+ }
+
+ readonly property int t: 34
+ signal tt
+ required property int k
+
+ signal kkk(string a)
+ signal yyy(string a)
+
+ function ttt() {
+ }
+
+ function createComplexExpression(...objects) {
+ // Create an object that holds some data
+ let data = {
+ a: 5,
+ b: 10,
+ c: 3
+ };
+
+ // Create a complex expression using the data object
+ let expression = ((data.a + data.b * data.c) / (data.a - data.b)) ** data.c;
+
+ return expression;
+ }
+
+ function set1() {
+ const array = [1, 2, 3, 4];
+ const [a, b] = [1, 2];
+ const [aa, , bb] = array;
+ const [aaa = 23, bbb] = array;
+ const [a1, b1, ...rest1] = array;
+ const [a2, , b2, ...rest2] = array;
+ const [a3, b3, ...{
+ pop,
+ push
+ }] = array;
+ const [a4, b4, ...[c, d]] = array;
+
+ const obj = {
+ _a: 1,
+ _b: 2
+ };
+ const {
+ a5,
+ b5
+ } = obj;
+ const {
+ a6: a_,
+ b6: b1_
+ } = obj;
+ const {
+ a7: a11 = 4,
+ b11 = 34,
+ c1: b111,
+ d1
+ } = obj;
+ let key = a;
+ const {
+ [key]: a___
+ } = obj;
+ }
+
+ function set2(s: int): int {
+ // declare first
+ let a, b, a1, b1, c, d, rest, pop, push;
+ const array = [1, 2, 3, 4];
+ [a, b] = array;
+ [a, , b] = array;
+ [a = aDefault, b] = array;
+ [a, b, ...rest] = array;
+ [a, , b, ...rest] = array;
+ [a, b, ...{
+ pop,
+ push
+ }] = array;
+ [a, b, ...[c, d]] = array;
+
+ const obj = {
+ _a: 1,
+ _b: 2
+ };
+ ({
+ a,
+ b
+ } = obj); // brackets are required
+ ({
+ a: a1,
+ b: b1
+ } = obj);
+
+ const complicatedObject = {
+ a: 1,
+ b: {
+ c: 2,
+ d: {
+ e: 3,
+ f: [4, 5, 6]
+ }
+ },
+ g: [7, 8, 9]
+ };
+
+ const {
+ patron,
+ b: {
+ mafik,
+ d: {
+ e,
+ f: [, secondF, ...restF]
+ }
+ },
+ g: [firstG, ...restG]
+ } = complicatedObject;
+ }
+}
diff --git a/tests/auto/qmlls/modules/data/renameUsages/RenameMe.qml b/tests/auto/qmlls/modules/data/renameUsages/RenameMe.qml
new file mode 100644
index 0000000000..7680c63f95
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/renameUsages/RenameMe.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property int helloProperty
+} \ No newline at end of file
diff --git a/tests/auto/qmlls/modules/data/renameUsages/RenameMe2.ui.qml b/tests/auto/qmlls/modules/data/renameUsages/RenameMe2.ui.qml
new file mode 100644
index 0000000000..b9197def63
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/renameUsages/RenameMe2.ui.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property int helloProperty
+}
diff --git a/tests/auto/qmlls/modules/data/renameUsages/main.qml b/tests/auto/qmlls/modules/data/renameUsages/main.qml
new file mode 100644
index 0000000000..b59508f92f
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/renameUsages/main.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ RenameMe {}
+ RenameMe2 {}
+}
diff --git a/tests/auto/qmlls/modules/tst_qmlls_modules.cpp b/tests/auto/qmlls/modules/tst_qmlls_modules.cpp
index 764a8f65cd..9a5acae81b 100644
--- a/tests/auto/qmlls/modules/tst_qmlls_modules.cpp
+++ b/tests/auto/qmlls/modules/tst_qmlls_modules.cpp
@@ -3,6 +3,7 @@
#include "tst_qmlls_modules.h"
#include "QtQmlLS/private/qqmllsutils_p.h"
+#include "QtQmlLS/private/qqmlsemantictokens_p.h"
#include <algorithm>
#include <memory>
#include <optional>
@@ -372,7 +373,7 @@ void tst_qmlls_modules::buildDir()
didChange.textDocument.uri = *uri;
didChange.textDocument.version = 2;
- // change the file content to force qqmlcodemodel to recreate a new DomItem
+ // change the file content to force qqml— to recreate a new DomItem
// if it reuses the old DomItem then it will not know about the added build directory
TextDocumentContentChangeEvent change;
change.range = Range{ Position{ 4, 0 }, Position{ 4, 0 } };
@@ -870,11 +871,17 @@ void tst_qmlls_modules::renameUsages_data()
QVERIFY(file.open(QIODeviceBase::ReadOnly));
jsIdentifierUsagesContent = QString::fromUtf8(file.readAll());
}
+ QString renamingContent;
+ {
+ QFile file(testFile("renameUsages/main.qml").toUtf8());
+ QVERIFY(file.open(QIODeviceBase::ReadOnly));
+ renamingContent = QString::fromUtf8(file.readAll());
+ }
// TODO: create workspace edit for the tests
QLspSpecification::WorkspaceEdit sumRenames{
std::nullopt, // TODO
- QList<TextDocumentEdit>{
+ QList<QLspSpecification::WorkspaceEdit::DocumentChange>{
TextDocumentEdit{
OptionalVersionedTextDocumentIdentifier{ { jsIdentifierUsagesUri } },
{
@@ -905,6 +912,83 @@ void tst_qmlls_modules::renameUsages_data()
"Invalid EcmaScript identifier!",
std::nullopt,
};
+
+ const QString renameUsagesPath = u"renameUsages/main.qml"_s;
+ const QByteArray renameUsagesUri = testFileUrl("renameUsages/main.qml").toEncoded();
+ const QByteArray renameMeUri = testFileUrl("renameUsages/RenameMe.qml").toEncoded();
+ const QByteArray renameMe2Uri = testFileUrl("renameUsages/RenameMe2.ui.qml").toEncoded();
+
+ const QByteArray newFileUri = testFileUrl("renameUsages/HelloWorld.qml").toEncoded();
+ const QByteArray newFileUri2 = testFileUrl("renameUsages/HelloWorld.ui.qml").toEncoded();
+
+ {
+
+ const QLspSpecification::WorkspaceEdit qmlComponentRename{
+ std::nullopt,
+ QList<QLspSpecification::WorkspaceEdit::DocumentChange>{
+ TextDocumentEdit{
+ OptionalVersionedTextDocumentIdentifier{ { renameUsagesUri } },
+ {
+ TextEdit{ rangeFrom(renamingContent, 4, 5,
+ strlen("RenameMe")),
+ "HelloWorld" },
+ } },
+ RenameFile{ "rename", renameMeUri, newFileUri } }
+ };
+
+ QTest::addRow("renameQmlComponent")
+ << renameUsagesPath << 4 << 8 << u"HelloWorld"_s << qmlComponentRename << noError;
+ }
+
+ {
+ QLspSpecification::WorkspaceEdit qmlComponentRename{
+ std::nullopt,
+ QList<QLspSpecification::WorkspaceEdit::DocumentChange>{
+ TextDocumentEdit{
+ OptionalVersionedTextDocumentIdentifier{ { renameUsagesUri } },
+ {
+ TextEdit{ rangeFrom(renamingContent, 5, 5,
+ strlen("RenameMe2")),
+ "HelloWorld" },
+ } },
+ RenameFile{ "rename", renameMe2Uri, newFileUri2 } }
+ };
+
+ QTest::addRow("renameUiQmlComponent")
+ << renameUsagesPath << 5 << 8 << u"HelloWorld"_s << qmlComponentRename << noError;
+ }
+}
+
+void tst_qmlls_modules::compareQTextDocumentEdit(const TextDocumentEdit &a,
+ const TextDocumentEdit &b)
+{
+
+ QCOMPARE(a.textDocument.uri, b.textDocument.uri);
+ QVERIFY(a.textDocument.uri.startsWith("file://"));
+ QCOMPARE(a.textDocument.version, b.textDocument.version);
+ QCOMPARE(a.edits.size(), b.edits.size());
+
+ for (qsizetype j = 0; j < a.edits.size(); ++j) {
+ std::visit(
+ [](auto &&textEdit, auto &&expectedTextEdit) {
+ using U = std::decay_t<decltype(textEdit)>;
+ using V = std::decay_t<decltype(expectedTextEdit)>;
+
+ if constexpr (std::conjunction_v<std::is_same<U, V>,
+ std::is_same<U, TextEdit>>) {
+ QCOMPARE(textEdit.range.start.line, expectedTextEdit.range.start.line);
+ QCOMPARE(textEdit.range.start.character,
+ expectedTextEdit.range.start.character);
+ QCOMPARE(textEdit.range.end.line, expectedTextEdit.range.end.line);
+ QCOMPARE(textEdit.range.end.character,
+ expectedTextEdit.range.end.character);
+ QCOMPARE(textEdit.newText, expectedTextEdit.newText);
+ } else {
+ QFAIL("Comparison not implemented");
+ }
+ },
+ a.edits[j], b.edits[j]);
+ }
}
void tst_qmlls_modules::renameUsages()
@@ -933,7 +1017,7 @@ void tst_qmlls_modules::renameUsages()
auto clean = [didFinish]() { *didFinish = true; };
m_protocol->requestRename(
params,
- [&](auto res) {
+ [&](auto &&res) {
QScopeGuard cleanup(clean);
auto *result = std::get_if<QLspSpecification::WorkspaceEdit>(&res);
@@ -944,66 +1028,40 @@ void tst_qmlls_modules::renameUsages()
QCOMPARE(result->documentChanges.has_value(),
expectedEdit.documentChanges.has_value());
- std::visit(
- [&expectedError](auto &&documentChanges, auto &&expectedDocumentChanges) {
- if (!expectedError.message.isEmpty())
- QVERIFY2(false, "No expected error was thrown.");
-
- QCOMPARE(documentChanges.size(), expectedDocumentChanges.size());
- using U = std::decay_t<decltype(documentChanges)>;
- using V = std::decay_t<decltype(expectedDocumentChanges)>;
-
- if constexpr (std::conjunction_v<
- std::is_same<U, V>,
- std::is_same<U, QList<TextDocumentEdit>>>) {
- for (qsizetype i = 0; i < expectedDocumentChanges.size(); ++i) {
- QCOMPARE(documentChanges[i].textDocument.uri,
- expectedDocumentChanges[i].textDocument.uri);
- QVERIFY(documentChanges[i].textDocument.uri.startsWith(
- "file://"));
- QCOMPARE(documentChanges[i].textDocument.version,
- expectedDocumentChanges[i].textDocument.version);
- QCOMPARE(documentChanges[i].edits.size(),
- expectedDocumentChanges[i].edits.size());
-
- for (qsizetype j = 0; j < documentChanges[i].edits.size();
- ++j) {
- std::visit(
- [](auto &&textEdit, auto &&expectedTextEdit) {
- using U = std::decay_t<decltype(textEdit)>;
- using V = std::decay_t<
- decltype(expectedTextEdit)>;
-
- if constexpr (std::conjunction_v<
- std::is_same<U, V>,
- std::is_same<U,
- TextEdit>>) {
- QCOMPARE(textEdit.range.start.line,
- expectedTextEdit.range.start.line);
- QCOMPARE(textEdit.range.start.character,
- expectedTextEdit.range.start
- .character);
- QCOMPARE(textEdit.range.end.line,
- expectedTextEdit.range.end.line);
- QCOMPARE(textEdit.range.end.character,
- expectedTextEdit.range.end
- .character);
- QCOMPARE(textEdit.newText,
- expectedTextEdit.newText);
- } else {
- QFAIL("Comparison not implemented");
- }
- },
- documentChanges[i].edits[j],
- expectedDocumentChanges[i].edits[j]);
- }
- }
+ auto &documentChanges = *result->documentChanges;
+ auto &expectedDocumentChanges = *expectedEdit.documentChanges;
+
+ if (!expectedError.message.isEmpty())
+ QVERIFY2(false, "No expected error was thrown.");
+
+ QCOMPARE(documentChanges.size(), expectedDocumentChanges.size());
+
+ for (qsizetype i = 0; i < expectedDocumentChanges.size(); ++i) {
+ QCOMPARE(documentChanges[i].index(), expectedDocumentChanges[i].index());
+ if (std::holds_alternative<TextDocumentEdit>(documentChanges[i])) {
+ compareQTextDocumentEdit(
+ std::get<TextDocumentEdit>(documentChanges[i]),
+ std::get<TextDocumentEdit>(expectedDocumentChanges[i]));
+ } else if (std::holds_alternative<RenameFile>(documentChanges[i])) {
+ const auto &actual = std::get<RenameFile>(documentChanges[i]);
+ const auto &expected = std::get<RenameFile>(expectedDocumentChanges[i]);
+
+ QCOMPARE(actual.kind, expected.kind);
+ QCOMPARE(expected.kind, "rename");
+ QCOMPARE(actual.oldUri, expected.oldUri);
+ QCOMPARE(actual.newUri, expected.newUri);
+ QCOMPARE(actual.options.has_value(), expected.options.has_value());
+ if (expected.options.has_value()) {
+ QCOMPARE(actual.options->overwrite, expected.options->overwrite);
+ QCOMPARE(actual.options->ignoreIfExists,
+ expected.options->ignoreIfExists);
+ }
+ QCOMPARE(actual.annotationId, expected.annotationId);
- } else {
- QFAIL("Comparison not implemented");
- }
- },
- result->documentChanges.value(), expectedEdit.documentChanges.value());
+ } else {
+ QFAIL("TODO: implement me!");
+ }
+ }
},
[clean, &expectedError](const ResponseError &err) {
QScopeGuard cleanup(clean);
@@ -1487,12 +1545,12 @@ void tst_qmlls_modules::quickFixes()
QVERIFY(codeAction.edit);
QVERIFY(codeAction.edit->documentChanges);
- QVERIFY(std::holds_alternative<QList<TextDocumentEdit>>(*codeAction.edit->documentChanges));
- auto edits = std::get<QList<TextDocumentEdit>>(*codeAction.edit->documentChanges);
+ const auto &edits = *codeAction.edit->documentChanges;
QCOMPARE(edits.size(), 1);
- QCOMPARE(edits.front().edits.size(), 1);
- QVERIFY(std::holds_alternative<TextEdit>(edits.front().edits.front()));
- auto textEdit = std::get<TextEdit>(edits.front().edits.front());
+ const auto& firstEdit = std::get<TextDocumentEdit>(edits.front());
+ QCOMPARE(firstEdit.edits.size(), 1);
+ QVERIFY(std::holds_alternative<TextEdit>(firstEdit.edits.front()));
+ auto textEdit = std::get<TextEdit>(firstEdit.edits.front());
// make sure that the quick fix does something
QCOMPARE(textEdit.newText, replacementText);
@@ -1504,4 +1562,202 @@ void tst_qmlls_modules::quickFixes()
QTRY_VERIFY_WITH_TIMEOUT(codeActionOk, 5000);
}
+static QQmlJS::Dom::DomItem fileObject(const QString &filePath)
+{
+ QFile f(filePath);
+ QQmlJS::Dom::DomItem file;
+ if (!f.open(QIODevice::ReadOnly))
+ return file;
+ QString code = f.readAll();
+ QQmlJS::Dom::DomCreationOptions options;
+ options.setFlag(QQmlJS::Dom::DomCreationOption::WithScriptExpressions);
+ options.setFlag(QQmlJS::Dom::DomCreationOption::WithSemanticAnalysis);
+ options.setFlag(QQmlJS::Dom::DomCreationOption::WithRecovery);
+
+ QStringList dirs = {QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath)};
+ auto envPtr = QQmlJS::Dom::DomEnvironment::create(dirs,
+ QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
+ | QQmlJS::Dom::DomEnvironment::Option::NoDependencies, options);
+ envPtr->loadBuiltins();
+ envPtr->loadFile(QQmlJS::Dom::FileToLoad::fromMemory(envPtr, filePath, code),
+ [&file](QQmlJS::Dom::Path, const QQmlJS::Dom::DomItem &, const QQmlJS::Dom::DomItem &newIt) {
+ file = newIt.fileObject();
+ });
+ envPtr->loadPendingDependencies();
+ return file;
+};
+
+void tst_qmlls_modules::semanticHighlightingFull_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addRow("bigfile") << u"highlighting/bigFile.qml"_s;
+}
+
+void tst_qmlls_modules::semanticHighlightingFull()
+{
+ QFETCH(QString, filePath);
+ const auto item = fileObject(testFile(filePath));
+ Highlights highlights;
+ const auto expectedData = highlights.collectTokens(item, std::nullopt);
+
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+ QLspSpecification::SemanticTokensParams params;
+ params.textDocument.uri = *uri;
+ std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
+ const auto cleanup = [didFinish]() { *didFinish = true; };
+
+ auto &&responseHandler = [&](auto res) {
+ QScopeGuard callAtExit(cleanup);
+ const auto *const result = std::get_if<QLspSpecification::SemanticTokens>(&res);
+ QVERIFY(result);
+ QList<int> data = result->data;
+ QCOMPARE(data.size(), expectedData.size());
+ QCOMPARE(data, expectedData);
+ };
+
+ auto &&errorHandler = [&](auto &error) {
+ QScopeGuard callAtExit(cleanup);
+ ProtocolBase::defaultResponseErrorHandler(error);
+ QVERIFY2(false, "error occurred on full semantic tokens");
+ };
+
+ m_protocol->requestSemanticTokens(params, std::move(responseHandler), std::move(errorHandler));
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 10000);
+}
+
+void tst_qmlls_modules::semanticHighlightingRange_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<QLspSpecification::Range>("range");
+ QTest::addRow("bigfile") << u"highlighting/bigFile.qml"_s
+ << QLspSpecification::Range{ { 6, 0 }, { 15, 0 } };
+}
+
+void tst_qmlls_modules::semanticHighlightingRange()
+{
+ QFETCH(QString, filePath);
+ QFETCH(QLspSpecification::Range, range);
+
+ const auto item = fileObject(testFile(filePath));
+ Highlights highlights;
+ const auto qmlFile = item.as<QQmlJS::Dom::QmlFile>();
+ const auto code = qmlFile->code();
+ const int startOffset = int(QQmlLSUtils::textOffsetFrom(code, range.start.line, range.end.character));
+ const int endOffset = int(QQmlLSUtils::textOffsetFrom(code, range.end.line, range.end.character));
+ const auto expectedData = highlights.collectTokens(item, HighlightsRange{startOffset, endOffset});
+
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+ QLspSpecification::SemanticTokensRangeParams params;
+ params.textDocument.uri = *uri;
+ params.range = range;
+
+ std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
+ const auto cleanup = [didFinish]() { *didFinish = true; };
+
+ auto &&responseHandler = [&](auto res) {
+ QScopeGuard callAtExit(cleanup);
+ const auto *const result = std::get_if<QLspSpecification::SemanticTokens>(&res);
+ QVERIFY(result);
+ QList<int> data = result->data;
+ QCOMPARE(data.size(), expectedData.size());
+ QCOMPARE(data, expectedData);
+ };
+
+ auto &&errorHandler = [&](auto &error) {
+ QScopeGuard callAtExit(cleanup);
+ ProtocolBase::defaultResponseErrorHandler(error);
+ QVERIFY2(false, "error occurred on full semantic tokens");
+ };
+
+ m_protocol->requestSemanticTokensRange(params, std::move(responseHandler),
+ std::move(errorHandler));
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 10000);
+}
+
+void tst_qmlls_modules::semanticHighlightingDelta_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addRow("basicDelta") << u"highlighting/basic.qml"_s;
+}
+
+void tst_qmlls_modules::semanticHighlightingDelta()
+{
+ QSKIP("This test should be skipped until QTBUG-124870 is fixed");
+ QFETCH(QString, filePath);
+ QFETCH(QString, deltaFilePath);
+
+ const auto fileItem = fileObject(testFile(filePath));
+ const auto deltaFileItem = fileObject(testFile(deltaFilePath));
+ Highlights highlights;
+ auto fullDocumentSemanticTokensData = highlights.collectTokens(fileItem, std::nullopt);
+ auto editedDocumentSemanticTokensData = highlights.collectTokens(deltaFileItem, std::nullopt);
+ const auto expectedEdits = HighlightingUtils::computeDiff(fullDocumentSemanticTokensData, editedDocumentSemanticTokensData);
+
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+ const auto deltaUri = openFile(deltaFilePath);
+ QVERIFY(deltaUri);
+
+ std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
+ const auto cleanup = [didFinish]() { *didFinish = true; };
+
+ QLspSpecification::SemanticTokensDeltaParams params;
+ QLspSpecification::Responses::SemanticTokensDeltaResultType result;
+
+ auto &&errorHandler = [&](auto &error) {
+ QScopeGuard callAtExit(cleanup);
+ ProtocolBase::defaultResponseErrorHandler(error);
+ QVERIFY2(false, "error occurred on semantic tokens/delta");
+ };
+
+ QLspSpecification::SemanticTokensParams fullParams;
+ fullParams.textDocument.uri = *uri;
+ m_protocol->requestSemanticTokens(fullParams,
+ [&](auto res) {
+ QScopeGuard callAtExit(cleanup);
+ if (auto r = std::get_if<QLspSpecification::SemanticTokens>(&res)) {
+ params.previousResultId = r->resultId.value();
+ fullDocumentSemanticTokensData = r->data;
+ }
+ }, errorHandler);
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 10000);
+
+ // Change the file
+ DidChangeTextDocumentParams didChange;
+ didChange.textDocument.uri = *uri;
+ didChange.textDocument.version = 2;
+
+ TextDocumentContentChangeEvent change;
+ change.range = Range{ Position{ 8, 4 }, Position{ 8, 4 } };
+ change.text = "const Patron = 42";
+
+ didChange.contentChanges.append(change);
+ m_protocol->notifyDidChangeTextDocument(didChange);
+
+ *didFinish = false;
+ params.textDocument.uri = *uri;
+ m_protocol->requestSemanticTokensDelta(params,
+ [&](auto res) {
+ QScopeGuard callAtExit(cleanup);
+ result = res;
+ }, std::move(errorHandler));
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 10000);
+
+ if (const auto *const delta = std::get_if<QLspSpecification::SemanticTokensDelta>(&result)) {
+ QVERIFY(delta);
+ const auto data = delta->edits.front().data;
+ const auto start = delta->edits.front().start;
+ const auto deleteCount = delta->edits.front().deleteCount;
+ QCOMPARE(start, expectedEdits.front().start);
+ QCOMPARE(deleteCount, expectedEdits.front().deleteCount);
+ QCOMPARE(data, expectedEdits.front().data);
+ } else {
+ const auto *const full = std::get_if<QLspSpecification::SemanticTokens>(&result);
+ QVERIFY(full);
+ QCOMPARE(full->data, expectedEdits.front().data);
+ }
+}
+
QTEST_MAIN(tst_qmlls_modules)
diff --git a/tests/auto/qmlls/modules/tst_qmlls_modules.h b/tests/auto/qmlls/modules/tst_qmlls_modules.h
index 352af1d928..d7b601cf5a 100644
--- a/tests/auto/qmlls/modules/tst_qmlls_modules.h
+++ b/tests/auto/qmlls/modules/tst_qmlls_modules.h
@@ -37,6 +37,8 @@ public:
std::optional<QByteArray> openFile(const QString &uri);
std::optional<QByteArray> openFileFromAbsolutePath(const QString &uri);
void ignoreDiagnostics();
+ void compareQTextDocumentEdit(const QLspSpecification::TextDocumentEdit &a,
+ const QLspSpecification::TextDocumentEdit &b);
private slots:
void init() final;
void cleanup();
@@ -67,7 +69,12 @@ private slots:
void hover_data();
void hover();
void checkQuickSnippets();
-
+ void semanticHighlightingFull_data();
+ void semanticHighlightingFull();
+ void semanticHighlightingRange_data();
+ void semanticHighlightingRange();
+ void semanticHighlightingDelta_data();
+ void semanticHighlightingDelta();
private:
QProcess m_server;
std::unique_ptr<QLanguageServerProtocol> m_protocol;
diff --git a/tests/auto/qmlls/qmlls/tst_qmlls.cpp b/tests/auto/qmlls/qmlls/tst_qmlls.cpp
index 4507a4b8b9..9e057992c4 100644
--- a/tests/auto/qmlls/qmlls/tst_qmlls.cpp
+++ b/tests/auto/qmlls/qmlls/tst_qmlls.cpp
@@ -219,12 +219,12 @@ void tst_Qmlls::didOpenTextDocument()
WorkspaceEdit edit = action.edit.value();
QVERIFY(edit.documentChanges.has_value());
- auto docChangeVariant = edit.documentChanges.value();
- QVERIFY(std::holds_alternative<QList<TextDocumentEdit>>(docChangeVariant));
- auto documentChanges = std::get<QList<TextDocumentEdit>>(docChangeVariant);
+ auto documentChanges = edit.documentChanges.value();
QCOMPARE(documentChanges.size(), 1);
- TextDocumentEdit textDocEdit = documentChanges.first();
+ QVERIFY(std::holds_alternative<TextDocumentEdit>(documentChanges.first()));
+ TextDocumentEdit textDocEdit
+ = std::get<TextDocumentEdit>(documentChanges.first());
QCOMPARE(textDocEdit.textDocument.uri, textDocument.uri);
QVERIFY(std::holds_alternative<int>(textDocEdit.textDocument.version));
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/FileA.qml b/tests/auto/qmlls/qqmlcodemodel/data/FileA.qml
new file mode 100644
index 0000000000..5560aee727
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/FileA.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+
+}
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/FileA2.qml b/tests/auto/qmlls/qqmlcodemodel/data/FileA2.qml
new file mode 100644
index 0000000000..7680c63f95
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/FileA2.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property int helloProperty
+} \ No newline at end of file
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/FileB.qml b/tests/auto/qmlls/qqmlcodemodel/data/FileB.qml
new file mode 100644
index 0000000000..03cd2f9fb3
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/FileB.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+FileA {
+ property int helloPropertyInB
+}
diff --git a/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp b/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp
index f56839d99a..a3293769e5 100644
--- a/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp
+++ b/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp
@@ -128,4 +128,58 @@ void tst_qmlls_qqmlcodemodel::fileNamesToWatch()
QVERIFY(fileNames.contains(u"helloworld.h"_s));
}
+QString tst_qmlls_qqmlcodemodel::readFile(const QString &filename) const
+{
+ QFile f(testFile(filename));
+ if (!f.open(QFile::ReadOnly)) {
+ QTest::qFail("Can't read test file", __FILE__, __LINE__);
+ return {};
+ }
+ return f.readAll();
+}
+
+void tst_qmlls_qqmlcodemodel::openFiles()
+{
+ QmlLsp::QQmlCodeModel model;
+
+ const QByteArray fileAUrl = testFileUrl(u"FileA.qml"_s).toEncoded();
+ const QString fileAPath = testFile(u"FileA.qml"_s);
+
+ // open file A
+ model.newOpenFile(fileAUrl, 0, readFile(u"FileA.qml"_s));
+
+ QTRY_VERIFY_WITH_TIMEOUT(model.validEnv().field(Fields::qmlFileWithPath).key(fileAPath), 3000);
+
+ {
+ const DomItem fileAComponents = model.validEnv()
+ .field(Fields::qmlFileWithPath)
+ .key(fileAPath)
+ .field(Fields::currentItem)
+ .field(Fields::components);
+ // if there is no component then the lazy qml file was not loaded correctly.
+ QCOMPARE(fileAComponents.size(), 1);
+ }
+
+ model.newDocForOpenFile(fileAUrl, 1, readFile(u"FileA2.qml"_s));
+
+ {
+ const DomItem fileAComponents = model.validEnv()
+ .field(Fields::qmlFileWithPath)
+ .key(fileAPath)
+ .field(Fields::currentItem)
+ .field(Fields::components);
+ // if there is no component then the lazy qml file was not loaded correctly.
+ QCOMPARE(fileAComponents.size(), 1);
+
+ // also check if the property is there
+ const DomItem properties = fileAComponents.key(QString())
+ .index(0)
+ .field(Fields::objects)
+ .index(0)
+ .field(Fields::propertyDefs);
+ QVERIFY(properties);
+ QVERIFY(properties.key(u"helloProperty"_s));
+ }
+}
+
QTEST_MAIN(tst_qmlls_qqmlcodemodel)
diff --git a/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.h b/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.h
index 45c88d908e..a913f4bd19 100644
--- a/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.h
+++ b/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.h
@@ -23,6 +23,7 @@ class tst_qmlls_qqmlcodemodel : public QQmlDataTest
Q_OBJECT
public:
tst_qmlls_qqmlcodemodel();
+ QString readFile(const QString &filename) const;
private slots:
void buildPathsForFileUrl_data();
@@ -30,6 +31,7 @@ private slots:
void fileNamesToWatch();
void findFilePathsFromFileNames_data();
void findFilePathsFromFileNames();
+ void openFiles();
};
#endif // TST_QMLLS_QQMLCODEMODEL_H
diff --git a/tests/auto/qmlls/utils/CMakeLists.txt b/tests/auto/qmlls/utils/CMakeLists.txt
index a8a4e9f0c4..ba81707b30 100644
--- a/tests/auto/qmlls/utils/CMakeLists.txt
+++ b/tests/auto/qmlls/utils/CMakeLists.txt
@@ -27,6 +27,36 @@ qt_internal_add_test(tst_qmlls_utils
TESTDATA ${test_data}
)
+qt_internal_add_test(tst_qmlls_highlighting
+ SOURCES
+ tst_qmlls_highlighting.cpp
+ DEFINES
+ QT_QMLLS_HIGHLIGHTS_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
+ LIBRARIES
+ Qt::Core
+ Qt::QmlDomPrivate
+ Qt::LanguageServerPrivate
+ Qt::Test
+ Qt::QuickTestUtilsPrivate
+ Qt::QmlLSPrivate
+ TESTDATA ${test_data}
+)
+
+qt_internal_add_test(tst_qmlls_documentationHints
+ SOURCES
+ tst_qmlls_documentationHints.cpp
+ DEFINES
+ QT_QMLLS_DOCUMENTATION_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
+ LIBRARIES
+ Qt::Core
+ Qt::QmlDomPrivate
+ Qt::LanguageServerPrivate
+ Qt::Test
+ Qt::QuickTestUtilsPrivate
+ Qt::QmlLSPrivate
+ TESTDATA ${test_data}
+)
+
qt_internal_extend_target(tst_qmlls_utils CONDITION ANDROID OR IOS
DEFINES
QT_QMLLS_UTILS_DATADIR=":/domdata"
diff --git a/tests/auto/qmlls/utils/data/highlights/Identifiers.qml b/tests/auto/qmlls/utils/data/highlights/Identifiers.qml
new file mode 100644
index 0000000000..7725b6d5e4
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/Identifiers.qml
@@ -0,0 +1,37 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ readonly property int test: 34
+ signal pressed()
+ function f() {
+ let sum = 0, sum2 = 0
+ for(let i = 1; i < 42; i = i + 2) {
+ sum = test + i
+ {
+ let sum = 42; // another unrelated sum
+ }
+ }
+ // signal and property changed
+ testChanged();
+ pressed();
+ }
+
+ // attached
+ Keys.onPressed: {
+ }
+
+ // propertychanged handler
+ onTestChanged: {
+ f(); // method identifier
+ }
+
+ // signal handler
+ onPressed: {}
+
+ enum K { Plus}
+ property int tt: Identifiers.Plus // component and enum value
+
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/bindings.qml b/tests/auto/qmlls/utils/data/highlights/bindings.qml
new file mode 100644
index 0000000000..ac1592e778
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/bindings.qml
@@ -0,0 +1,12 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ property int x: 45
+
+ Behavior on width {}
+
+ x: width
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/comments.qml b/tests/auto/qmlls/utils/data/highlights/comments.qml
new file mode 100644
index 0000000000..351aaee36c
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/comments.qml
@@ -0,0 +1,19 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+import QtQuick
+Item {
+/*
+ multiline comment
+*/
+
+/* single line comment */
+// another
+
+ function inc() {
+ // in
+
+ /*
+ inside js
+ */
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/enums.qml b/tests/auto/qmlls/utils/data/highlights/enums.qml
new file mode 100644
index 0000000000..22183bf37f
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/enums.qml
@@ -0,0 +1,11 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ enum Osc {
+ Sin,
+ Saw = 1
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/identifiers.qml b/tests/auto/qmlls/utils/data/highlights/identifiers.qml
new file mode 100644
index 0000000000..7725b6d5e4
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/identifiers.qml
@@ -0,0 +1,37 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ readonly property int test: 34
+ signal pressed()
+ function f() {
+ let sum = 0, sum2 = 0
+ for(let i = 1; i < 42; i = i + 2) {
+ sum = test + i
+ {
+ let sum = 42; // another unrelated sum
+ }
+ }
+ // signal and property changed
+ testChanged();
+ pressed();
+ }
+
+ // attached
+ Keys.onPressed: {
+ }
+
+ // propertychanged handler
+ onTestChanged: {
+ f(); // method identifier
+ }
+
+ // signal handler
+ onPressed: {}
+
+ enum K { Plus}
+ property int tt: Identifiers.Plus // component and enum value
+
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/imports.qml b/tests/auto/qmlls/utils/data/highlights/imports.qml
new file mode 100644
index 0000000000..1e69077070
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/imports.qml
@@ -0,0 +1,9 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQml 2.15
+import "X" as Patron
+
+Item {
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/literals.qml b/tests/auto/qmlls/utils/data/highlights/literals.qml
new file mode 100644
index 0000000000..520ed5d2ef
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/literals.qml
@@ -0,0 +1,14 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ property int a: 123
+ property string b: "single"
+ property string c: "multi
+ line string";
+ property bool d: true
+ property var e: null
+
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/methodAndSignal.qml b/tests/auto/qmlls/utils/data/highlights/methodAndSignal.qml
new file mode 100644
index 0000000000..4e8319f049
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/methodAndSignal.qml
@@ -0,0 +1,11 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ signal p()
+ signal q(int a)
+ signal r(a: int)
+ function a(b: int) : int {}
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/objectAndComponent.qml b/tests/auto/qmlls/utils/data/highlights/objectAndComponent.qml
new file mode 100644
index 0000000000..9165e4b1b5
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/objectAndComponent.qml
@@ -0,0 +1,11 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ component Patron: Item {}
+ Item {
+ id: inner
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/pragmas.qml b/tests/auto/qmlls/utils/data/highlights/pragmas.qml
new file mode 100644
index 0000000000..cf99c93584
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/pragmas.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+pragma Singleton
+pragma FunctionSignatureBehavior: Enforced
+pragma ValueTypeBehavior: Copy,Addressable
+
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qmlls/utils/data/highlights/properties.qml b/tests/auto/qmlls/utils/data/highlights/properties.qml
new file mode 100644
index 0000000000..bde60915ca
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/properties.qml
@@ -0,0 +1,13 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ Item {
+ property int k
+ readonly property int kk
+ required property int kkk
+ default property int kkkk
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/scriptExpressions.qml b/tests/auto/qmlls/utils/data/highlights/scriptExpressions.qml
new file mode 100644
index 0000000000..ee0b4ff5f8
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/scriptExpressions.qml
@@ -0,0 +1,116 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function k() {
+ }
+
+ function mafik() {
+ var patron = 34;
+ const upperLimit = 42;
+ do {
+ ++patron;
+ if (patron < 2)
+ continue;
+ else
+ ++patron;
+ } while (patron < upperLimit)
+ switch (patron) {
+ case 1:
+ return 23;
+ default:
+ break;
+ }
+ try {
+ {}
+ } catch (error) {
+ {}
+ } finally {}
+ for (const a in [1, 2, 3]) {
+ throw 2;
+ }
+ }
+
+ enum Test {
+ LOG
+ }
+
+ readonly property int t: 34
+ signal tt
+ required property int k
+
+ signal kkk(string a)
+ signal yyy(a: string)
+
+ function ttt() {
+
+ }
+
+function createComplexExpression(...objects) {
+ // Create an object that holds some data
+ let data = {
+ a: 5,
+ b: 10,
+ c: 3
+ };
+
+ // Create a complex expression using the data object
+ let expression = ((data.a + data.b * data.c) / (data.a - data.b)) ** data.c;
+
+ return expression;
+}
+
+ function set1() {
+ const array = [1,2,3,4];
+ const [a, b] = [1,2];
+ const [aa, , bb] = array;
+ const [aaa = 23, bbb] = array;
+ const [a1, b1, ...rest1] = array;
+ const [a2, , b2, ...rest2] = array;
+ const [a3, b3, ...{ pop, push }] = array;
+ const [a4, b4, ...[c, d]] = array;
+
+ const obj = {_a:1,_b:2};
+ const { a5, b5 } = obj;
+ const { a6: a_, b6: b1_ } = obj;
+ const { a7: a11 = 4, b11 = 34, c1: b111, d1 } = obj;
+ let key = a;
+ const { [key]: a___ } = obj;
+ }
+
+ function set2(s : int) : int {
+ // declare first
+ let a, b, a1, b1, c, d, rest, pop, push;
+ const array = [1,2,3,4];
+ [a, b] = array;
+ [a, , b] = array;
+ [a = aDefault, b] = array;
+ [a, b, ...rest] = array;
+ [a, , b, ...rest] = array;
+ [a, b, ...{ pop, push }] = array;
+ [a, b, ...[c, d]] = array;
+
+ const obj = {_a:1,_b:2};
+ ({ a, b } = obj); // brackets are required
+ ({ a: a1, b: b1 } = obj);
+
+ const complicatedObject = {
+ a: 1,
+ b: {
+ c: 2,
+ d: {
+ e: 3,
+ f: [4, 5, 6]
+ }
+ },
+ g: [7, 8, 9]
+ };
+
+ const { patron, b: { mafik, d: { e, f: [ , secondF, ...restF ] } }, g: [ firstG, ...restG ] } = complicatedObject;
+ }
+
+
+}
+
diff --git a/tests/auto/qmlls/utils/data/renaming/RenameMe.qml b/tests/auto/qmlls/utils/data/renaming/RenameMe.qml
new file mode 100644
index 0000000000..adc3da9800
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/renaming/RenameMe.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property int i42
+} \ No newline at end of file
diff --git a/tests/auto/qmlls/utils/data/renaming/RenameMe2.ui.qml b/tests/auto/qmlls/utils/data/renaming/RenameMe2.ui.qml
new file mode 100644
index 0000000000..35320e03ff
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/renaming/RenameMe2.ui.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property string i42
+} \ No newline at end of file
diff --git a/tests/auto/qmlls/utils/data/renaming/RenamedByQmldir.qml b/tests/auto/qmlls/utils/data/renaming/RenamedByQmldir.qml
new file mode 100644
index 0000000000..f97cbcf115
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/renaming/RenamedByQmldir.qml
@@ -0,0 +1,4 @@
+import QtQuick
+
+Item {
+}
diff --git a/tests/auto/qmlls/utils/data/renaming/UnrelatedFile.qml b/tests/auto/qmlls/utils/data/renaming/UnrelatedFile.qml
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/renaming/UnrelatedFile.qml
diff --git a/tests/auto/qmlls/utils/data/renaming/main.qml b/tests/auto/qmlls/utils/data/renaming/main.qml
new file mode 100644
index 0000000000..10afda9773
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/renaming/main.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ RenameMe {}
+ RenameMe2 {}
+ HelloWorld {}
+}
diff --git a/tests/auto/qmlls/utils/data/renaming/qmldir b/tests/auto/qmlls/utils/data/renaming/qmldir
new file mode 100644
index 0000000000..8cff297e26
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/renaming/qmldir
@@ -0,0 +1,6 @@
+module renaming
+RenameMe 254.0 RenameMe.qml
+RenameMe2 254.0 RenameMe2.ui.qml
+RenameMe3 254.0 subfolder/RenameMe3.qml
+main 254.0 main.qml
+HelloWorld 254.0 RenamedByQmldir.qml \ No newline at end of file
diff --git a/tests/auto/qmlls/utils/tst_qmlls_documentationHints.cpp b/tests/auto/qmlls/utils/tst_qmlls_documentationHints.cpp
new file mode 100644
index 0000000000..9527f635b4
--- /dev/null
+++ b/tests/auto/qmlls/utils/tst_qmlls_documentationHints.cpp
@@ -0,0 +1,125 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "tst_qmlls_documentationHints.h"
+
+#include <QtQmlLS/private/qdochtmlparser_p.h>
+#include <QtQmlDom/private/qqmldomtop_p.h>
+
+tst_qmlls_documentationHints::tst_qmlls_documentationHints()
+ : QQmlDataTest(QT_QMLLS_DOCUMENTATION_DATADIR) , m_documentationDataDir(QT_QMLLS_DOCUMENTATION_DATADIR + "/documentationHints"_L1)
+{
+}
+
+void tst_qmlls_documentationHints::qdochtmlparser_data()
+{
+ using namespace QQmlJS::Dom;
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<QString>("keyword");
+ QTest::addColumn<DomType>("domType");
+ QTest::addColumn<HtmlExtractor::ExtractionMode>("extractionMode");
+ QTest::addColumn<QString>("expectedDocumentation");
+
+ QTest::addRow("qml-object-type-extended-plaintext")
+ << testFile("qdochtmlparser/qml-qtqml-qtobject.html")
+ << "QtObject"
+ << DomType::QmlObject
+ << HtmlExtractor::ExtractionMode::Extended
+ << R"(The QtObject type is a non-visual element which contains only the objectName property.
+It can be useful to create a QtObject if you need an extremely lightweight type to enclose a set of custom properties:
+
+ import QtQuick
+
+ Item {
+ QtObject {
+ id: attributes
+ property string name
+ property int size
+ property variant attributes
+ }
+
+ Text { text: attributes.name }
+ }
+
+It can also be useful for C++ integration, as it is just a plain QObject. See the QObject documentation for further details.)";
+
+ QTest::addRow("qml-object-type-simplified-plaintext")
+ << testFile("qdochtmlparser/qml-qtqml-qtobject.html")
+ << "QtObject"
+ << DomType::QmlObject
+ << HtmlExtractor::ExtractionMode::Simplified
+ << R"(A basic QML type.)";
+
+ QTest::addRow("qml-property-simplified-plaintext")
+ << testFile("qdochtmlparser/qml-qtqml-qtobject.html")
+ << "objectName"
+ << DomType::PropertyDefinition
+ << HtmlExtractor::ExtractionMode::Simplified
+ << R"(This property holds the QObject::objectName for this specific object instance.)";
+
+ QTest::addRow("qml-property-simplified-plaintext-from-Qt5")
+ << testFile("qdochtmlparser/qml-qtqml-qtobject-qt-5.html")
+ << "objectName"
+ << DomType::PropertyDefinition
+ << HtmlExtractor::ExtractionMode::Simplified
+ << R"(This property holds the QObject::objectName for this specific object instance.)";
+
+ QTest::addRow("qml-property-simplified-plaintext")
+ << testFile("qdochtmlparser/qml-qtquick-item.html")
+ << "width"
+ << DomType::PropertyDefinition
+ << HtmlExtractor::ExtractionMode::Simplified
+ << R"(Defines the item's position and size. The default value is 0.)";
+
+ QTest::addRow("qml-group-property-simplified-plaintext")
+ << testFile("qdochtmlparser/qml-qtquick-item.html")
+ << "anchors.fill"
+ << DomType::PropertyDefinition
+ << HtmlExtractor::ExtractionMode::Simplified
+ << R"(Anchors provide a way to position an item by specifying its relationship with other items.)";
+ QTest::addRow("qml-functions")
+ << testFile("qdochtmlparser/qml-qtquick-item.html")
+ << "mapFromGlobal"
+ << DomType::MethodInfo
+ << HtmlExtractor::ExtractionMode::Simplified
+ << "Maps the point (x, y), which is in the global coordinate system, to the item's coordinate system,"
+ " and returns a point matching the mapped coordinate.";
+
+ QTest::addRow("qml-functions-list")
+ << testFile("qdochtmlparser/qml-qtquick-item.html")
+ << "mapFromItem"
+ << DomType::MethodInfo
+ << HtmlExtractor::ExtractionMode::Simplified
+ << "Maps the point (x, y) or rect (x, y, width, height), which is in item's coordinate system,"
+ " to this item's coordinate system, and returns a point or rect matching the mapped coordinate.";
+ QTest::addRow("qml-signal")
+ << testFile("qdochtmlparser/qml-qtquick-mousearea.html")
+ << "pressAndHold"
+ << DomType::MethodInfo
+ << HtmlExtractor::ExtractionMode::Simplified
+ << "This signal is emitted when there is a long press (currently 800ms). The mouse parameter provides information about the press, "
+ "including the x and y position of the press, and which button is pressed.";
+}
+
+void tst_qmlls_documentationHints::qdochtmlparser()
+{
+ using namespace QQmlJS::Dom;
+ QFETCH(QString, filePath);
+ QFETCH(QString, keyword);
+ QFETCH(DomType, domType);
+ QFETCH(HtmlExtractor::ExtractionMode, extractionMode);
+ QFETCH(QString, expectedDocumentation);
+
+ const auto htmlCode = [](const QString &testFileName) {
+ QFile file(testFileName);
+ if (file.open(QIODeviceBase::ReadOnly | QIODevice::Text))
+ return QString::fromUtf8(file.readAll());
+ return QString{};
+ }(filePath);
+
+ ExtractDocumentation extractor(domType);
+ const auto actual = extractor.execute(htmlCode, keyword, extractionMode);
+ QCOMPARE(actual, expectedDocumentation);
+}
+
+QTEST_MAIN(tst_qmlls_documentationHints)
diff --git a/tests/auto/qmlls/utils/tst_qmlls_documentationHints.h b/tests/auto/qmlls/utils/tst_qmlls_documentationHints.h
new file mode 100644
index 0000000000..f3b0f4ddd1
--- /dev/null
+++ b/tests/auto/qmlls/utils/tst_qmlls_documentationHints.h
@@ -0,0 +1,24 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TST_QMLLS_DOCUMENTATION_H
+#define TST_QMLLS_DOCUMENTATION_H
+
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtCore/qobject.h>
+#include <QtTest/qtest.h>
+
+class tst_qmlls_documentationHints : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_qmlls_documentationHints();
+private slots:
+ void qdochtmlparser_data();
+ void qdochtmlparser();
+
+private:
+ QString m_documentationDataDir;
+};
+
+#endif // TST_QMLLS_DOCUMENTATION_H
diff --git a/tests/auto/qmlls/utils/tst_qmlls_highlighting.cpp b/tests/auto/qmlls/utils/tst_qmlls_highlighting.cpp
new file mode 100644
index 0000000000..f21de11990
--- /dev/null
+++ b/tests/auto/qmlls/utils/tst_qmlls_highlighting.cpp
@@ -0,0 +1,650 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "tst_qmlls_highlighting.h"
+
+#include <QtQml/private/qqmljsengine_p.h>
+#include <QtQml/private/qqmljslexer_p.h>
+#include <QtQml/private/qqmljsparser_p.h>
+#include <QtQmlDom/private/qqmldomitem_p.h>
+#include <QtQmlDom/private/qqmldomtop_p.h>
+#include <QtQmlLS/private/qqmlsemantictokens_p.h>
+#include <QtCore/qlibraryinfo.h>
+#include <QtLanguageServer/private/qlanguageserverspectypes_p.h>
+
+#include <qlist.h>
+
+using namespace QLspSpecification;
+
+tst_qmlls_highlighting::tst_qmlls_highlighting()
+ : QQmlDataTest(QT_QMLLS_HIGHLIGHTS_DATADIR) , m_highlightingDataDir(QT_QMLLS_HIGHLIGHTS_DATADIR + "/highlights"_L1)
+{
+}
+
+// Token encoding as in:
+// https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#textDocument_semanticTokens
+void tst_qmlls_highlighting::encodeSemanticTokens_data()
+{
+ QTest::addColumn<Highlights>("highlights");
+ QTest::addColumn<QList<int>>("expectedMemoryLayout");
+
+ {
+ Highlights c;
+ c.highlights().insert(0, Token());
+ QTest::addRow("empty-token-single") << c << QList {0, 0, 0, 0, 0};
+ }
+ {
+ Highlights c;
+ QQmlJS::SourceLocation loc(0, 1, 1, 1);
+ c.highlights().insert(0, Token(loc, 0, 0));
+ QTest::addRow("single-token") << c << QList {0, 0, 1, 0, 0};
+ }
+ {
+ Highlights c;
+ Token t1(QQmlJS::SourceLocation(0, 1, 1, 1), 0, 0);
+ Token t2(QQmlJS::SourceLocation(1, 1, 3, 3), 0, 0);
+ c.highlights().insert(t1.offset, t1);
+ c.highlights().insert(t2.offset, t2);
+ QTest::addRow("different-lines") << c << QList {0, 0, 1, 0, 0, 2, 2, 1, 0, 0};
+ }
+ {
+ Highlights c;
+ Token t1(QQmlJS::SourceLocation(0, 1, 1, 1), 0, 0);
+ Token t2(QQmlJS::SourceLocation(1, 1, 1, 3), 0, 0);
+ c.highlights().insert(t1.offset, t1);
+ c.highlights().insert(t2.offset, t2);
+ QTest::addRow("same-line-different-column") << c << QList {0, 0, 1, 0, 0, 0, 2, 1, 0, 0};
+ }
+ {
+ Highlights c;
+ Token t1(QQmlJS::SourceLocation(0, 1, 1, 1), 1, 0);
+ c.highlights().insert(t1.offset, t1);
+ QTest::addRow("token-type") << c << QList {0, 0, 1, 1, 0};
+ }
+ {
+ Highlights c;
+ Token t1(QQmlJS::SourceLocation(0, 1, 1, 1), 1, 1);
+ c.highlights().insert(t1.offset, t1);
+ QTest::addRow("token-modifier") << c << QList {0, 0, 1, 1, 1};
+ }
+}
+
+void tst_qmlls_highlighting::encodeSemanticTokens()
+{
+ QFETCH(Highlights, highlights);
+ QFETCH(QList<int>, expectedMemoryLayout);
+ const auto encoded = HighlightingUtils::encodeSemanticTokens(highlights);
+ QCOMPARE(encoded, expectedMemoryLayout);
+}
+
+struct LineLength
+{
+ quint32 startLine;
+ quint32 length;
+};
+
+void tst_qmlls_highlighting::sourceLocationsFromMultiLineToken_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<QList<LineLength>>("expectedLines");
+
+ QTest::addRow("multilineComment1") << R"("line 1
+line 2
+line 3 ")" << QList{ LineLength{ 1, 7 }, LineLength{ 2, 6 }, LineLength{ 3, 8 } };
+
+ QTest::addRow("prePostNewlines") <<
+ R"("
+
+")" << QList{ LineLength{ 1, 1 }, LineLength{ 2, 0 }, LineLength{ 3, 1 } };
+ QTest::addRow("windows-newline")
+ << QString::fromUtf8("\"test\r\nwindows\r\nnewline\"")
+ << QList{ LineLength{ 1, 5 }, LineLength{ 2, 7 }, LineLength{ 3, 8 } };
+}
+
+void tst_qmlls_highlighting::sourceLocationsFromMultiLineToken()
+{
+ QFETCH(QString, source);
+ QFETCH(QList<LineLength>, expectedLines);
+ using namespace QQmlJS::AST;
+
+ QQmlJS::Engine jsEngine;
+ QQmlJS::Lexer lexer(&jsEngine);
+ lexer.setCode(source, 1, true);
+ QQmlJS::Parser parser(&jsEngine);
+ parser.parseExpression();
+ const auto expression = parser.expression();
+
+ auto *literal = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(expression);
+ const auto locs =
+ HighlightingUtils::sourceLocationsFromMultiLineToken(source, literal->literalToken);
+
+ [&]() {
+ QCOMPARE(locs.size(), expectedLines.size());
+
+ for (auto i = 0; i < locs.size(); ++i) {
+ QCOMPARE(locs[i].startLine, expectedLines[i].startLine);
+ QCOMPARE(locs[i].length, expectedLines[i].length);
+ }
+ }();
+
+ if (QTest::currentTestFailed()) {
+
+ qDebug() << "Actual locations";
+ for (auto i = 0; i < locs.size(); ++i) {
+ qDebug() << "Startline :" << locs[i].startLine << "Length " << locs[i].length;
+ }
+
+ qDebug() << "Expected locations";
+ for (auto i = 0; i < expectedLines.size(); ++i) {
+ qDebug() << "Startline :" << expectedLines[i].startLine
+ << "Length :" << expectedLines[i].length;
+ }
+ }
+}
+
+void tst_qmlls_highlighting::highlights_data()
+{
+ using namespace QQmlJS::Dom;
+ QTest::addColumn<DomItem>("fileItem");
+ QTest::addColumn<Token>("expectedHighlightedToken");
+
+ const auto fileObject = [](const QString &filePath){
+ QFile f(filePath);
+ DomItem file;
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
+ return file;
+ QString code = f.readAll();
+ DomCreationOptions options;
+ options.setFlag(DomCreationOption::WithScriptExpressions);
+ options.setFlag(DomCreationOption::WithSemanticAnalysis);
+ options.setFlag(DomCreationOption::WithRecovery);
+
+ QStringList dirs = {QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath)};
+ auto envPtr = DomEnvironment::create(dirs,
+ QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
+ | QQmlJS::Dom::DomEnvironment::Option::NoDependencies, options);
+ envPtr->loadBuiltins();
+ envPtr->loadFile(FileToLoad::fromMemory(envPtr, filePath, code),
+ [&file](Path, const DomItem &, const DomItem &newIt) {
+ file = newIt.fileObject();
+ });
+ envPtr->loadPendingDependencies();
+ return file;
+ };
+
+ { // Comments
+ const auto filePath = m_highlightingDataDir + "/comments.qml";
+ const auto fileItem = fileObject(filePath);
+ // Copyright (C) 2023 The Qt Company Ltd.
+ QTest::addRow("single-line-1")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(0, 41, 1, 1), int(SemanticTokenTypes::Comment), 0);
+
+ /* single line comment */
+ QTest::addRow("single-line-2") << fileItem
+ << Token(QQmlJS::SourceLocation(162, 28, 9, 1),
+ int(SemanticTokenTypes::Comment), 0);
+
+ // Multiline comments are split into multiple locations
+ QTest::addRow("multiline-first-line")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(133, 2, 5, 1), int(SemanticTokenTypes::Comment), 0);
+ QTest::addRow("multiline-second-line") << fileItem
+ << Token(QQmlJS::SourceLocation(136, 21, 6, 1),
+ int(SemanticTokenTypes::Comment), 0);
+ QTest::addRow("multiline-third-line")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(158, 2, 7, 1), int(SemanticTokenTypes::Comment), 0);
+
+ // Comments Inside Js blocks
+ QTest::addRow("inside-js") << fileItem
+ << Token(QQmlJS::SourceLocation(232, 5, 13, 9),
+ int(SemanticTokenTypes::Comment), 0);
+ }
+ { // Imports
+ const auto filePath = m_highlightingDataDir + "/imports.qml";
+ const auto fileItem = fileObject(filePath);
+ QTest::addRow("import-keyword")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(112, 6, 4, 1), int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("module-uri") << fileItem
+ << Token(QQmlJS::SourceLocation(119, 7, 4, 8),
+ int(SemanticTokenTypes::Namespace), 0);
+ QTest::addRow("directory-uri")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(152, 3, 6, 8), int(SemanticTokenTypes::String), 0);
+ QTest::addRow("as-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(156, 2, 6, 12),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("version-number")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(140, 4, 5, 14), int(SemanticTokenTypes::Number), 0);
+ QTest::addRow("qualified-namespace") << fileItem
+ << Token(QQmlJS::SourceLocation(159, 6, 6, 15),
+ int(SemanticTokenTypes::Namespace), 0);
+ }
+ { // Bindings
+ const auto filePath = m_highlightingDataDir + "/bindings.qml";
+ const auto fileItem = fileObject(filePath);
+
+ // normal binding
+ QTest::addRow("normalBinding") << fileItem
+ << Token(QQmlJS::SourceLocation(189, 1, 11, 5),
+ int(SemanticTokenTypes::Property), 0);
+ // on binding
+ QTest::addRow("on-binding") << fileItem
+ << Token(QQmlJS::SourceLocation(175, 5, 9, 17),
+ int(SemanticTokenTypes::Property), 0);
+ QTest::addRow("on-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(172, 2, 9, 14),
+ int(SemanticTokenTypes::Keyword), 0);
+ }
+ { // Pragmas
+ const auto filePath = m_highlightingDataDir + "/pragmas.qml";
+ const auto fileItem = fileObject(filePath);
+ QTest::addRow("pragma-keyword")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(112, 6, 4, 1), int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("pragma-name") << fileItem
+ << Token(QQmlJS::SourceLocation(136, 25, 5, 8),
+ int(SemanticTokenTypes::Variable), 0);
+ QTest::addRow("pragma-value") << fileItem
+ << Token(QQmlJS::SourceLocation(198, 4, 6, 27),
+ int(SemanticTokenTypes::Variable), 0);
+ }
+ { // Enums
+ const auto filePath = m_highlightingDataDir + "/enums.qml";
+ const auto fileItem = fileObject(filePath);
+ QTest::addRow("enum-keyword")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(141, 4, 7, 5), int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("enum-name")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(146, 3, 7, 10), int(SemanticTokenTypes::Enum), 0);
+ QTest::addRow("enum-item") << fileItem
+ << Token(QQmlJS::SourceLocation(160, 3, 8, 9),
+ int(SemanticTokenTypes::EnumMember), 0);
+ QTest::addRow("enum-value")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(179, 1, 9, 15), int(SemanticTokenTypes::Number), 0);
+ }
+ { // objects and inline components
+ const auto filePath = m_highlightingDataDir + "/objectAndComponent.qml";
+ const auto fileItem = fileObject(filePath);
+
+ // object
+ QTest::addRow("object-identifier")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(169, 4, 8, 5), int(SemanticTokenTypes::Type), 0);
+ QTest::addRow("object-id-property") << fileItem
+ << Token(QQmlJS::SourceLocation(184, 2, 9, 9),
+ int(SemanticTokenTypes::Property), 0);
+ QTest::addRow("object-id-name") << fileItem
+ << Token(QQmlJS::SourceLocation(188, 5, 9, 13),
+ int(SemanticTokenTypes::Variable), 0);
+
+ // component
+ QTest::addRow("component-keyword")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(139, 9, 7, 5), int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("component-name")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(149, 6, 7, 15), int(SemanticTokenTypes::Type), 0);
+ }
+ { // property definition
+ const auto filePath = m_highlightingDataDir + "/properties.qml";
+ const auto fileItem = fileObject(filePath);
+
+ int definitionModifier = 1 << int(SemanticTokenModifiers::Definition);
+ QTest::addRow("property-keyword")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(154, 8, 8, 9), int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("property-type")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(163, 3, 8, 18), int(SemanticTokenTypes::Type), 0);
+ QTest::addRow("property-name")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(167, 1, 8, 22), int(SemanticTokenTypes::Property),
+ definitionModifier);
+ int readOnlyModifier = definitionModifier | (1 << int(SemanticTokenModifiers::Readonly));
+ QTest::addRow("readonly-keyword")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(177, 8, 9, 9), int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("readonly-modifier")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(199, 2, 9, 31), int(SemanticTokenTypes::Property),
+ readOnlyModifier);
+ int requiredModifier = definitionModifier | (1 << int(SemanticTokenModifiers::Abstract));
+ QTest::addRow("required-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(210, 8, 10, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("required-modifier")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(232, 3, 10, 31), int(SemanticTokenTypes::Property),
+ requiredModifier);
+ int defaultModifier =
+ definitionModifier | (1 << int(SemanticTokenModifiers::DefaultLibrary));
+ QTest::addRow("default-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(244, 7, 11, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("default-modifier")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(265, 4, 11, 30), int(SemanticTokenTypes::Property),
+ defaultModifier);
+ }
+ {
+ // methods and signals
+ const auto filePath = m_highlightingDataDir + "/methodAndSignal.qml";
+ const auto fileItem = fileObject(filePath);
+
+ QTest::addRow("signal-keyword")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(139, 6, 7, 5), int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("signal-name")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(146, 1, 7, 12), int(SemanticTokenTypes::Method), 0);
+ QTest::addRow("signal-type")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(163, 3, 8, 14), int(SemanticTokenTypes::Type), 0);
+ QTest::addRow("signal-type-2")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(186, 3, 9, 17), int(SemanticTokenTypes::Type), 0);
+ QTest::addRow("function-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(195, 9, 10, 5),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("function-name") << fileItem
+ << Token(QQmlJS::SourceLocation(204, 1, 10, 14),
+ int(SemanticTokenTypes::Method), 0);
+ QTest::addRow("function-prm-type")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(209, 3, 10, 19), int(SemanticTokenTypes::Type), 0);
+ QTest::addRow("function-prm-name") << fileItem
+ << Token(QQmlJS::SourceLocation(206, 1, 10, 16),
+ int(SemanticTokenTypes::Parameter), 0);
+ QTest::addRow("function-rtn-type")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(216, 3, 10, 26), int(SemanticTokenTypes::Type), 0);
+ }
+ { // literals
+ const auto filePath = m_highlightingDataDir + "/literals.qml";
+ const auto fileItem = fileObject(filePath);
+
+ QTest::addRow("number") << fileItem
+ << Token(QQmlJS::SourceLocation(155, 3, 7, 21),
+ int(SemanticTokenTypes::Number), 0);
+ QTest::addRow("singleline-string")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(182, 8, 8, 24), int(SemanticTokenTypes::String), 0);
+ QTest::addRow("multiline-string-first")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(214, 6, 9, 24), int(SemanticTokenTypes::String), 0);
+ QTest::addRow("multiline-string-second") << fileItem
+ << Token(QQmlJS::SourceLocation(221, 16, 10, 1),
+ int(SemanticTokenTypes::String), 0);
+ QTest::addRow("boolean") << fileItem
+ << Token(QQmlJS::SourceLocation(260, 4, 11, 22),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("null") << fileItem
+ << Token(QQmlJS::SourceLocation(285, 4, 12, 21),
+ int(SemanticTokenTypes::Keyword), 0);
+ }
+ { // identifiers
+ const auto filePath = m_highlightingDataDir + "/Identifiers.qml";
+ const auto fileItem = fileObject(filePath);
+ QTest::addRow("js-property") << fileItem
+ << Token(QQmlJS::SourceLocation(222, 3, 10, 13),
+ int(SemanticTokenTypes::Variable), 0);
+ QTest::addRow("property-id")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(302, 4, 12, 19), int(SemanticTokenTypes::Property),
+ (1 << int(SemanticTokenModifiers::Readonly)));
+ QTest::addRow("property-changed") << fileItem
+ << Token(QQmlJS::SourceLocation(451, 11, 18, 9),
+ int(SemanticTokenTypes::Method), 0);
+ QTest::addRow("signal") << fileItem
+ << Token(QQmlJS::SourceLocation(474, 7, 19, 9),
+ int(SemanticTokenTypes::Method), 0);
+
+ QTest::addRow("attached-id")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(512, 4, 23, 5), int(SemanticTokenTypes::Type), 0);
+ QTest::addRow("attached-signalhandler") << fileItem
+ << Token(QQmlJS::SourceLocation(517, 9, 23, 10),
+ int(SemanticTokenTypes::Method), 0);
+ QTest::addRow("propchanged-handler") << fileItem
+ << Token(QQmlJS::SourceLocation(572, 13, 27, 5),
+ int(SemanticTokenTypes::Method), 0);
+ QTest::addRow("method-id")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(597, 1, 28, 9), int(SemanticTokenTypes::Method), 0);
+ QTest::addRow("signal-handler")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(656, 9, 32, 5), int(SemanticTokenTypes::Method), 0);
+ }
+ { // script expressions
+ const auto filePath = m_highlightingDataDir + "/scriptExpressions.qml";
+ const auto fileItem = fileObject(filePath);
+
+ QTest::addRow("var-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(192, 3, 11, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("const-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(217, 5, 12, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ const auto modifier = (1 << int(SemanticTokenModifiers::Readonly));
+ QTest::addRow("const-name") << fileItem
+ << Token(QQmlJS::SourceLocation(223, 10, 12, 15),
+ int(SemanticTokenTypes::Variable), modifier);
+ QTest::addRow("do-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(248, 2, 13, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("if-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(287, 2, 15, 13),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("continue-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(319, 8, 16, 17),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("else-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(341, 4, 17, 13),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("while-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(382, 5, 19, 11),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("switch-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(418, 6, 20, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("case-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(444, 4, 21, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("return-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(464, 6, 22, 13),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("default-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(483, 7, 23, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("break-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(504, 5, 24, 13),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("try-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(529, 3, 26, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("catch-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(560, 5, 28, 11),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("finally-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(601, 7, 30, 11),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("for-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(620, 3, 31, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("throw-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(661, 5, 32, 13),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("for-declaration") << fileItem
+ << Token(QQmlJS::SourceLocation(625, 5, 31, 14),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("destructuring")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(1511, 2, 73, 16), int(SemanticTokenTypes::Variable),
+ (1 << int(SemanticTokenModifiers::Readonly)));
+ QTest::addRow("obj-destructuring")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(1589, 2, 76, 17), int(SemanticTokenTypes::Variable),
+ (1 << int(SemanticTokenModifiers::Readonly)));
+ }
+}
+
+void tst_qmlls_highlighting::highlights()
+{
+ using namespace QQmlJS::Dom;
+ QFETCH(DomItem, fileItem);
+ QFETCH(Token, expectedHighlightedToken);
+
+ Highlights h;
+ HighlightingVisitor hv(h, std::nullopt);
+
+ fileItem.visitTree(QQmlJS::Dom::Path(), hv, VisitOption::Default, emptyChildrenVisitor,
+ emptyChildrenVisitor);
+
+ const auto highlights = h.highlights();
+ QVERIFY(highlights.contains(expectedHighlightedToken.offset));
+ QCOMPARE(highlights.value(expectedHighlightedToken.offset), expectedHighlightedToken);
+}
+
+void tst_qmlls_highlighting::rangeOverlapsWithSourceLocation_data()
+{
+ QTest::addColumn<QQmlJS::SourceLocation>("sourceLocation");
+ QTest::addColumn<HighlightsRange>("range");
+ QTest::addColumn<bool>("overlaps");
+
+ QTest::addRow("sl-inside-range")
+ << QQmlJS::SourceLocation(5, 1, 1, 1) << HighlightsRange{ 0, 100 } << true;
+ QTest::addRow("sl-exceeds-rightBoundRange")
+ << QQmlJS::SourceLocation(5, 1000, 1, 1) << HighlightsRange{ 0, 100 } << true;
+ QTest::addRow("sl-exceeds-leftRightBoundRange")
+ << QQmlJS::SourceLocation(5, 1000, 1, 1) << HighlightsRange{ 8, 100 } << true;
+ QTest::addRow("sl-exceeds-leftBoundRange")
+ << QQmlJS::SourceLocation(5, 100, 1, 1) << HighlightsRange{ 8, 1000 } << true;
+ QTest::addRow("no-overlaps") << QQmlJS::SourceLocation(5, 100, 1, 1)
+ << HighlightsRange{ 8000, 100000 } << false;
+}
+
+void tst_qmlls_highlighting::rangeOverlapsWithSourceLocation()
+{
+ QFETCH(QQmlJS::SourceLocation, sourceLocation);
+ QFETCH(HighlightsRange, range);
+ QFETCH(bool, overlaps);
+ QVERIFY(overlaps == HighlightingUtils::rangeOverlapsWithSourceLocation(sourceLocation, range));
+}
+
+void tst_qmlls_highlighting::updateResultID_data()
+{
+ QTest::addColumn<QByteArray>("currentId");
+ QTest::addColumn<QByteArray>("expectedNextId");
+
+ QTest::addRow("zero-to-one") << QByteArray("0") << QByteArray("1");
+ QTest::addRow("nine-to-ten") << QByteArray("9") << QByteArray("10");
+ QTest::addRow("nineteen-to-twenty") << QByteArray("19") << QByteArray("20");
+ QTest::addRow("twodigit-to-threedigit") << QByteArray("99") << QByteArray("100");
+}
+
+void tst_qmlls_highlighting::updateResultID()
+{
+ QFETCH(QByteArray, currentId);
+ QFETCH(QByteArray, expectedNextId);
+
+ HighlightingUtils::updateResultID(currentId);
+ QCOMPARE(currentId, expectedNextId);
+}
+
+void tst_qmlls_highlighting::computeDiff_data()
+{
+ QTest::addColumn<QList<int>>("oldData");
+ QTest::addColumn<QList<int>>("newData");
+ QTest::addColumn<QList<SemanticTokensEdit>>("expected");
+
+ {
+ QList<int> oldData { 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0};
+ QList<int> newData { 3,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0};
+ SemanticTokensEdit expected;
+ expected.start = 0;
+ expected.deleteCount = 1;
+ expected.data = QList{3};
+ QTest::addRow("simple") << oldData << newData << QList{expected};
+ }
+ {
+ QList<int> oldData { 0, 0, 5, 5, 0};
+ QList<int> newData { 3, 3, 3, 3, 3, 0, 0, 5, 5, 0};
+ SemanticTokensEdit expected;
+ expected.start = 0;
+ expected.deleteCount = 0;
+ expected.data = QList{3, 3, 3, 3, 3};
+ QTest::addRow("prepend") << oldData << newData << QList{expected};
+ }
+ {
+ QList<int> oldData { 3, 3, 3, 3, 3, 0, 0, 5, 5, 0};
+ QList<int> newData { 0, 0, 5, 5, 0};
+ SemanticTokensEdit expected;
+ expected.start = 0;
+ expected.deleteCount = 5;
+ expected.data = {};
+ QTest::addRow("remove-front") << oldData << newData << QList{expected};
+ }
+ {
+ QList<int> oldData { 0, 0, 5, 5, 0};
+ QList<int> newData { 0, 0, 5, 5, 0, 1, 0, 23, 5, 0};
+ SemanticTokensEdit expected;
+ expected.start = 5;
+ expected.deleteCount = 0;
+ expected.data = QList{1, 0, 23, 5, 0};
+ QTest::addRow("append") << oldData << newData << QList{expected};
+ }
+ {
+ QList<int> oldData { 0, 0, 5, 5, 0, 1, 0, 23, 5, 0};
+ QList<int> newData { 0, 0, 5, 5, 0};
+ SemanticTokensEdit expected;
+ expected.start = 5;
+ expected.deleteCount = 5;
+ expected.data = {};
+ QTest::addRow("remove-back") << oldData << newData << QList{expected};
+ }
+ {
+ QList<int> oldData { 0, 0, 5, 5, 0, 1, 0, 23, 5, 0};
+ QList<int> newData { 0, 0, 5, 5, 0, 3, 3, 3, 3, 3, 1, 0, 23, 5, 0};
+ SemanticTokensEdit expected;
+ expected.start = 5;
+ expected.deleteCount = 0;
+ expected.data = QList{3, 3, 3, 3, 3};
+ QTest::addRow("insert-middle") << oldData << newData << QList{expected};
+ }
+ {
+ QList<int> oldData { 0, 0, 5, 5, 0, 3, 3, 3, 3, 3, 1, 0, 23, 5, 0};
+ QList<int> newData { 0, 0, 5, 5, 0, 1, 0, 23, 5, 0};
+ SemanticTokensEdit expected;
+ expected.start = 5;
+ expected.deleteCount = 5;
+ expected.data = {};
+ QTest::addRow("remove-middle") << oldData << newData << QList{expected};
+ }
+}
+
+void tst_qmlls_highlighting::computeDiff()
+{
+ QFETCH(QList<int>, oldData);
+ QFETCH(QList<int>, newData);
+ QFETCH(QList<SemanticTokensEdit>, expected);
+
+ const auto edits = HighlightingUtils::computeDiff(oldData, newData);
+ QCOMPARE(edits.size(), expected.size());
+
+ qsizetype i = 0;
+ for (const auto &edit : edits) {
+ QCOMPARE(edit.start, expected.at(i).start);
+ QCOMPARE(edit.deleteCount, expected.at(i).deleteCount);
+ QCOMPARE(edit.data, expected.at(i).data);
+ ++i;
+ }
+}
+
+
+QTEST_MAIN(tst_qmlls_highlighting)
diff --git a/tests/auto/qmlls/utils/tst_qmlls_highlighting.h b/tests/auto/qmlls/utils/tst_qmlls_highlighting.h
new file mode 100644
index 0000000000..a1d0e3c9b1
--- /dev/null
+++ b/tests/auto/qmlls/utils/tst_qmlls_highlighting.h
@@ -0,0 +1,37 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TST_QMLLS_HIGHLIGHTING_H
+#define TST_QMLLS_HIGHLIGHTING_H
+
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtCore/qobject.h>
+#include <QtTest/qtest.h>
+
+class tst_qmlls_highlighting : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_qmlls_highlighting();
+private slots:
+ void encodeSemanticTokens_data();
+ void encodeSemanticTokens();
+ void sourceLocationsFromMultiLineToken_data();
+ void sourceLocationsFromMultiLineToken();
+
+ void highlights_data();
+ void highlights();
+
+ void rangeOverlapsWithSourceLocation_data();
+ void rangeOverlapsWithSourceLocation();
+
+ void updateResultID_data();
+ void updateResultID();
+
+ void computeDiff_data();
+ void computeDiff();
+private:
+ QString m_highlightingDataDir;
+};
+
+#endif // TST_QMLLS_HIGHLIGHTING_H
diff --git a/tests/auto/qmlls/utils/tst_qmlls_utils.cpp b/tests/auto/qmlls/utils/tst_qmlls_utils.cpp
index c8808e2d7c..332dc13590 100644
--- a/tests/auto/qmlls/utils/tst_qmlls_utils.cpp
+++ b/tests/auto/qmlls/utils/tst_qmlls_utils.cpp
@@ -39,7 +39,7 @@ tst_qmlls_utils::createEnvironmentAndLoadFile(const QString &filePath)
{
CacheKey cacheKey = QDir::cleanPath(filePath + u"/.."_s);
if (auto entry = cache.find(cacheKey); entry != cache.end()) {
- DomItem env{ *entry };
+ QQmlJS::Dom::DomItem env{ *entry };
return { env, env.field(QQmlJS::Dom::Fields::qmlFileWithPath).key(filePath) };
};
@@ -663,7 +663,7 @@ void tst_qmlls_utils::findBaseObject()
struct UsageData
{
QString testFileName;
- QList<QQmlLSUtilsLocation> expectedUsages;
+ QQmlLSUtils::Usages expectedUsages;
};
void tst_qmlls_utils::findUsages_data()
@@ -679,33 +679,41 @@ void tst_qmlls_utils::findUsages_data()
return QString{};
};
- const auto makeUsages = [](const QString &fileName, QList<QQmlLSUtilsLocation> &locations) {
+ const auto makeUsages = [](const QString &fileName, QList<QQmlLSUtils::Location> &locations) {
UsageData data;
std::sort(locations.begin(), locations.end());
- data.expectedUsages = locations;
+ data.expectedUsages = { locations, {} };
data.testFileName = fileName;
return data;
};
{
- QList<QQmlLSUtilsLocation> expectedUsages;
+ QList<QQmlLSUtils::Location> expectedUsages;
const auto testFileName = testFile("findUsages/jsIdentifier/jsIdentifier.qml");
const auto testFileContent = readFileContent(testFileName);
{
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 8, 13, strlen("sum"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 10, 13, strlen("sum"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 10, 19, strlen("sum"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 13,
+ strlen("sum"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 13,
+ strlen("sum"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 19,
+ strlen("sum"));
const auto sumUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findSumFromDeclaration") << 8 << 13 << sumUsages;
QTest::addRow("findSumFromUsage") << 10 << 20 << sumUsages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 9, 17, strlen("i"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 9, 24, strlen("i"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 9, 32, strlen("i"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 9, 36, strlen("i"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 10, 25, strlen("i"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 17,
+ strlen("i"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 24,
+ strlen("i"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 32,
+ strlen("i"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 36,
+ strlen("i"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 25,
+ strlen("i"));
const auto iUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findIFromDeclaration") << 9 << 17 << iUsages;
QTest::addRow("findIFromUsage") << 9 << 24 << iUsages;
@@ -718,40 +726,54 @@ void tst_qmlls_utils::findUsages_data()
const auto testFileContent = readFileContent(testFileName);
const auto otherFileContent = readFileContent(otherFile);
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 8, 18, strlen("helloProperty"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 13, 13, strlen("helloProperty"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 13, 29, strlen("helloProperty"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 20, 9, strlen("helloProperty"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 21, 9, strlen("helloPropertyChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 23, 5, strlen("onHelloPropertyChanged"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 18,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 13, 13,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 13, 29,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 20, 9,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 21, 9,
+ strlen("helloPropertyChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 5,
+ strlen("onHelloPropertyChanged"));
const auto helloPropertyUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findPropertyFromDeclaration") << 8 << 18 << helloPropertyUsages;
QTest::addRow("findPropertyFromUsage") << 13 << 13 << helloPropertyUsages;
QTest::addRow("findPropertyFromUsage2") << 13 << 29 << helloPropertyUsages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 36, 20, strlen("helloProperty"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 38, 25, strlen("helloProperty"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 36, 20,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 38, 25,
+ strlen("helloProperty"));
const auto subItemHelloPropertyUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findPropertyFromDeclarationInSubItem") << 38 << 25 << subItemHelloPropertyUsages;
QTest::addRow("findPropertyFromUsageInSubItem") << 36 << 20 << subItemHelloPropertyUsages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 27, 22, strlen("helloProperty"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 29, 20, strlen("helloProperty"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 27, 22,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 29, 20,
+ strlen("helloProperty"));
const auto ICHelloPropertyUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findPropertyFromDeclarationInIC") << 27 << 22 << ICHelloPropertyUsages;
QTest::addRow("findPropertyFromUsageInIC") << 29 << 20 << ICHelloPropertyUsages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(otherFile, otherFileContent, 4, 18, strlen("helloProperty"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 42, 9, strlen("helloProperty"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 44, 20, strlen("helloProperty"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 46, 9, strlen("OnHelloPropertyChanged"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(otherFile, otherFileContent, 4, 18,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 42, 9,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 44, 20,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 46, 9,
+ strlen("OnHelloPropertyChanged"));
const auto helloPropertyUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findPropertyFromOtherFile") << 42 << 13 << helloPropertyUsages;
@@ -770,35 +792,52 @@ void tst_qmlls_utils::findUsages_data()
const auto componentFileContent3 = readFileContent(componentFileName);
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 7, 18, strlen("p2"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 33, 31, strlen("p2"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 34, 37, strlen("p2"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 35, 43, strlen("p2"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 36, 49, strlen("p2"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 42, 26, strlen("p2"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 7, 18,
+ strlen("p2"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 33, 31,
+ strlen("p2"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 34, 37,
+ strlen("p2"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 35, 43,
+ strlen("p2"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 36, 49,
+ strlen("p2"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 42, 26,
+ strlen("p2"));
const auto p2Usages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findPropertyFromDeclaration2") << 7 << 18 << p2Usages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 29, 13, strlen("myNested"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 32, 17, strlen("myNested"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 33, 17, strlen("myNested"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 34, 17, strlen("myNested"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 35, 17, strlen("myNested"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 36, 17, strlen("myNested"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 29, 13,
+ strlen("myNested"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 32, 17,
+ strlen("myNested"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 33, 17,
+ strlen("myNested"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 34, 17,
+ strlen("myNested"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 35, 17,
+ strlen("myNested"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 36, 17,
+ strlen("myNested"));
const auto nestedUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findIdFromUsage") << 36 << 20 << nestedUsages;
QTest::addRow("findIdFromDefinition") << 29 << 17 << nestedUsages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 14, 35, strlen("inner"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 32, 32, strlen("inner"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 35, 32, strlen("inner"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 36, 32, strlen("inner"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 16, 9, strlen("inner"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 14, 35,
+ strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 32, 32,
+ strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 35, 32,
+ strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 36, 32,
+ strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 16, 9,
+ strlen("inner"));
const auto nestedComponent3Usages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findPropertyFromUsageInFieldMemberExpression")
<< 36 << 34 << nestedComponent3Usages;
@@ -807,12 +846,17 @@ void tst_qmlls_utils::findUsages_data()
<< 14 << 38 << nestedComponent3Usages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(componentFileName, componentFileContent, 4, 37, strlen("inner"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 50, 32, strlen("inner"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 52, 32, strlen("inner"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 53, 32, strlen("inner"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 54, 32, strlen("inner"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(componentFileName, componentFileContent,
+ 4, 37, strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 50, 32,
+ strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 52, 32,
+ strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 53, 32,
+ strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 54, 32,
+ strlen("inner"));
const auto nestedComponent3Usages = makeUsages(testFileName, expectedUsages);
const auto nestedComponent3UsagesFromOtherFile =
makeUsages(componentFileName, expectedUsages);
@@ -823,19 +867,21 @@ void tst_qmlls_utils::findUsages_data()
<< 4 << 38 << nestedComponent3UsagesFromOtherFile;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 35, 38, strlen("p2"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 20, 22, strlen("p2"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 35, 38,
+ strlen("p2"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 20, 22,
+ strlen("p2"));
const auto nestedComponent3P2Usages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findProperty2FromUsageInFieldMemberExpression")
<< 35 << 39 << nestedComponent3P2Usages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(componentFileName3, componentFileContent3,
- 5, 18, strlen("p2"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 53, 44,
- strlen("p2"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(componentFileName3, componentFileContent3,
+ 5, 18, strlen("p2"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 53, 44,
+ strlen("p2"));
const auto nestedComponent3P2Usages = makeUsages(testFileName, expectedUsages);
const auto nestedComponent3P2UsagesFromOtherFile = makeUsages(componentFileName3, expectedUsages);
QTest::addRow("findProperty2FromUsageInFieldMemberExpressionInOtherFile")
@@ -845,28 +891,40 @@ void tst_qmlls_utils::findUsages_data()
}
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
+ QList<QQmlLSUtils::Location> expectedUsages;
const auto testFileName = testFile("findUsages/idUsages/idUsages.qml");
const auto testFileContent = readFileContent(testFileName);
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 7, 9, strlen("rootId"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 11, 17, strlen("rootId"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 12, 20, strlen("rootId"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 17, 9, strlen("rootId"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 7, 9,
+ strlen("rootId"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 11, 17,
+ strlen("rootId"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 12, 20,
+ strlen("rootId"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 17, 9,
+ strlen("rootId"));
const auto rootIdUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findIdFromUsageInChild") << 12 << 20 << rootIdUsages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
+ QList<QQmlLSUtils::Location> expectedUsages;
const auto testFileName = testFile("findUsages/recursive/recursive.qml");
const auto testFileContent = readFileContent(testFileName);
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 8, 14, strlen("recursive"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 10, 24, strlen("recursive"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 10, 34, strlen("recursive"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 10, 51, strlen("recursive"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 10, 68, strlen("recursive"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 12, 20, strlen("recursive"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 15, 34, strlen("recursive"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 19, 27, strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 14,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 24,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 34,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 51,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 68,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 12, 20,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 15, 34,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 19, 27,
+ strlen("recursive"));
const auto recursiveUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findFunctionUsage") << 10 << 30 << recursiveUsages;
QTest::addRow("findFunctionUsage2") << 12 << 24 << recursiveUsages;
@@ -874,26 +932,26 @@ void tst_qmlls_utils::findUsages_data()
QTest::addRow("findFunctionUsageFromDefinition") << 8 << 17 << recursiveUsages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
+ QList<QQmlLSUtils::Location> expectedUsages;
const auto testFileName = testFile("findUsages/recursive/recursive.qml");
const auto testFileContent = readFileContent(testFileName);
const auto otherFileName = testFile("findUsages/recursive/RecursiveInOtherFile.qml");
const auto otherFileContent = readFileContent(otherFileName);
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 27, 61,
- strlen("recursive"));
- expectedUsages << QQmlLSUtilsLocation::from(otherFileName, otherFileContent, 4, 14,
- strlen("recursive"));
- expectedUsages << QQmlLSUtilsLocation::from(otherFileName, otherFileContent, 6, 24,
- strlen("recursive"));
- expectedUsages << QQmlLSUtilsLocation::from(otherFileName, otherFileContent, 6, 34,
- strlen("recursive"));
- expectedUsages << QQmlLSUtilsLocation::from(otherFileName, otherFileContent, 6, 51,
- strlen("recursive"));
- expectedUsages << QQmlLSUtilsLocation::from(otherFileName, otherFileContent, 6, 68,
- strlen("recursive"));
- expectedUsages << QQmlLSUtilsLocation::from(otherFileName, otherFileContent, 8, 20,
- strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 27, 61,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 4, 14,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 6, 24,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 6, 34,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 6, 51,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 6, 68,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 8, 20,
+ strlen("recursive"));
const auto recursiveUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findFunctionUsageFromOtherFile") << 27 << 64 << recursiveUsages;
@@ -909,26 +967,38 @@ void tst_qmlls_utils::findUsages_data()
const auto otherFileName = testFile("findUsages/signalsAndHandlers/widthChangedInAnotherFile.qml");
const auto otherFileContent = readFileContent(otherFileName);
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 8, 12, strlen("helloSignal"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 11, 9, strlen("helloSignal"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 13, 13, strlen("helloSignal"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 17, 17, strlen("helloSignal"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 21, 9, strlen("helloSignal"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 39, 5, strlen("onHelloSignal"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 12,
+ strlen("helloSignal"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 11, 9,
+ strlen("helloSignal"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 13, 13,
+ strlen("helloSignal"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 17, 17,
+ strlen("helloSignal"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 21, 9,
+ strlen("helloSignal"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 39, 5,
+ strlen("onHelloSignal"));
const auto helloSignalUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findQmlSignalUsageFromDefinition") << 8 << 17 << helloSignalUsages;
QTest::addRow("findQmlSignalUsageFromUsage") << 13 << 17 << helloSignalUsages;
QTest::addRow("findQmlSignalUsageFromHandler") << 39 << 11 << helloSignalUsages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(otherFileName, otherFileContent, 5, 5, strlen("onWidthChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 23, 13, strlen("widthChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 27, 17, strlen("widthChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 28, 20, strlen("widthChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 34, 20, strlen("widthChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 33, 13, strlen("widthChanged"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 5, 5,
+ strlen("onWidthChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 13,
+ strlen("widthChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 27, 17,
+ strlen("widthChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 28, 20,
+ strlen("widthChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 34, 20,
+ strlen("widthChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 33, 13,
+ strlen("widthChanged"));
const auto widthChangedUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findCppSignalUsageFromUsage") << 27 << 23 << widthChangedUsages;
QTest::addRow("findCppSignalUsageFromQualifiedUsage") << 28 << 23 << widthChangedUsages;
@@ -938,11 +1008,11 @@ void tst_qmlls_utils::findUsages_data()
{
const auto testFileName = testFile("findUsages/binding/binding.qml");
const auto testFileContent = readFileContent(testFileName);
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 9, 18,
- strlen("helloPropertyBinding"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 10, 5,
- strlen("helloPropertyBinding"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 18,
+ strlen("helloPropertyBinding"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 5,
+ strlen("helloPropertyBinding"));
const auto helloPropertyBindingUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findBindingUsagesFromDefinition") << 9 << 21 << helloPropertyBindingUsages;
QTest::addRow("findBindingUsagesFromBinding") << 10 << 19 << helloPropertyBindingUsages;
@@ -951,80 +1021,107 @@ void tst_qmlls_utils::findUsages_data()
const auto testFileName = testFile("findUsages/signalsAndHandlers/signalAndHandlers2.qml");
const auto testFileContent = readFileContent(testFileName);
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 7, 14, strlen("myHelloHandler"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 8, 20, strlen("myHelloHandler"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 14, 29, strlen("myHelloHandler"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 15, 24, strlen("myHelloHandler"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 23, 17, strlen("myHelloHandler"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 24, 24, strlen("myHelloHandler"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 25, 21, strlen("myHelloHandler"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 33, 19, strlen("myHelloHandler"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 42, 29, strlen("myHelloHandler"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 7, 14,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 20,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 14, 29,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 15, 24,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 17,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 24, 24,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 25, 21,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 33, 19,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 42, 29,
+ strlen("myHelloHandler"));
const auto myHelloHandlerUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findJSMethodFromUsageInBinding") << 8 << 27 << myHelloHandlerUsages;
QTest::addRow("findJSMethodFromDefinition") << 7 << 22 << myHelloHandlerUsages;
QTest::addRow("findJSMethodFromDefinition2") << 7 << 9 << myHelloHandlerUsages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 13, 18, strlen("checkHandlers"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 14, 5,
- strlen("onCheckHandlersChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 17, 9,
- strlen("checkHandlersChanged"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 13, 18,
+ strlen("checkHandlers"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 14, 5,
+ strlen("onCheckHandlersChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 17, 9,
+ strlen("checkHandlersChanged"));
const auto checkHandlersUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findQmlPropertyHandlerFromDefinition") << 13 << 18 << checkHandlersUsages;
QTest::addRow("findQmlPropertyHandlerFromHandler") << 14 << 5 << checkHandlersUsages;
QTest::addRow("findQmlPropertyHandlerFromSignalCall") << 17 << 9 << checkHandlersUsages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 15, 5,
- strlen("onChildrenChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 18, 9, strlen("childrenChanged"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 15, 5,
+ strlen("onChildrenChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 18, 9,
+ strlen("childrenChanged"));
const auto checkCppHandlersUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findCppPropertyHandlerFromHandler") << 15 << 5 << checkCppHandlersUsages;
QTest::addRow("findCppPropertyHandlerFromSignalCall") << 18 << 9 << checkCppHandlersUsages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 20, 18, strlen("_"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 23, 5, strlen("on_Changed"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 27, 9, strlen("_Changed"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 20, 18,
+ strlen("_"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 5,
+ strlen("on_Changed"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 27, 9,
+ strlen("_Changed"));
const auto checkHandlersUsages2 = makeUsages(testFileName, expectedUsages);
QTest::addRow("findQmlPropertyHandler2FromDefinition") << 20 << 18 << checkHandlersUsages2;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 21, 18, strlen("______42"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 24, 5,
- strlen("on______42Changed"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 28, 9, strlen("______42Changed"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 21, 18,
+ strlen("______42"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 24, 5,
+ strlen("on______42Changed"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 28, 9,
+ strlen("______42Changed"));
const auto checkHandlersUsages3 = makeUsages(testFileName, expectedUsages);
QTest::addRow("findQmlPropertyHandler3FromDefinition") << 21 << 18 << checkHandlersUsages3;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 22, 18, strlen("_123a"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 25, 5, strlen("on_123AChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 29, 9, strlen("_123aChanged"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 22, 18,
+ strlen("_123a"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 25, 5,
+ strlen("on_123AChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 29, 9,
+ strlen("_123aChanged"));
const auto checkHandlersUsages4 = makeUsages(testFileName, expectedUsages);
QTest::addRow("findQmlPropertyHandler4FromDefinition") << 22 << 18 << checkHandlersUsages4;
}
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
+ QList<QQmlLSUtils::Location> expectedUsages;
const auto testFileName = testFile("findUsages/connections/connections.qml");
const auto testFileContent = readFileContent(testFileName);
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 9, 9, strlen("onClicked"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 17, 23, strlen("clicked"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 33, 15, strlen("clicked"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 16, 22, strlen("onClicked"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 34, 15, strlen("clicked"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 18, 23, strlen("clicked"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 28, 9, strlen("onClicked"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 35, 15, strlen("clicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 9,
+ strlen("onClicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 17, 23,
+ strlen("clicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 33, 15,
+ strlen("clicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 16, 22,
+ strlen("onClicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 34, 15,
+ strlen("clicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 18, 23,
+ strlen("clicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 28, 9,
+ strlen("onClicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 35, 15,
+ strlen("clicked"));
const auto signalInConnection = makeUsages(testFileName, expectedUsages);
QTest::addRow("findSignalsInConnectionFromSignal") << 33 << 15 << signalInConnection;
QTest::addRow("findSignalsInConnectionFromHandler") << 9 << 9 << signalInConnection;
@@ -1035,41 +1132,51 @@ void tst_qmlls_utils::findUsages_data()
testFile("findUsages/parametersAndDeconstruction/parametersAndDeconstruction.qml");
const auto testFileContent = readFileContent(testFileName);
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 8, 30, strlen("a"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 9, 16, strlen("a"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 30,
+ strlen("a"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 16,
+ strlen("a"));
const auto aParamUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findMethodParameterA") << 9 << 16 << aParamUsages;
QTest::addRow("findMethodParameterAFromUsage") << 8 << 30 << aParamUsages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 8, 50, strlen("x"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 9, 28, strlen("x"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 50,
+ strlen("x"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 28,
+ strlen("x"));
const auto xParamUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findMethodParameterXDeconstructed") << 8 << 50 << xParamUsages;
QTest::addRow("findMethodParameterXDeconstructedFromUsage") << 9 << 28 << xParamUsages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 8, 53, strlen("y"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 9, 32, strlen("y"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 53,
+ strlen("y"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 32,
+ strlen("y"));
const auto yParamUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findMethodParameterYDeconstructed") << 8 << 53 << yParamUsages;
QTest::addRow("findMethodParameterYDeconstructedFromUsage") << 9 << 32 << yParamUsages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 8, 59, strlen("z"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 9, 36, strlen("z"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 59,
+ strlen("z"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 36,
+ strlen("z"));
const auto zParamUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("findMethodParameterZDeconstructed") << 8 << 59 << zParamUsages;
QTest::addRow("findMethodParameterZDeconstructedFromUsage") << 9 << 36 << zParamUsages;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 13, 14, strlen("a"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 14, 17, strlen("a"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 13, 14,
+ strlen("a"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 14, 17,
+ strlen("a"));
const auto deconstructedAUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("deconstructed") << 14 << 17 << deconstructedAUsages;
QTest::addRow("deconstructedFromDefinition") << 13 << 14 << deconstructedAUsages;
@@ -1081,12 +1188,17 @@ void tst_qmlls_utils::findUsages_data()
const auto otherFileName = testFile("findUsages/groupPropertyUsage/fontFamilyUsage.qml");
const auto otherFileContent = readFileContent(otherFileName);
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(otherFileName, otherFileContent, 5, 34, strlen("family"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 14, 17, strlen("family"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 23, 35, strlen("family"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 23, 10, strlen("family"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 33, 48, strlen("family"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 5, 34,
+ strlen("family"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 14, 17,
+ strlen("family"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 35,
+ strlen("family"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 10,
+ strlen("family"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 33, 48,
+ strlen("family"));
const auto groupPropertyUsages1 = makeUsages(testFileName, expectedUsages);
QTest::addRow("groupPropertyUsages1") << 14 << 17 << groupPropertyUsages1;
const auto groupPropertyUsages1FromOtherFile =
@@ -1095,13 +1207,19 @@ void tst_qmlls_utils::findUsages_data()
<< 5 << 37 << groupPropertyUsages1FromOtherFile;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 23, 5, strlen("font"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 24, 5, strlen("font"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 12, 13, strlen("font"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 23, 30, strlen("font"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 32, 41, strlen("font"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 33, 43, strlen("font"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 5,
+ strlen("font"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 24, 5,
+ strlen("font"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 12, 13,
+ strlen("font"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 30,
+ strlen("font"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 32, 41,
+ strlen("font"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 33, 43,
+ strlen("font"));
const auto groupPropertyUsages2 = makeUsages(testFileName, expectedUsages);
QTest::addRow("groupPropertyUsages2") << 23 << 5 << groupPropertyUsages2;
}
@@ -1110,20 +1228,26 @@ void tst_qmlls_utils::findUsages_data()
const auto testFileName =
testFile("findUsages/attachedPropertyUsage/attachedPropertyUsage.qml");
const auto testFileContent = readFileContent(testFileName);
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 9, 5, strlen("Keys"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 12, 25, strlen("Keys"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 5,
+ strlen("Keys"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 12, 25,
+ strlen("Keys"));
const auto attachedPropertyUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("attachedPropertyUsages") << 12 << 25 << attachedPropertyUsages;
}
{
const auto testFileName = testFile("findUsages/inlineComponents/inlineComponents.qml");
const auto testFileContent = readFileContent(testFileName);
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 9, 22, strlen("foo"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 10, 44, strlen("foo"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 14, 27, strlen("foo"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 20, 20, strlen("foo"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 22,
+ strlen("foo"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 44,
+ strlen("foo"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 14, 27,
+ strlen("foo"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 20, 20,
+ strlen("foo"));
const auto inlineUsages = makeUsages(testFileName, expectedUsages);
QTest::addRow("inlineUsagesFromProperty") << 9 << 22 << inlineUsages;
QTest::addRow("inlineUsagesFromUsageOfBaseProperty") << 14 << 27 << inlineUsages;
@@ -1132,26 +1256,38 @@ void tst_qmlls_utils::findUsages_data()
{
const auto testFileName = testFile("findUsages/propertyChanges/propertyChanges.qml");
const auto testFileContent = readFileContent(testFileName);
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 8, 9, strlen("onClicked"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 16, 21, strlen("onClicked"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 19, 25, strlen("onClicked"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 25, 17, strlen("onClicked"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 9,
+ strlen("onClicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 16, 21,
+ strlen("onClicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 19, 25,
+ strlen("onClicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 25, 17,
+ strlen("onClicked"));
const auto propertyChanges = makeUsages(testFileName, expectedUsages);
QTest::addRow("propertyChanges1") << 16 << 21 << propertyChanges;
}
{
const auto testFileName = testFile("findUsages/bindings/bindings.qml");
const auto testFileContent = readFileContent(testFileName);
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 11, 23, strlen("patronChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 14, 27, strlen("patronChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 21, 27, strlen("patronChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 27, 19, strlen("patronChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 27, 41, strlen("patronChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 34, 17, strlen("patronChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 13, 20, strlen("patronChanged"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 20, 23, strlen("\"patronChanged\""));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 11, 23,
+ strlen("patronChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 14, 27,
+ strlen("patronChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 21, 27,
+ strlen("patronChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 27, 19,
+ strlen("patronChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 27, 41,
+ strlen("patronChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 34, 17,
+ strlen("patronChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 13, 20,
+ strlen("patronChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 20, 23,
+ strlen("\"patronChanged\""));
const auto bindings = makeUsages(testFileName, expectedUsages);
QTest::addRow("propertyInBindingsFromDecl") << 11 << 23 << bindings;
QTest::addRow("generalizedGroupPropertyBindings") << 27 << 19 << bindings;
@@ -1162,28 +1298,33 @@ void tst_qmlls_utils::findUsages_data()
const auto otherFileName = testFile("findUsages/enums/EnumsFromAnotherFile.qml");
const auto otherFileContent = readFileContent(otherFileName);
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 9, 9, strlen("Patron"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 22, 35, strlen("Patron"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 23, 34, strlen("Patron"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 9,
+ strlen("Patron"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 22, 35,
+ strlen("Patron"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 34,
+ strlen("Patron"));
const auto enums = makeUsages(testFileName, expectedUsages);
QTest::addRow("enumValuesFromDeclaration") << 9 << 9 << enums;
QTest::addRow("enumValuesFromUsage") << 22 << 35 << enums;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 8, 10, strlen("Cats"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 22, 30, strlen("Cats"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 10,
+ strlen("Cats"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 22, 30,
+ strlen("Cats"));
const auto enums = makeUsages(testFileName, expectedUsages);
QTest::addRow("enumNameFromDeclaration") << 8 << 10 << enums;
QTest::addRow("enumNameFromUsage") << 22 << 30 << enums;
}
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 26, 46,
- strlen("FromAnotherUniverse"));
- expectedUsages << QQmlLSUtilsLocation::from(otherFileName, otherFileContent, 4, 68,
- strlen("FromAnotherUniverse"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 26, 46,
+ strlen("FromAnotherUniverse"));
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 4, 68,
+ strlen("FromAnotherUniverse"));
const auto enums = makeUsages(testFileName, expectedUsages);
QTest::addRow("enumNameFromDeclarationInOtherFile") << 26 << 50 << enums;
const auto enumsFromOtherFile = makeUsages(otherFileName, expectedUsages);
@@ -1194,13 +1335,19 @@ void tst_qmlls_utils::findUsages_data()
const auto testFileName = testFile("findUsages/inlineComponents/inlineComponents2.qml");
const auto testFileContent = readFileContent(testFileName);
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 4, 15, strlen("MyIC"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 5, 5, strlen("MyIC"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 5, 12, strlen("MyIC"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 5, 19, strlen("MyIC"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 6, 19, strlen("MyIC"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 6, 26, strlen("MyIC"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 4, 15,
+ strlen("MyIC"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 5, 5,
+ strlen("MyIC"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 5, 12,
+ strlen("MyIC"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 5, 19,
+ strlen("MyIC"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 6, 19,
+ strlen("MyIC"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 6, 26,
+ strlen("MyIC"));
const auto inlineComponents = makeUsages(testFileName, expectedUsages);
QTest::addRow("findICUsagesFromDefinition") << 4 << 16 << inlineComponents;
QTest::addRow("findICUsagesFromDefinition2") << 4 << 9 << inlineComponents;
@@ -1215,20 +1362,20 @@ void tst_qmlls_utils::findUsages_data()
testFile("findUsages/inlineComponents/InlineComponentProvider.qml");
const auto providerFileContent = readFileContent(providerFileName);
{
- QList<QQmlLSUtilsLocation> expectedUsages;
- expectedUsages << QQmlLSUtilsLocation::from(providerFileName, providerFileContent, 4,
- 15, strlen("IC1"));
- expectedUsages << QQmlLSUtilsLocation::from(providerFileName, providerFileContent, 5,
- 36, strlen("IC1"));
- expectedUsages << QQmlLSUtilsLocation::from(providerFileName, providerFileContent, 7, 5,
- strlen("IC1"));
- expectedUsages << QQmlLSUtilsLocation::from(providerFileName, providerFileContent, 17,
- 13, strlen("IC1"));
-
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 25, 38,
- strlen("IC1"));
- expectedUsages << QQmlLSUtilsLocation::from(testFileName, testFileContent, 25, 84,
- strlen("IC1"));
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(providerFileName, providerFileContent, 4,
+ 15, strlen("IC1"));
+ expectedUsages << QQmlLSUtils::Location::from(providerFileName, providerFileContent, 5,
+ 36, strlen("IC1"));
+ expectedUsages << QQmlLSUtils::Location::from(providerFileName, providerFileContent, 7,
+ 5, strlen("IC1"));
+ expectedUsages << QQmlLSUtils::Location::from(providerFileName, providerFileContent, 17,
+ 13, strlen("IC1"));
+
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 25, 38,
+ strlen("IC1"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 25, 84,
+ strlen("IC1"));
{
const auto usagesForTestFile = makeUsages(testFileName, expectedUsages);
@@ -1255,7 +1402,13 @@ void tst_qmlls_utils::findUsages()
QFETCH(int, line);
QFETCH(int, character);
QFETCH(UsageData, data);
- QVERIFY(std::is_sorted(data.expectedUsages.begin(), data.expectedUsages.end()));
+
+ {
+ auto usagesInFilename = data.expectedUsages.usagesInFilename();
+ QVERIFY(std::is_sorted(usagesInFilename.begin(), usagesInFilename.end()));
+ auto usagesInFile = data.expectedUsages.usagesInFile();
+ QVERIFY(std::is_sorted(usagesInFile.begin(), usagesInFile.end()));
+ }
auto [env, file] = createEnvironmentAndLoadFile(data.testFileName);
@@ -1275,17 +1428,19 @@ void tst_qmlls_utils::findUsages()
if constexpr (enable_debug_output) {
if (usages != data.expectedUsages) {
qDebug() << "Got:\n";
- for (auto &x : usages) {
+ for (auto &x : usages.usagesInFile()) {
qDebug() << x.filename << "(" << x.sourceLocation.startLine << ", "
<< x.sourceLocation.startColumn << "), " << x.sourceLocation.offset << "+"
<< x.sourceLocation.length;
}
+ qDebug() << "with usages in filenames:" << usages.usagesInFilename();
qDebug() << "But expected: \n";
- for (auto &x : data.expectedUsages) {
+ for (auto &x : data.expectedUsages.usagesInFile()) {
qDebug() << x.filename << "(" << x.sourceLocation.startLine << ", "
<< x.sourceLocation.startColumn << "), " << x.sourceLocation.offset << "+"
<< x.sourceLocation.length;
}
+ qDebug() << "with usages in filenames:" << data.expectedUsages.usagesInFilename();
}
}
@@ -1299,7 +1454,7 @@ void tst_qmlls_utils::renameUsages_data()
QTest::addColumn<int>("line");
QTest::addColumn<int>("character");
QTest::addColumn<QString>("newName");
- QTest::addColumn<QList<QQmlLSUtilsEdit>>("expectedRenames");
+ QTest::addColumn<QQmlLSUtils::RenameUsages>("expectedRenames");
QTest::addColumn<QString>("expectedError");
const QString testFileName = testFile(u"JSUsages.qml"_s);
@@ -1308,97 +1463,140 @@ void tst_qmlls_utils::renameUsages_data()
const QString testFileFromAnotherFileContent = readFileContent(testFileNameFromAnotherFile);
const QString noError;
- const QList<QQmlLSUtilsEdit> noRenames;
-
- QList<QQmlLSUtilsEdit> methodFRename{
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 72, 14, strlen("recursive"),
- u"newNameNewMe"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 74, 24, strlen("recursive"),
- u"newNameNewMe"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 74, 34, strlen("recursive"),
- u"newNameNewMe"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 74, 51, strlen("recursive"),
- u"newNameNewMe"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 74, 68, strlen("recursive"),
- u"newNameNewMe"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 76, 20, strlen("recursive"),
- u"newNameNewMe"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 79, 34, strlen("recursive"),
- u"newNameNewMe"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 84, 27, strlen("recursive"),
- u"newNameNewMe"_s),
+ const QQmlLSUtils::RenameUsages noRenames;
+
+ QQmlLSUtils::RenameUsages methodFRename{
+ {
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 72, 14, strlen("recursive"),
+ u"newNameNewMe"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 74, 24, strlen("recursive"),
+ u"newNameNewMe"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 74, 34, strlen("recursive"),
+ u"newNameNewMe"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 74, 51, strlen("recursive"),
+ u"newNameNewMe"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 74, 68, strlen("recursive"),
+ u"newNameNewMe"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 76, 20, strlen("recursive"),
+ u"newNameNewMe"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 79, 34, strlen("recursive"),
+ u"newNameNewMe"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 84, 27, strlen("recursive"),
+ u"newNameNewMe"_s),
+ },
+ {}
};
- QList<QQmlLSUtilsEdit> JSIdentifierSumRename{
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 8, 13, strlen("sum"),
- u"sumsumsum123"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 10, 13, strlen("sum"),
- u"sumsumsum123"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 10, 19, strlen("sum"),
- u"sumsumsum123"_s),
+ QQmlLSUtils::RenameUsages JSIdentifierSumRename{
+ {
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 8, 13, strlen("sum"),
+ u"sumsumsum123"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 10, 13, strlen("sum"),
+ u"sumsumsum123"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 10, 19, strlen("sum"),
+ u"sumsumsum123"_s),
+ },
+ {}
};
- QList<QQmlLSUtilsEdit> qmlSignalRename{
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 88, 12, strlen("helloSignal"),
- u"finalSignal"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 91, 9, strlen("helloSignal"),
- u"finalSignal"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 93, 13, strlen("helloSignal"),
- u"finalSignal"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 97, 17, strlen("helloSignal"),
- u"finalSignal"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 101, 9, strlen("helloSignal"),
- u"finalSignal"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 119, 5, strlen("onHelloSignal"),
- u"onFinalSignal"_s),
+ QQmlLSUtils::RenameUsages qmlSignalRename{
+ {
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 88, 12,
+ strlen("helloSignal"), u"finalSignal"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 91, 9, strlen("helloSignal"),
+ u"finalSignal"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 93, 13,
+ strlen("helloSignal"), u"finalSignal"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 97, 17,
+ strlen("helloSignal"), u"finalSignal"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 101, 9,
+ strlen("helloSignal"), u"finalSignal"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 119, 5,
+ strlen("onHelloSignal"), u"onFinalSignal"_s),
+ },
+ {}
};
- QList<QQmlLSUtilsEdit> helloPropertyRename{
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 17, 18, strlen("helloProperty"),
- u"freshPropertyName"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 24, 13, strlen("helloProperty"),
- u"freshPropertyName"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 24, 29, strlen("helloProperty"),
- u"freshPropertyName"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 65, 60, strlen("helloProperty"),
- u"freshPropertyName"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 151, 9, strlen("helloPropertyChanged"),
- u"freshPropertyNameChanged"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 153, 5,
- strlen("onHelloPropertyChanged"), u"onFreshPropertyNameChanged"_s),
- QQmlLSUtilsEdit::from(testFileNameFromAnotherFile, testFileFromAnotherFileContent, 12, 16,
- strlen("helloProperty"), u"freshPropertyName"_s),
+ QQmlLSUtils::RenameUsages helloPropertyRename{
+ {
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 17, 18,
+ strlen("helloProperty"), u"freshPropertyName"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 24, 13,
+ strlen("helloProperty"), u"freshPropertyName"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 24, 29,
+ strlen("helloProperty"), u"freshPropertyName"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 65, 60,
+ strlen("helloProperty"), u"freshPropertyName"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 151, 9,
+ strlen("helloPropertyChanged"),
+ u"freshPropertyNameChanged"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 153, 5,
+ strlen("onHelloPropertyChanged"),
+ u"onFreshPropertyNameChanged"_s),
+ QQmlLSUtils::Edit::from(testFileNameFromAnotherFile, testFileFromAnotherFileContent,
+ 12, 16, strlen("helloProperty"), u"freshPropertyName"_s),
+ },
+ {}
};
- QList<QQmlLSUtilsEdit> nestedComponentRename{
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 42, 15, strlen("NestedComponent"),
- u"SuperInlineComponent"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 61, 5, strlen("NestedComponent"),
- u"SuperInlineComponent"_s),
+ QQmlLSUtils::RenameUsages nestedComponentRename{
+ {
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 42, 15,
+ strlen("NestedComponent"), u"SuperInlineComponent"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 61, 5,
+ strlen("NestedComponent"), u"SuperInlineComponent"_s),
+ },
+ {}
};
- QList<QQmlLSUtilsEdit> myNestedIdRename{
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 62, 13, strlen("myNested"),
- u"freshNewIdForMyNested"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 65, 17, strlen("myNested"),
- u"freshNewIdForMyNested"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 66, 17, strlen("myNested"),
- u"freshNewIdForMyNested"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 67, 17, strlen("myNested"),
- u"freshNewIdForMyNested"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 68, 17, strlen("myNested"),
- u"freshNewIdForMyNested"_s),
- QQmlLSUtilsEdit::from(testFileName, testFileContent, 69, 17, strlen("myNested"),
- u"freshNewIdForMyNested"_s),
+ QQmlLSUtils::RenameUsages myNestedIdRename{
+ {
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 62, 13, strlen("myNested"),
+ u"freshNewIdForMyNested"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 65, 17, strlen("myNested"),
+ u"freshNewIdForMyNested"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 66, 17, strlen("myNested"),
+ u"freshNewIdForMyNested"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 67, 17, strlen("myNested"),
+ u"freshNewIdForMyNested"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 68, 17, strlen("myNested"),
+ u"freshNewIdForMyNested"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 69, 17, strlen("myNested"),
+ u"freshNewIdForMyNested"_s),
+ },
+ {}
};
- std::sort(methodFRename.begin(), methodFRename.end());
- std::sort(JSIdentifierSumRename.begin(), JSIdentifierSumRename.end());
- std::sort(qmlSignalRename.begin(), qmlSignalRename.end());
- std::sort(helloPropertyRename.begin(), helloPropertyRename.end());
- std::sort(helloPropertyRename.begin(), helloPropertyRename.end());
- std::sort(nestedComponentRename.begin(), nestedComponentRename.end());
- std::sort(myNestedIdRename.begin(), myNestedIdRename.end());
+ const QString renameFileQml = testFile("renaming/main.qml");
+ const QString renameFileQmlContent = readFileContent(renameFileQml);
+ const QQmlLSUtils::RenameUsages renameComponent1{
+ {
+ QQmlLSUtils::Edit::from(renameFileQml, renameFileQmlContent, 4, 5,
+ strlen("RenameMe"), u"FreshNewComponentName"_s),
+ },
+ {
+ { testFile("renaming/RenameMe.qml"),
+ testFile(u"renaming/FreshNewComponentName.qml"_s) },
+ }
+ };
+ const QQmlLSUtils::RenameUsages renameComponent2{
+ {
+ QQmlLSUtils::Edit::from(renameFileQml, renameFileQmlContent, 5, 5,
+ strlen("RenameMe2"), u"AnotherOneThankYou"_s),
+ },
+ {
+ { testFile("renaming/RenameMe2.ui.qml"),
+ testFile(u"renaming/AnotherOneThankYou.ui.qml"_s) },
+ }
+ };
+ const QQmlLSUtils::RenameUsages renameComponentNamedByQmldir{
+ {
+ QQmlLSUtils::Edit::from(renameFileQml, renameFileQmlContent, 6, 5,
+ strlen("HelloWorld"), u"AnotherOneThankYou"_s),
+ },
+ // make sure that the file itself does not get renamed
+ {}
+ };
const QString parserError = u"Invalid EcmaScript identifier!"_s;
@@ -1461,6 +1659,16 @@ void tst_qmlls_utils::renameUsages_data()
QTest::addRow("JSIdentifierStartsWithNumber")
<< testFileName << 67 << 13 << u"123"_s << noRenames << parserError;
+
+ QTest::addRow("renameQmlFile") << testFile(u"renaming/main.qml"_s) << 4 << 9
+ << u"FreshNewComponentName"_s << renameComponent1 << noError;
+
+ QTest::addRow("renameUiQmlFile") << testFile(u"renaming/main.qml"_s) << 5 << 9
+ << u"AnotherOneThankYou"_s << renameComponent2 << noError;
+
+ QTest::addRow("renameQmlFileRenamedByQmldir")
+ << testFile(u"renaming/main.qml"_s) << 6 << 8 << u"AnotherOneThankYou"_s
+ << renameComponentNamedByQmldir << noError;
}
void tst_qmlls_utils::renameUsages()
@@ -1471,10 +1679,15 @@ void tst_qmlls_utils::renameUsages()
QFETCH(int, line);
QFETCH(int, character);
QFETCH(QString, newName);
- QFETCH(QList<QQmlLSUtilsEdit>, expectedRenames);
+ QFETCH(QQmlLSUtils::RenameUsages, expectedRenames);
QFETCH(QString, expectedError);
- QVERIFY(std::is_sorted(expectedRenames.begin(), expectedRenames.end()));
+ {
+ const auto renameInFile = expectedRenames.renameInFile();
+ QVERIFY(std::is_sorted(renameInFile.constBegin(), renameInFile.constEnd()));
+ const auto renameInFilename = expectedRenames.renameInFilename();
+ QVERIFY(std::is_sorted(renameInFilename.begin(), renameInFilename.end()));
+ }
auto [env, file] = createEnvironmentAndLoadFile(filePath);
@@ -1505,21 +1718,29 @@ void tst_qmlls_utils::renameUsages()
if constexpr (enable_debug_output) {
if (edits != expectedRenames) {
qDebug() << "Got:\n";
- for (auto &x : edits) {
+ for (auto &x : edits.renameInFile()) {
qDebug() << x.replacement << x.location.filename << "("
<< x.location.sourceLocation.startLine << ", "
<< x.location.sourceLocation.startColumn << "), "
<< x.location.sourceLocation.offset << "+"
<< x.location.sourceLocation.length;
}
+ qDebug() << "with renames in filenames:";
+ for (auto &x : edits.renameInFilename()) {
+ qDebug() << x.oldFilename << "->" << x.newFilename;
+ }
qDebug() << "But expected: \n";
- for (auto &x : expectedRenames) {
+ for (auto &x : expectedRenames.renameInFile()) {
qDebug() << x.replacement << x.location.filename << "("
<< x.location.sourceLocation.startLine << ", "
<< x.location.sourceLocation.startColumn << "), "
<< x.location.sourceLocation.offset << "+"
<< x.location.sourceLocation.length;
}
+ qDebug() << "with renames in filenames:";
+ for (auto &x : expectedRenames.renameInFilename()) {
+ qDebug() << x.oldFilename << "->" << x.newFilename;
+ }
}
}
QCOMPARE(edits, expectedRenames);
@@ -1676,11 +1897,13 @@ void tst_qmlls_utils::resolveExpressionType_data()
// keep in mind that line and character are starting at 1!
QTest::addColumn<int>("line");
QTest::addColumn<int>("character");
- QTest::addColumn<QQmlLSUtilsResolveOptions>("resolveOption");
+ QTest::addColumn<QQmlLSUtils::ResolveOptions>("resolveOption");
QTest::addColumn<QString>("expectedFile");
// startline of the owners definition
QTest::addColumn<int>("expectedLine");
- QTest::addColumn<QQmlLSUtilsIdentifierType>("expectedType");
+ QTest::addColumn<QQmlLSUtils::IdentifierType>("expectedType");
+
+ using namespace QQmlLSUtils;
const int noLine = -1;
const QString noFile;
@@ -1828,10 +2051,10 @@ void tst_qmlls_utils::resolveExpressionType()
QFETCH(QString, filePath);
QFETCH(int, line);
QFETCH(int, character);
- QFETCH(QQmlLSUtilsResolveOptions, resolveOption);
+ QFETCH(QQmlLSUtils::ResolveOptions, resolveOption);
QFETCH(QString, expectedFile);
QFETCH(int, expectedLine);
- QFETCH(QQmlLSUtilsIdentifierType, expectedType);
+ QFETCH(QQmlLSUtils::IdentifierType, expectedType);
// they all start at 1.
Q_ASSERT(line > 0);
@@ -3930,97 +4153,4 @@ void tst_qmlls_utils::cmakeBuildCommand()
QCOMPARE(QQmlLSUtils::cmakeBuildCommand(path), expected);
}
-void tst_qmlls_utils::qdochtmlparser_data()
-{
- QTest::addColumn<QString>("filePath");
- QTest::addColumn<QDocHtmlExtractor::Element>("element");
- QTest::addColumn<QDocHtmlExtractor::ExtractionMode>("extractionMode");
- QTest::addColumn<QString>("expectedDocumentation");
-
- QTest::addRow("qml-object-type-extended-plaintext")
- << testFile("qdochtmlparser/qml-qtqml-qtobject.html")
- << QDocHtmlExtractor::Element{"QtObject", QDocHtmlExtractor::ElementType::QmlType}
- << QDocHtmlExtractor::ExtractionMode::Extended
- << R"(The QtObject type is a non-visual element which contains only the objectName property.
-It can be useful to create a QtObject if you need an extremely lightweight type to enclose a set of custom properties:
-
- import QtQuick
-
- Item {
- QtObject {
- id: attributes
- property string name
- property int size
- property variant attributes
- }
-
- Text { text: attributes.name }
- }
-
-It can also be useful for C++ integration, as it is just a plain QObject. See the QObject documentation for further details.)";
-
- QTest::addRow("qml-object-type-simplified-plaintext")
- << testFile("qdochtmlparser/qml-qtqml-qtobject.html")
- << QDocHtmlExtractor::Element{"QtObject", QDocHtmlExtractor::ElementType::QmlType}
- << QDocHtmlExtractor::ExtractionMode::Simplified
- << R"(A basic QML type.)";
-
- QTest::addRow("qml-property-simplified-plaintext")
- << testFile("qdochtmlparser/qml-qtqml-qtobject.html")
- << QDocHtmlExtractor::Element{"objectName",QDocHtmlExtractor::ElementType::QmlProperty}
- << QDocHtmlExtractor::ExtractionMode::Simplified
- << R"(This property holds the QObject::objectName for this specific object instance.)";
-
- QTest::addRow("qml-property-simplified-plaintext-from-Qt5")
- << testFile("qdochtmlparser/qml-qtqml-qtobject-qt-5.html") << QDocHtmlExtractor::Element{"objectName", QDocHtmlExtractor::ElementType::QmlProperty}
- << QDocHtmlExtractor::ExtractionMode::Simplified
- << R"(This property holds the QObject::objectName for this specific object instance.)";
-
- QTest::addRow("qml-property-simplified-plaintext")
- << testFile("qdochtmlparser/qml-qtquick-item.html") << QDocHtmlExtractor::Element{"width", QDocHtmlExtractor::ElementType::QmlProperty}
- << QDocHtmlExtractor::ExtractionMode::Simplified
- << R"(Defines the item's position and size. The default value is 0.)";
-
- QTest::addRow("qml-group-property-simplified-plaintext")
- << testFile("qdochtmlparser/qml-qtquick-item.html") << QDocHtmlExtractor::Element{"anchors.fill", QDocHtmlExtractor::ElementType::QmlProperty}
- << QDocHtmlExtractor::ExtractionMode::Simplified
- << R"(Anchors provide a way to position an item by specifying its relationship with other items.)";
- QTest::addRow("qml-functions")
- << testFile("qdochtmlparser/qml-qtquick-item.html") << QDocHtmlExtractor::Element{"mapFromGlobal", QDocHtmlExtractor::ElementType::QmlMethod}
- << QDocHtmlExtractor::ExtractionMode::Simplified
- << "Maps the point (x, y), which is in the global coordinate system, to the item's coordinate system,"
- " and returns a point matching the mapped coordinate.";
-
- QTest::addRow("qml-functions-list")
- << testFile("qdochtmlparser/qml-qtquick-item.html") << QDocHtmlExtractor::Element{"mapFromItem", QDocHtmlExtractor::ElementType::QmlMethod}
- << QDocHtmlExtractor::ExtractionMode::Simplified
- << "Maps the point (x, y) or rect (x, y, width, height), which is in item's coordinate system,"
- " to this item's coordinate system, and returns a point or rect matching the mapped coordinate.";
- QTest::addRow("qml-signal")
- << testFile("qdochtmlparser/qml-qtquick-mousearea.html") << QDocHtmlExtractor::Element{"pressAndHold", QDocHtmlExtractor::ElementType::QmlSignal}
- << QDocHtmlExtractor::ExtractionMode::Simplified
- << "This signal is emitted when there is a long press (currently 800ms). The mouse parameter provides information about the press, "
- "including the x and y position of the press, and which button is pressed.";
-}
-
-void tst_qmlls_utils::qdochtmlparser()
-{
- QFETCH(QString, filePath);
- QFETCH(QDocHtmlExtractor::Element, element);
- QFETCH(QDocHtmlExtractor::ExtractionMode, extractionMode);
- QFETCH(QString, expectedDocumentation);
-
- const auto htmlCode = [](const QString &testFileName) {
- QFile file(testFileName);
- if (file.open(QIODeviceBase::ReadOnly | QIODevice::Text))
- return QString::fromUtf8(file.readAll());
- return QString{};
- }(filePath);
-
-
- QDocHtmlExtractor extractor(htmlCode);
- const auto actual = extractor.extract(element, extractionMode);
- QCOMPARE(actual, expectedDocumentation);
-}
-
QTEST_MAIN(tst_qmlls_utils)
diff --git a/tests/auto/qmlls/utils/tst_qmlls_utils.h b/tests/auto/qmlls/utils/tst_qmlls_utils.h
index 51fa74dd0a..2f1ea19a2c 100644
--- a/tests/auto/qmlls/utils/tst_qmlls_utils.h
+++ b/tests/auto/qmlls/utils/tst_qmlls_utils.h
@@ -80,9 +80,6 @@ private slots:
void cmakeBuildCommand();
- void qdochtmlparser_data();
- void qdochtmlparser();
-
private:
using EnvironmentAndFile = std::tuple<QQmlJS::Dom::DomItem, QQmlJS::Dom::DomItem>;