diff options
Diffstat (limited to 'tests/auto/qmlls')
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>; |