diff options
author | Cristian Adam <[email protected]> | 2023-09-27 20:20:46 +0200 |
---|---|---|
committer | Cristian Adam <[email protected]> | 2023-09-28 10:49:56 +0000 |
commit | 776c8670d7e8124c8b78dc505b85a94d51372e54 (patch) | |
tree | aa36c168060eb569bfc7e09a3b6b5dfd426fa7b4 | |
parent | d08f1c6e9415c6aa2e47410c9c8763580e28b046 (diff) |
CMakePM: Handle project FindPackage package variables
For example find_package(ZLIB QUEIT) will result in the package
variables ZLIB_LIBRARY ZLIB_INCLUDE_DIR.
The variables are available for both code completion and navigation.
Change-Id: I4ea6090f44a980dc91632fcabbda16987b0f0285
Reviewed-by: Alessandro Portale <[email protected]>
4 files changed, 56 insertions, 0 deletions
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp index 8d5f9823245..a055d07149c 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp @@ -1337,13 +1337,58 @@ void CMakeBuildSystem::setupCMakeSymbolsHash() m_cmakeSymbolsHash.insert(QString::fromUtf8(arg.Value), link); }; + // Gather the exported variables for the Find<Package> CMake packages + m_projectFindPackageVariables.clear(); + + const std::string fphsFunctionName = "find_package_handle_standard_args"; + CMakeKeywords keywords; + if (auto tool = CMakeKitAspect::cmakeTool(target()->kit())) + keywords = tool->keywords(); + QSet<std::string> fphsFunctionArgs; + if (keywords.functionArgs.contains(QString::fromStdString(fphsFunctionName))) { + const QList<std::string> args + = Utils::transform(keywords.functionArgs.value(QString::fromStdString(fphsFunctionName)), + &QString::toStdString); + fphsFunctionArgs = Utils::toSet(args); + } + + auto handleFindPackageVariables = [&](const CMakeFileInfo &cmakeFile, const cmListFileFunction &func) { + if (func.LowerCaseName() != fphsFunctionName) + return; + + if (func.Arguments().size() == 0) + return; + auto firstArgument = func.Arguments()[0]; + const auto filteredArguments = Utils::filtered(func.Arguments(), [&](const auto &arg) { + return !fphsFunctionArgs.contains(arg.Value) && arg != firstArgument; + }); + + for (const auto &arg : filteredArguments) { + const QString value = QString::fromUtf8(arg.Value); + if (value.contains("${") || (value.startsWith('"') && value.endsWith('"')) + || (value.startsWith("'") && value.endsWith("'"))) + continue; + + m_projectFindPackageVariables << value; + + Utils::Link link; + link.targetFilePath = cmakeFile.path; + link.targetLine = arg.Line; + link.targetColumn = arg.Column - 1; + m_cmakeSymbolsHash.insert(value, link); + } + }; + for (const auto &cmakeFile : std::as_const(m_cmakeFiles)) { for (const auto &func : cmakeFile.cmakeListFile.Functions) { handleFunctionMacroOption(cmakeFile, func); handleImportedTargets(cmakeFile, func); handleProjectTargets(cmakeFile, func); + handleFindPackageVariables(cmakeFile, func); } } + + m_projectFindPackageVariables.removeDuplicates(); } void CMakeBuildSystem::ensureBuildDirectory(const BuildDirParameters ¶meters) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h index a8f2a66308b..d29ee777d41 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h @@ -122,6 +122,7 @@ public: const QHash<QString, Utils::Link> &cmakeSymbolsHash() const { return m_cmakeSymbolsHash; } CMakeKeywords projectKeywords() const { return m_projectKeywords; } QStringList projectImportedTargets() const { return m_projectImportedTargets; } + QStringList projectFindPackageVariables() const { return m_projectFindPackageVariables; } signals: void configurationCleared(); @@ -229,6 +230,7 @@ private: QHash<QString, Utils::Link> m_cmakeSymbolsHash; CMakeKeywords m_projectKeywords; QStringList m_projectImportedTargets; + QStringList m_projectFindPackageVariables; QHash<QString, ProjectFileArgumentPosition> m_filesToBeRenamed; diff --git a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp index 86f8823fdee..beed0d2ebe5 100644 --- a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp @@ -248,6 +248,10 @@ void CMakeEditorWidget::findLinkAt(const QTextCursor &cursor, // Check if the symbols is a user defined function or macro const CMakeBuildSystem *cbs = static_cast<const CMakeBuildSystem *>(bs); + // Strip variable coating + if (buffer.startsWith("${") && buffer.endsWith("}")) + buffer = buffer.mid(2, buffer.size() - 3); + if (cbs->cmakeSymbolsHash().contains(buffer)) { link = cbs->cmakeSymbolsHash().value(buffer); addTextStartEndToLink(link); diff --git a/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp index 80bd513fd6d..93c00509c0c 100644 --- a/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp +++ b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp @@ -254,12 +254,14 @@ IAssistProposal *CMakeFileCompletionAssist::performAsync() QStringList buildTargets; QStringList importedTargets; + QStringList findPackageVariables; if (auto bs = qobject_cast<CMakeBuildSystem *>(ProjectTree::currentBuildSystem())) { for (const auto &target : std::as_const(bs->buildTargets())) if (target.targetType != TargetType::UtilityType) buildTargets << target.title; projectKeywords = bs->projectKeywords(); importedTargets = bs->projectImportedTargets(); + findPackageVariables = bs->projectFindPackageVariables(); } if (isInComment(interface())) @@ -296,6 +298,7 @@ IAssistProposal *CMakeFileCompletionAssist::performAsync() if (varGenexToken == "${") { items.append(generateList(keywords.variables, m_variableIcon)); items.append(generateList(projectKeywords.variables, m_projectVariableIcon)); + items.append(generateList(findPackageVariables, m_projectVariableIcon)); } if (varGenexToken == "$<") items.append(generateList(keywords.generatorExpressions, m_genexIcon)); @@ -311,6 +314,7 @@ IAssistProposal *CMakeFileCompletionAssist::performAsync() || functionName == "cmake_print_variables") { items.append(generateList(keywords.variables, m_variableIcon)); items.append(generateList(projectKeywords.variables, m_projectVariableIcon)); + items.append(generateList(findPackageVariables, m_projectVariableIcon)); items.append(generateList(localVariables, m_variableIcon)); } @@ -369,6 +373,7 @@ IAssistProposal *CMakeFileCompletionAssist::performAsync() items.append(generateList(keywords.variables, m_variableIcon)); items.append(generateList(projectKeywords.variables, m_projectVariableIcon)); items.append(generateList(localVariables, m_variableIcon)); + items.append(generateList(findPackageVariables, m_projectVariableIcon)); items.append(generateList(keywords.properties, m_propertyIcon)); items.append(generateList(buildTargets, m_targetsIcon)); |