aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp')
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp185
1 files changed, 185 insertions, 0 deletions
diff --git a/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp b/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp
new file mode 100644
index 0000000000..a3293769e5
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp
@@ -0,0 +1,185 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "tst_qmlls_qqmlcodemodel.h"
+
+#include <QtQmlToolingSettings/private/qqmltoolingsettings_p.h>
+#include <QtQmlLS/private/qqmlcodemodel_p.h>
+#include <QtQmlLS/private/qqmllsutils_p.h>
+#include <QtQmlDom/private/qqmldomitem_p.h>
+#include <QtQmlDom/private/qqmldomtop_p.h>
+
+tst_qmlls_qqmlcodemodel::tst_qmlls_qqmlcodemodel() : QQmlDataTest(QT_QQMLCODEMODEL_DATADIR) { }
+
+void tst_qmlls_qqmlcodemodel::buildPathsForFileUrl_data()
+{
+ QTest::addColumn<QString>("pathFromIniFile");
+ QTest::addColumn<QString>("pathFromEnvironmentVariable");
+ QTest::addColumn<QString>("pathFromCommandLine");
+ QTest::addColumn<QString>("expectedPath");
+
+ const QString path1 = u"/Users/helloWorld/build-myProject"_s;
+ const QString path2 = u"/Users/helloWorld/build-custom"_s;
+ const QString path3 = u"/Users/helloWorld/build-12345678"_s;
+
+ QTest::addRow("justCommandLine") << QString() << QString() << path1 << path1;
+ QTest::addRow("all3") << path1 << path2 << path3 << path3;
+
+ QTest::addRow("commandLineOverridesEnvironmentVariable")
+ << QString() << path2 << path3 << path3;
+ QTest::addRow("commandLineOverridesIniFile") << path2 << QString() << path3 << path3;
+
+ QTest::addRow("EnvironmentVariableOverridesIniFile") << path1 << path2 << QString() << path2;
+ QTest::addRow("iniFile") << path1 << QString() << QString() << path1;
+ QTest::addRow("environmentVariable") << QString() << path3 << QString() << path3;
+}
+
+void tst_qmlls_qqmlcodemodel::buildPathsForFileUrl()
+{
+ QFETCH(QString, pathFromIniFile);
+ QFETCH(QString, pathFromEnvironmentVariable);
+ QFETCH(QString, pathFromCommandLine);
+ QFETCH(QString, expectedPath);
+
+ QQmlToolingSettings settings(u"qmlls"_s);
+ if (!pathFromIniFile.isEmpty())
+ settings.addOption("buildDir", pathFromIniFile);
+
+ constexpr char environmentVariable[] = "QMLLS_BUILD_DIRS";
+ qunsetenv(environmentVariable);
+ if (!pathFromEnvironmentVariable.isEmpty()) {
+ qputenv(environmentVariable, pathFromEnvironmentVariable.toUtf8());
+ }
+
+ QmlLsp::QQmlCodeModel model(nullptr, &settings);
+ if (!pathFromCommandLine.isEmpty())
+ model.setBuildPathsForRootUrl(QByteArray(), QStringList{ pathFromCommandLine });
+
+ // use nonexistent path to avoid loading random .qmlls.ini files that might be laying around.
+ // in this case, it should abort the search and the standard value we set in the settings
+ const QByteArray nonExistentUrl =
+ QUrl::fromLocalFile(u"./___thispathdoesnotexist123___/abcdefghijklmnop"_s).toEncoded();
+
+ QStringList result = model.buildPathsForFileUrl(nonExistentUrl);
+ QCOMPARE(result.size(), 1);
+ QCOMPARE(result.front(), expectedPath);
+}
+
+void tst_qmlls_qqmlcodemodel::findFilePathsFromFileNames_data()
+{
+ QTest::addColumn<QStringList>("fileNames");
+ QTest::addColumn<QStringList>("expectedPaths");
+
+ const QString folder = testFile("sourceFolder");
+ const QString subfolder = testFile("sourceFolder/subSourceFolder/subsubSourceFolder");
+
+ QTest::addRow("notExistingFile") << QStringList{ u"notExistingFile.h"_s } << QStringList{};
+
+ QTest::addRow("myqmlelement") << QStringList{ u"myqmlelement.h"_s }
+ << QStringList{ folder + u"/myqmlelement.h"_s,
+ subfolder + u"/myqmlelement.h"_s };
+
+ QTest::addRow("myqmlelement2") << QStringList{ u"myqmlelement2.hpp"_s }
+ << QStringList{ folder + u"/myqmlelement2.hpp"_s };
+
+ QTest::addRow("anotherqmlelement") << QStringList{ u"anotherqmlelement.cpp"_s }
+ << QStringList{ subfolder + u"/anotherqmlelement.cpp"_s };
+}
+
+void tst_qmlls_qqmlcodemodel::findFilePathsFromFileNames()
+{
+ QFETCH(QStringList, fileNames);
+ QFETCH(QStringList, expectedPaths);
+
+ QmlLsp::QQmlCodeModel model;
+ model.setRootUrls({ testFileUrl(u"sourceFolder"_s).toEncoded() });
+
+ auto result = model.findFilePathsFromFileNames(fileNames);
+ // the order only is required for the QCOMPARE
+ std::sort(result.begin(), result.end());
+ std::sort(expectedPaths.begin(), expectedPaths.end());
+
+ QCOMPARE(result, expectedPaths);
+}
+
+using namespace QQmlJS::Dom;
+
+void tst_qmlls_qqmlcodemodel::fileNamesToWatch()
+{
+ DomItem qmlFile;
+ DomCreationOptions options;
+ options.setFlag(DomCreationOption::WithSemanticAnalysis);
+
+ auto envPtr = DomEnvironment::create(QStringList(),
+ DomEnvironment::Option::SingleThreaded
+ | DomEnvironment::Option::NoDependencies, options);
+
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, testFile("MyCppModule/Main.qml")),
+ [&qmlFile](Path, const DomItem &, const DomItem &newIt) {
+ qmlFile = newIt.fileObject();
+ });
+ envPtr->loadPendingDependencies();
+
+ const auto fileNames = QmlLsp::QQmlCodeModel::fileNamesToWatch(qmlFile);
+
+ // fileNames also contains some builtins it seems, like:
+ // QSet("qqmlcomponentattached_p.h", "qqmlcomponent.h", "qobject.h", "qqmllist.h",
+ // "helloworld.h", "qqmlengine_p.h")
+ 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)