forked from qt-creator/qt-creator
CMakePM: Consider local CMAKE_PREFIX|MODULE_PATH for code completion
If projects are using a local "cmake" directory containing
Find<Package>.cmake modules the common practice is to use something like
this:
## Add paths to check for cmake modules:
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
This commit makes sure that these packages are taken into consideration
for code completion.
Change-Id: I152ccce0c97ab2385eda93ff6bc5fc4e7cefb6c4
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -228,16 +228,20 @@ static int addFilePathItems(const AssistInterface *interface,
|
|||||||
return startPos;
|
return startPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QPair<QStringList, QStringList> getLocalFunctionsAndVariables(const QByteArray &content)
|
static cmListFile parseCMakeListFromBuffer(const QByteArray &content)
|
||||||
{
|
{
|
||||||
cmListFile cmakeListFile;
|
cmListFile cmakeListFile;
|
||||||
std::string errorString;
|
std::string errorString;
|
||||||
if (!content.isEmpty()) {
|
if (!content.isEmpty()) {
|
||||||
const std::string fileName = "buffer";
|
const std::string fileName = "buffer";
|
||||||
if (!cmakeListFile.ParseString(content.toStdString(), fileName, errorString))
|
if (!cmakeListFile.ParseString(content.toStdString(), fileName, errorString))
|
||||||
return {{}, {}};
|
return {};
|
||||||
|
}
|
||||||
|
return cmakeListFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QPair<QStringList, QStringList> getLocalFunctionsAndVariables(const cmListFile &cmakeListFile)
|
||||||
|
{
|
||||||
QStringList variables;
|
QStringList variables;
|
||||||
QStringList functions;
|
QStringList functions;
|
||||||
for (const auto &func : cmakeListFile.Functions) {
|
for (const auto &func : cmakeListFile.Functions) {
|
||||||
@@ -252,8 +256,67 @@ static QPair<QStringList, QStringList> getLocalFunctionsAndVariables(const QByte
|
|||||||
return {functions, variables};
|
return {functions, variables};
|
||||||
}
|
}
|
||||||
|
|
||||||
static QPair<QStringList, QStringList> getFindAndConfigCMakePackages(const CMakeConfig &cmakeCache,
|
static void updateCMakeConfigurationWithLocalData(CMakeConfig &cmakeCache,
|
||||||
const Environment &environment)
|
const cmListFile &cmakeListFile,
|
||||||
|
const FilePath ¤tDir)
|
||||||
|
{
|
||||||
|
auto isValidCMakeVariable = [](const std::string &var) {
|
||||||
|
return var == "CMAKE_PREFIX_PATH" || var == "CMAKE_MODULE_PATH";
|
||||||
|
};
|
||||||
|
|
||||||
|
const FilePath projectDir = ProjectTree::currentBuildSystem()->projectDirectory();
|
||||||
|
auto updateDirVariables = [currentDir, projectDir, cmakeCache](QByteArray &value) {
|
||||||
|
value.replace("${CMAKE_CURRENT_SOURCE_DIR}", currentDir.path().toUtf8());
|
||||||
|
value.replace("${CMAKE_CURRENT_LIST_DIR}", currentDir.path().toUtf8());
|
||||||
|
value.replace("${CMAKE_SOURCE_DIR}", projectDir.path().toUtf8());
|
||||||
|
value.replace("${CMAKE_PREFIX_PATH}", cmakeCache.valueOf("CMAKE_PREFIX_PATH"));
|
||||||
|
value.replace("${CMAKE_MODULE_PATH}", cmakeCache.valueOf("CMAKE_MODULE_PATH"));
|
||||||
|
};
|
||||||
|
|
||||||
|
auto insertOrAppendListValue = [&cmakeCache](const QByteArray &key, const QByteArray &value) {
|
||||||
|
auto it = std::find_if(cmakeCache.begin(), cmakeCache.end(), [key](const auto &item) {
|
||||||
|
return item.key == key;
|
||||||
|
});
|
||||||
|
if (it == cmakeCache.end()) {
|
||||||
|
cmakeCache << CMakeConfigItem(key, value);
|
||||||
|
} else {
|
||||||
|
it->value.append(";");
|
||||||
|
it->value.append(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto &func : cmakeListFile.Functions) {
|
||||||
|
const bool isSet = func.LowerCaseName() == "set" && func.Arguments().size() > 1;
|
||||||
|
const bool isList = func.LowerCaseName() == "list" && func.Arguments().size() > 2;
|
||||||
|
if (!isSet && !isList)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QByteArray key;
|
||||||
|
QByteArray value;
|
||||||
|
if (isSet) {
|
||||||
|
const auto firstArg = func.Arguments()[0];
|
||||||
|
const auto secondArg = func.Arguments()[1];
|
||||||
|
if (!isValidCMakeVariable(firstArg.Value))
|
||||||
|
continue;
|
||||||
|
key = QByteArray::fromStdString(firstArg.Value);
|
||||||
|
value = QByteArray::fromStdString(secondArg.Value);
|
||||||
|
}
|
||||||
|
if (isList) {
|
||||||
|
const auto firstArg = func.Arguments()[0];
|
||||||
|
const auto secondArg = func.Arguments()[1];
|
||||||
|
const auto thirdArg = func.Arguments()[2];
|
||||||
|
if (firstArg.Value != "APPEND" || !isValidCMakeVariable(secondArg.Value))
|
||||||
|
continue;
|
||||||
|
key = QByteArray::fromStdString(secondArg.Value);
|
||||||
|
value = QByteArray::fromStdString(thirdArg.Value);
|
||||||
|
}
|
||||||
|
updateDirVariables(value);
|
||||||
|
insertOrAppendListValue(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static QPair<QStringList, QStringList> getFindAndConfigCMakePackages(
|
||||||
|
const CMakeConfig &cmakeCache, const Environment &environment)
|
||||||
{
|
{
|
||||||
auto toFilePath = [](const QByteArray &str) -> FilePath {
|
auto toFilePath = [](const QByteArray &str) -> FilePath {
|
||||||
return FilePath::fromUserInput(QString::fromUtf8(str));
|
return FilePath::fromUserInput(QString::fromUtf8(str));
|
||||||
@@ -391,10 +454,15 @@ IAssistProposal *CMakeFileCompletionAssist::doPerform(const PerformInputData &da
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [localFunctions, localVariables] = getLocalFunctionsAndVariables(
|
cmListFile cmakeListFile = parseCMakeListFromBuffer(
|
||||||
interface()->textAt(0, prevFunctionEnd + 1).toUtf8());
|
interface()->textAt(0, prevFunctionEnd + 1).toUtf8());
|
||||||
|
auto [localFunctions, localVariables] = getLocalFunctionsAndVariables(cmakeListFile);
|
||||||
|
|
||||||
auto [findModules, configModules] = getFindAndConfigCMakePackages(data.cmakeConfiguration,
|
CMakeConfig cmakeConfiguration = data.cmakeConfiguration;
|
||||||
|
const FilePath currentDir = interface()->filePath().absolutePath();
|
||||||
|
updateCMakeConfigurationWithLocalData(cmakeConfiguration, cmakeListFile, currentDir);
|
||||||
|
|
||||||
|
auto [findModules, configModules] = getFindAndConfigCMakePackages(cmakeConfiguration,
|
||||||
data.environment);
|
data.environment);
|
||||||
|
|
||||||
QList<AssistProposalItemInterface *> items;
|
QList<AssistProposalItemInterface *> items;
|
||||||
|
|||||||
Reference in New Issue
Block a user