forked from qt-creator/qt-creator
CMakePM: Search after packages in CMAKE_PREFIX|MODULE_PATH
This way code completion will have Qt6 package suggestions for find_packages. Change-Id: I9ab64425f850a0d990e77a559ce9f121bc9cf2d7 Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include "cmakebuildsystem.h"
|
#include "cmakebuildsystem.h"
|
||||||
#include "cmakebuildtarget.h"
|
#include "cmakebuildtarget.h"
|
||||||
|
#include "cmakebuildconfiguration.h"
|
||||||
|
#include "cmakeconfigitem.h"
|
||||||
#include "cmakeprojectconstants.h"
|
#include "cmakeprojectconstants.h"
|
||||||
#include "cmaketool.h"
|
#include "cmaketool.h"
|
||||||
#include "cmaketoolmanager.h"
|
#include "cmaketoolmanager.h"
|
||||||
@@ -250,6 +252,71 @@ static QPair<QStringList, QStringList> getLocalFunctionsAndVariables(const QByte
|
|||||||
return {functions, variables};
|
return {functions, variables};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QPair<QStringList, QStringList> getFindAndConfigCMakePackages(const CMakeConfig &cmakeCache,
|
||||||
|
const Environment &environment)
|
||||||
|
{
|
||||||
|
auto toFilePath = [](const QByteArray &str) -> FilePath {
|
||||||
|
return FilePath::fromUserInput(QString::fromUtf8(str));
|
||||||
|
};
|
||||||
|
|
||||||
|
auto findPackageName = [](const QString &fileName) -> QString {
|
||||||
|
auto findIdx = fileName.indexOf("Find");
|
||||||
|
auto endsWithCMakeIdx = fileName.lastIndexOf(".cmake");
|
||||||
|
if (findIdx == 0 && endsWithCMakeIdx > 0)
|
||||||
|
return fileName.mid(4, endsWithCMakeIdx - 4);
|
||||||
|
return QString();
|
||||||
|
};
|
||||||
|
|
||||||
|
auto configPackageName = [](const QString &fileName) -> QString {
|
||||||
|
auto configCMakeIdx = fileName.lastIndexOf("Config.cmake");
|
||||||
|
if (configCMakeIdx > 0)
|
||||||
|
return fileName.left(configCMakeIdx);
|
||||||
|
auto dashConfigCMakeIdx = fileName.lastIndexOf("-config.cmake");
|
||||||
|
if (dashConfigCMakeIdx > 0)
|
||||||
|
return fileName.left(dashConfigCMakeIdx);
|
||||||
|
return QString();
|
||||||
|
};
|
||||||
|
|
||||||
|
QStringList modulePackages;
|
||||||
|
QStringList configPackages;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
const QByteArray cmakeVariable;
|
||||||
|
const QString pathPrefix;
|
||||||
|
std::function<QString(const QString &)> function;
|
||||||
|
QStringList &result;
|
||||||
|
} mapping[] = {{"CMAKE_PREFIX_PATH", "lib/cmake", configPackageName, configPackages},
|
||||||
|
{"CMAKE_MODULE_PATH", QString(), findPackageName, modulePackages}};
|
||||||
|
|
||||||
|
for (const auto &m : mapping) {
|
||||||
|
FilePaths paths = Utils::transform<FilePaths>(cmakeCache.valueOf(m.cmakeVariable).split(';'),
|
||||||
|
toFilePath);
|
||||||
|
|
||||||
|
paths << Utils::transform<FilePaths>(environment.value(QString::fromUtf8(m.cmakeVariable))
|
||||||
|
.split(";"),
|
||||||
|
&FilePath::fromUserInput);
|
||||||
|
|
||||||
|
for (const auto &prefix : paths) {
|
||||||
|
// Only search for directories if we have a prefix
|
||||||
|
const FilePaths dirs = !m.pathPrefix.isEmpty()
|
||||||
|
? prefix.pathAppended(m.pathPrefix)
|
||||||
|
.dirEntries({{"*"}, QDir::Dirs | QDir::NoDotAndDotDot})
|
||||||
|
: FilePaths{prefix};
|
||||||
|
const QStringList cmakeFiles
|
||||||
|
= Utils::transform<QStringList>(dirs, [](const FilePath &path) {
|
||||||
|
return Utils::transform(path.dirEntries({{"*.cmake"}, QDir::Files},
|
||||||
|
QDir::Name),
|
||||||
|
&FilePath::fileName);
|
||||||
|
});
|
||||||
|
m.result << Utils::transform(cmakeFiles, m.function);
|
||||||
|
}
|
||||||
|
m.result = Utils::filtered(m.result, std::not_fn(&QString::isEmpty));
|
||||||
|
}
|
||||||
|
|
||||||
|
return {modulePackages, configPackages};
|
||||||
|
}
|
||||||
|
|
||||||
class PerformInputData
|
class PerformInputData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -259,6 +326,8 @@ public:
|
|||||||
QStringList buildTargets;
|
QStringList buildTargets;
|
||||||
QStringList importedTargets;
|
QStringList importedTargets;
|
||||||
QStringList findPackageVariables;
|
QStringList findPackageVariables;
|
||||||
|
CMakeConfig cmakeConfiguration;
|
||||||
|
Environment environment = Environment::systemEnvironment();
|
||||||
};
|
};
|
||||||
|
|
||||||
PerformInputData CMakeFileCompletionAssist::generatePerformInputData() const
|
PerformInputData CMakeFileCompletionAssist::generatePerformInputData() const
|
||||||
@@ -280,6 +349,8 @@ PerformInputData CMakeFileCompletionAssist::generatePerformInputData() const
|
|||||||
data.projectFunctions = projectKeywords.functions;
|
data.projectFunctions = projectKeywords.functions;
|
||||||
data.importedTargets = bs->projectImportedTargets();
|
data.importedTargets = bs->projectImportedTargets();
|
||||||
data.findPackageVariables = bs->projectFindPackageVariables();
|
data.findPackageVariables = bs->projectFindPackageVariables();
|
||||||
|
data.cmakeConfiguration = bs->configurationFromCMake();
|
||||||
|
data.environment = bs->cmakeBuildConfiguration()->configureEnvironment();
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@@ -323,6 +394,9 @@ IAssistProposal *CMakeFileCompletionAssist::doPerform(const PerformInputData &da
|
|||||||
auto [localFunctions, localVariables] = getLocalFunctionsAndVariables(
|
auto [localFunctions, localVariables] = getLocalFunctionsAndVariables(
|
||||||
interface()->textAt(0, prevFunctionEnd + 1).toUtf8());
|
interface()->textAt(0, prevFunctionEnd + 1).toUtf8());
|
||||||
|
|
||||||
|
auto [findModules, configModules] = getFindAndConfigCMakePackages(data.cmakeConfiguration,
|
||||||
|
data.environment);
|
||||||
|
|
||||||
QList<AssistProposalItemInterface *> items;
|
QList<AssistProposalItemInterface *> items;
|
||||||
|
|
||||||
const QString varGenexToken = interface()->textAt(startPos - 2, 2);
|
const QString varGenexToken = interface()->textAt(startPos - 2, 2);
|
||||||
@@ -375,8 +449,11 @@ IAssistProposal *CMakeFileCompletionAssist::doPerform(const PerformInputData &da
|
|||||||
|
|
||||||
if (functionName == "include" && !onlyFileItems())
|
if (functionName == "include" && !onlyFileItems())
|
||||||
items.append(generateList(data.keywords.includeStandardModules, m_moduleIcon));
|
items.append(generateList(data.keywords.includeStandardModules, m_moduleIcon));
|
||||||
if (functionName == "find_package")
|
if (functionName == "find_package") {
|
||||||
items.append(generateList(data.keywords.findModules, m_moduleIcon));
|
items.append(generateList(data.keywords.findModules, m_moduleIcon));
|
||||||
|
items.append(generateList(findModules, m_moduleIcon));
|
||||||
|
items.append(generateList(configModules, m_moduleIcon));
|
||||||
|
}
|
||||||
|
|
||||||
if ((functionName.contains("target") || functionName == "install"
|
if ((functionName.contains("target") || functionName == "install"
|
||||||
|| functionName == "add_dependencies" || functionName == "set_property"
|
|| functionName == "add_dependencies" || functionName == "set_property"
|
||||||
|
|||||||
Reference in New Issue
Block a user