qmlls: fix go to definition going to build folder

Amends b1ff6073a7 that does not find
resource files of QML Modules that are not the main QML Module: use all
available .qrc files in the build directory when doing operations like
"go to definition".

Also search for hidden folders, because .qrc files tend to be nested
inside of .qt or .rcc folders.

Add a test when going to the defition of a QML file defined in a
different module.

Pick-to: 6.8 6.9
Fixes: QTCREATORBUG-31881
Fixes: QTBUG-131920
Change-Id: I751e2cd2d1a9867459226e4f884eb1da5c1f9436
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Sami Shalayel 2024-12-05 16:52:13 +01:00
parent 94a481d433
commit 37f69c4341
12 changed files with 67 additions and 26 deletions

View File

@ -248,30 +248,14 @@ bool canCompareWithQUrl(
return lhsType == typeResolver->urlType() && rhsType == typeResolver->urlType();
}
static QVarLengthArray<QString, 2> resourceFoldersFromBuildFolder(const QString &buildFolder)
{
QVarLengthArray<QString, 2> result;
const QDir dir(buildFolder);
if (dir.exists(u".rcc"_s)) {
result.append(dir.filePath(u".rcc"_s));
}
if (dir.exists(u".qt/rcc"_s)) {
result.append(dir.filePath(u".qt/rcc"_s));
}
return result;
}
QStringList QQmlJSUtils::resourceFilesFromBuildFolders(const QStringList &buildFolders)
{
QStringList result;
for (const QString &path : buildFolders) {
for (const QString &resourceFolder : resourceFoldersFromBuildFolder(path)) {
QDirIterator it(resourceFolder, QStringList{ u"*.qrc"_s }, QDir::Files,
QDirIterator::Subdirectories);
while (it.hasNext()) {
result.append(it.next());
}
QDirIterator it(path, QStringList{ u"*.qrc"_s }, QDir::Files | QDir::Hidden,
QDirIterator::Subdirectories);
while (it.hasNext()) {
result.append(it.next());
}
}
return result;

View File

@ -0,0 +1,6 @@
import QtQuick
import MyModule
Item {
MyItem {}
}

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/TestApp">
<file alias="qmldir">../../TestApp/qmldir</file>
</qresource>
</RCC>

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/TestApp/">
<file alias="Main.qml">../../../TestApp/Main.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,6 @@
import QtQuick
import MyModule
Item {
MyItem {}
}

View File

@ -0,0 +1,3 @@
module testapp
prefer :/testapp/
Main 1.0 Main.qml

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/MyModule/">
<file alias="MyItem.qml">../../../../../../TestApp/somesubfolder/anothersubfolder/MyModule/MyItem.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/MyModule">
<file alias="qmldir">../../qmldir</file>
</qresource>
</RCC>

View File

@ -0,0 +1,4 @@
module MyModule
typeinfo MyModule.qmltypes
prefer :/MyModule/
MyItem 254.0 MyItem.qml

View File

@ -1819,11 +1819,11 @@ void tst_qmlls_utils::findDefinitionFromLocation_data()
QTest::addColumn<int>("expectedLine");
QTest::addColumn<int>("expectedCharacter");
QTest::addColumn<size_t>("expectedLength");
QTest::addColumn<QString>("extraBuildDir");
QTest::addColumn<QStringList>("extraBuildDirs");
const QString JSDefinitionsQml = testFile(u"JSDefinitions.qml"_s);
const QString BaseTypeQml = testFile(u"BaseType.qml"_s);
const QString noExtraBuildDir;
const QStringList noExtraBuildDir;
QTest::addRow("JSIdentifierX")
<< JSDefinitionsQml << 14 << 11 << JSDefinitionsQml << 13 << 13 << strlen("x") << noExtraBuildDir;
@ -1959,10 +1959,22 @@ void tst_qmlls_utils::findDefinitionFromLocation_data()
const QString myComponentQml = testFile(u"findDefinition/mymodule-source/MyModule/X/Y/Z/MyComponent.qml"_s);
QTest::addRow("nestedFromOwnModule") << mainQml << 4 << 5 << myComponentQml << 3 << 1
<< strlen("Item") << testFile(u"findDefinition/mymodule-build"_s);
<< strlen("Item") << QStringList { testFile(u"findDefinition/mymodule-build"_s) };
QTest::addRow("nestedFromOwnModuleWithoutQmldirPrefer") << mainQml << 4 << 5 << myComponentQml << 3 << 1
<< strlen("Item")
<< testFile(u"findDefinition/mymodule-build-without-qmldir-prefer"_s);
<< QStringList { testFile(u"findDefinition/mymodule-build-without-qmldir-prefer"_s) };
}
{
const QString mainQml = testFile(u"findDefinition/TestAppWithBuildFolder/TestApp/Main.qml"_s);
const QString myComponentQml = testFile(u"findDefinition/TestAppWithBuildFolder/TestApp/somesubfolder/anothersubfolder/MyModule/MyItem.qml"_s);
QTest::addRow("componentFromOtherModule")
<< mainQml << 5 << 8 << myComponentQml << 3 << 1 << strlen("Item")
<< QStringList{
testFile(u"findDefinition/TestAppWithBuildFolder/build"_s),
testFile(
u"findDefinition/TestAppWithBuildFolder/build/somesubfolder/anothersubfolder"_s)
};
}
}
@ -1975,7 +1987,7 @@ void tst_qmlls_utils::findDefinitionFromLocation()
QFETCH(int, expectedLine);
QFETCH(int, expectedCharacter);
QFETCH(size_t, expectedLength);
QFETCH(QString, extraBuildDir);
QFETCH(QStringList, extraBuildDirs);
if (expectedLine == -1)
expectedLine = line;
@ -1988,7 +2000,7 @@ void tst_qmlls_utils::findDefinitionFromLocation()
Q_ASSERT(expectedLine > 0);
Q_ASSERT(expectedCharacter > 0);
auto [env, file] = createEnvironmentAndLoadFile(filePath, QStringList { extraBuildDir });
auto [env, file] = createEnvironmentAndLoadFile(filePath, extraBuildDirs);
auto locations = QQmlLSUtils::itemsFromTextLocation(
file.field(QQmlJS::Dom::Fields::currentItem), line - 1, character - 1);