forked from qt-creator/qt-creator
QmlJS: Fix Follow under cursor
When trying to jump to a symbol in a qml file the Qml Model may find the location in a generated .qml file in the build folder. QtCreator searches in all generated .qrc files to try and find the source file so it can jump to it instead. Previously not all auto-generated ".rcc" folders would be found as only the folders of targets (executables) were searched. Plugins or Static Libraries were not searched. With this fix, all projects nodes are searched for the ".rcc" folder and therefore also finds them for Dynamic / Static libraries and plugins. Fixes: QTCREATORBUG-27173 Change-Id: Ic51ac8fbc82c15785cbefd76787942a512ecf3db Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -432,15 +432,13 @@ bool pInfoLessThanImports(const ModelManagerInterface::ProjectInfo &p1,
|
||||
|
||||
}
|
||||
|
||||
static QList<Utils::FilePath> generatedQrc(QList<Utils::FilePath> applicationDirectories)
|
||||
static QSet<Utils::FilePath> generatedQrc(
|
||||
const QList<ModelManagerInterface::ProjectInfo> &projectInfos)
|
||||
{
|
||||
QList<Utils::FilePath> res;
|
||||
for (const Utils::FilePath &path : applicationDirectories) {
|
||||
Utils::FilePath generatedQrcDir = path.pathAppended(".rcc");
|
||||
if (generatedQrcDir.isReadableDir()) {
|
||||
for (const Utils::FilePath & qrcPath: generatedQrcDir.dirEntries(FileFilter(QStringList({QStringLiteral(u"*.qrc")}), QDir::Files)))
|
||||
res.append(qrcPath.canonicalPath());
|
||||
}
|
||||
QSet<Utils::FilePath> res;
|
||||
for (const auto &pInfo : projectInfos) {
|
||||
for (const auto &generatedQrcFile: pInfo.generatedQrcFiles)
|
||||
res.insert(generatedQrcFile);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -467,7 +465,7 @@ void ModelManagerInterface::iterateQrcFiles(
|
||||
qrcFilePaths = pInfo.activeResourceFiles;
|
||||
else
|
||||
qrcFilePaths = pInfo.allResourceFiles;
|
||||
for (const Utils::FilePath &p : generatedQrc(pInfo.applicationDirectories))
|
||||
for (const Utils::FilePath &p : generatedQrc({pInfo}))
|
||||
qrcFilePaths.append(p);
|
||||
for (const Utils::FilePath &qrcFilePath : std::as_const(qrcFilePaths)) {
|
||||
if (pathsChecked.contains(qrcFilePath))
|
||||
@@ -590,7 +588,7 @@ void ModelManagerInterface::updateProjectInfo(const ProjectInfo &pinfo, ProjectE
|
||||
m_qrcContents = pinfo.resourceFileContents;
|
||||
for (const Utils::FilePath &newQrc : std::as_const(pinfo.allResourceFiles))
|
||||
m_qrcCache.addPath(newQrc.toString(), m_qrcContents.value(newQrc));
|
||||
for (const Utils::FilePath &newQrc : generatedQrc(pinfo.applicationDirectories))
|
||||
for (const Utils::FilePath &newQrc : pinfo.generatedQrcFiles)
|
||||
m_qrcCache.addPath(newQrc.toString(), m_qrcContents.value(newQrc));
|
||||
for (const Utils::FilePath &oldQrc : std::as_const(oldInfo.allResourceFiles))
|
||||
m_qrcCache.removePath(oldQrc.toString());
|
||||
@@ -1293,7 +1291,7 @@ void ModelManagerInterface::updateImportPaths()
|
||||
allImportPaths.maybeInsert(path, Dialect::Qml);
|
||||
findNewQmlApplicationInPath(path, snapshot, this, &newLibraries);
|
||||
}
|
||||
for (const Utils::FilePath &qrcPath : generatedQrc(allApplicationDirectories))
|
||||
for (const Utils::FilePath &qrcPath : generatedQrc(m_projects.values()))
|
||||
updateQrcFile(qrcPath);
|
||||
|
||||
updateSourceFiles(importedFiles, true);
|
||||
@@ -1625,8 +1623,10 @@ ModelManagerInterface::ProjectInfo ModelManagerInterface::defaultProjectInfo() c
|
||||
}
|
||||
|
||||
ModelManagerInterface::ProjectInfo ModelManagerInterface::defaultProjectInfoForProject(
|
||||
ProjectExplorer::Project *) const
|
||||
ProjectExplorer::Project *project, const FilePaths &hiddenRccFolders) const
|
||||
{
|
||||
Q_UNUSED(project);
|
||||
Q_UNUSED(hiddenRccFolders);
|
||||
return ModelManagerInterface::ProjectInfo();
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
PathsAndLanguages importPaths;
|
||||
QList<Utils::FilePath> activeResourceFiles;
|
||||
QList<Utils::FilePath> allResourceFiles;
|
||||
QList<Utils::FilePath> generatedQrcFiles;
|
||||
QHash<Utils::FilePath, QString> resourceFileContents;
|
||||
QList<Utils::FilePath> applicationDirectories;
|
||||
QHash<QString, QString> moduleMappings; // E.g.: QtQuick.Controls -> MyProject.MyControls
|
||||
@@ -164,8 +165,8 @@ public:
|
||||
|
||||
void setDefaultVContext(const ViewerContext &vContext);
|
||||
virtual ProjectInfo defaultProjectInfo() const;
|
||||
virtual ProjectInfo defaultProjectInfoForProject(ProjectExplorer::Project *project) const;
|
||||
|
||||
virtual ProjectInfo defaultProjectInfoForProject(ProjectExplorer::Project *project,
|
||||
const Utils::FilePaths &hiddenRccFolders) const;
|
||||
|
||||
// Blocks until all parsing threads are done. Use for testing only!
|
||||
void test_joinAllThreads();
|
||||
|
||||
@@ -1186,8 +1186,8 @@ void CMakeBuildSystem::updateQmlJSCodeModel(const QStringList &extraHeaderPaths,
|
||||
return;
|
||||
|
||||
Project *p = project();
|
||||
QmlJS::ModelManagerInterface::ProjectInfo projectInfo = modelManager
|
||||
->defaultProjectInfoForProject(p);
|
||||
QmlJS::ModelManagerInterface::ProjectInfo projectInfo
|
||||
= modelManager->defaultProjectInfoForProject(p, p->files(Project::HiddenRccFolders));
|
||||
|
||||
projectInfo.importPaths.clear();
|
||||
|
||||
|
||||
@@ -109,6 +109,10 @@ const Project::NodeMatcher Project::GeneratedFiles = [](const Node *node) {
|
||||
return isListedFileNode(node) && node->isGenerated();
|
||||
};
|
||||
|
||||
const Project::NodeMatcher Project::HiddenRccFolders = [](const Node *node) {
|
||||
return node->isFolderNodeType() && node->filePath().fileName() == ".rcc";
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// ProjectDocument:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -101,6 +101,7 @@ public:
|
||||
static const NodeMatcher AllFiles;
|
||||
static const NodeMatcher SourceFiles;
|
||||
static const NodeMatcher GeneratedFiles;
|
||||
static const NodeMatcher HiddenRccFolders;
|
||||
|
||||
Utils::FilePaths files(const NodeMatcher &matcher) const;
|
||||
bool isKnownFile(const Utils::FilePath &filename) const;
|
||||
|
||||
@@ -250,7 +250,8 @@ void PythonBuildSystem::triggerParsing()
|
||||
|
||||
auto modelManager = QmlJS::ModelManagerInterface::instance();
|
||||
if (modelManager) {
|
||||
auto projectInfo = modelManager->defaultProjectInfoForProject(project());
|
||||
const auto hiddenRccFolders = project()->files(Project::HiddenRccFolders);
|
||||
auto projectInfo = modelManager->defaultProjectInfoForProject(project(), hiddenRccFolders);
|
||||
|
||||
for (const QString &importPath : std::as_const(m_qmlImportPaths)) {
|
||||
const FilePath filePath = FilePath::fromString(importPath);
|
||||
|
||||
@@ -1052,8 +1052,9 @@ void QbsBuildSystem::updateQmlJsCodeModel()
|
||||
QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance();
|
||||
if (!modelManager)
|
||||
return;
|
||||
QmlJS::ModelManagerInterface::ProjectInfo projectInfo =
|
||||
modelManager->defaultProjectInfoForProject(project());
|
||||
QmlJS::ModelManagerInterface::ProjectInfo projectInfo
|
||||
= modelManager->defaultProjectInfoForProject(project(),
|
||||
project()->files(Project::HiddenRccFolders));
|
||||
|
||||
const QJsonObject projectData = session()->projectData();
|
||||
if (projectData.isEmpty())
|
||||
@@ -1068,7 +1069,7 @@ void QbsBuildSystem::updateQmlJsCodeModel()
|
||||
});
|
||||
|
||||
project()->setProjectLanguage(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID,
|
||||
!projectInfo.sourceFiles.isEmpty());
|
||||
!projectInfo.sourceFiles.isEmpty());
|
||||
modelManager->updateProjectInfo(projectInfo, project());
|
||||
}
|
||||
|
||||
|
||||
@@ -410,8 +410,9 @@ void QmakeBuildSystem::updateQmlJSCodeModel()
|
||||
if (!modelManager)
|
||||
return;
|
||||
|
||||
QmlJS::ModelManagerInterface::ProjectInfo projectInfo =
|
||||
modelManager->defaultProjectInfoForProject(project());
|
||||
QmlJS::ModelManagerInterface::ProjectInfo projectInfo
|
||||
= modelManager->defaultProjectInfoForProject(project(),
|
||||
project()->files(Project::HiddenRccFolders));
|
||||
|
||||
const QList<QmakeProFile *> proFiles = rootProFile()->allProFiles();
|
||||
|
||||
|
||||
@@ -81,8 +81,36 @@ static void setupProjectInfoQmlBundles(ModelManagerInterface::ProjectInfo &proje
|
||||
}
|
||||
}
|
||||
|
||||
static void findAllQrcFiles(const FilePath &filePath, FilePaths &out)
|
||||
{
|
||||
filePath.iterateDirectory(
|
||||
[&out](const FilePath &path) {
|
||||
out.append(path.canonicalPath());
|
||||
return true;
|
||||
},
|
||||
{{"*.qrc"}, QDir::Files});
|
||||
}
|
||||
|
||||
static FilePaths findGeneratedQrcFiles(const ModelManagerInterface::ProjectInfo &pInfo,
|
||||
const FilePaths &hiddenRccFolders)
|
||||
{
|
||||
FilePaths result;
|
||||
// Search in Application Directories for directories named ".rcc"
|
||||
// and add all .qrc files in there to the resource file list.
|
||||
for (const Utils::FilePath &path : pInfo.applicationDirectories) {
|
||||
Utils::FilePath generatedQrcDir = path.pathAppended(".rcc");
|
||||
findAllQrcFiles(generatedQrcDir, result);
|
||||
}
|
||||
|
||||
for (const Utils::FilePath &hiddenRccFolder : hiddenRccFolders) {
|
||||
findAllQrcFiles(hiddenRccFolder, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ModelManagerInterface::ProjectInfo ModelManager::defaultProjectInfoForProject(
|
||||
Project *project) const
|
||||
Project *project, const FilePaths &hiddenRccFolders) const
|
||||
{
|
||||
ModelManagerInterface::ProjectInfo projectInfo;
|
||||
projectInfo.project = project;
|
||||
@@ -183,6 +211,7 @@ ModelManagerInterface::ProjectInfo ModelManager::defaultProjectInfoForProject(
|
||||
}
|
||||
|
||||
setupProjectInfoQmlBundles(projectInfo);
|
||||
projectInfo.generatedQrcFiles = findGeneratedQrcFiles(projectInfo, hiddenRccFolders);
|
||||
return projectInfo;
|
||||
}
|
||||
|
||||
@@ -294,7 +323,7 @@ void ModelManager::updateDefaultProjectInfo()
|
||||
Project *currentProject = SessionManager::startupProject();
|
||||
setDefaultProject(containsProject(currentProject)
|
||||
? projectInfo(currentProject)
|
||||
: defaultProjectInfoForProject(currentProject),
|
||||
: defaultProjectInfoForProject(currentProject, {}),
|
||||
currentProject);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,8 @@ protected:
|
||||
WorkingCopy workingCopyInternal() const override;
|
||||
void addTaskInternal(const QFuture<void> &result, const QString &msg,
|
||||
const char *taskId) const override;
|
||||
ProjectInfo defaultProjectInfoForProject(ProjectExplorer::Project *project) const override;
|
||||
ProjectInfo defaultProjectInfoForProject(
|
||||
ProjectExplorer::Project *project, const Utils::FilePaths &hiddenRccFolders) const override;
|
||||
private:
|
||||
void updateDefaultProjectInfo();
|
||||
void loadDefaultQmlTypeDescriptions();
|
||||
|
||||
@@ -312,8 +312,9 @@ void QmlBuildSystem::refresh(RefreshOptions options)
|
||||
if (!modelManager)
|
||||
return;
|
||||
|
||||
QmlJS::ModelManagerInterface::ProjectInfo projectInfo =
|
||||
modelManager->defaultProjectInfoForProject(project());
|
||||
QmlJS::ModelManagerInterface::ProjectInfo projectInfo
|
||||
= modelManager->defaultProjectInfoForProject(project(),
|
||||
project()->files(Project::HiddenRccFolders));
|
||||
const QStringList searchPaths = makeAbsolute(canonicalProjectDir(), customImportPaths());
|
||||
for (const QString &searchPath : searchPaths)
|
||||
projectInfo.importPaths.maybeInsert(Utils::FilePath::fromString(searchPath),
|
||||
|
||||
Reference in New Issue
Block a user