CMakePM: Handle include(CMakeFileWithoutSuffix) navigation

Check that the function operating upon is "include" and then match the
word under cursor with a file from the project.

Change-Id: Ia0131f08515c56582a1fb02a59d6b2e41ac04288
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
Cristian Adam
2023-09-29 22:39:01 +02:00
parent 44836247ca
commit 762b0518a2
3 changed files with 70 additions and 9 deletions

View File

@@ -1379,12 +1379,25 @@ void CMakeBuildSystem::setupCMakeSymbolsHash()
} }
}; };
// Prepare a hash with all .cmake files
m_dotCMakeFilesHash.clear();
auto handleDotCMakeFiles = [&](const CMakeFileInfo &cmakeFile) {
if (cmakeFile.path.suffix() == "cmake") {
Utils::Link link;
link.targetFilePath = cmakeFile.path;
link.targetLine = 1;
link.targetColumn = 0;
m_dotCMakeFilesHash.insert(cmakeFile.path.completeBaseName(), link);
}
};
for (const auto &cmakeFile : std::as_const(m_cmakeFiles)) { for (const auto &cmakeFile : std::as_const(m_cmakeFiles)) {
for (const auto &func : cmakeFile.cmakeListFile.Functions) { for (const auto &func : cmakeFile.cmakeListFile.Functions) {
handleFunctionMacroOption(cmakeFile, func); handleFunctionMacroOption(cmakeFile, func);
handleImportedTargets(cmakeFile, func); handleImportedTargets(cmakeFile, func);
handleProjectTargets(cmakeFile, func); handleProjectTargets(cmakeFile, func);
handleFindPackageVariables(cmakeFile, func); handleFindPackageVariables(cmakeFile, func);
handleDotCMakeFiles(cmakeFile);
} }
} }

View File

@@ -123,6 +123,7 @@ public:
CMakeKeywords projectKeywords() const { return m_projectKeywords; } CMakeKeywords projectKeywords() const { return m_projectKeywords; }
QStringList projectImportedTargets() const { return m_projectImportedTargets; } QStringList projectImportedTargets() const { return m_projectImportedTargets; }
QStringList projectFindPackageVariables() const { return m_projectFindPackageVariables; } QStringList projectFindPackageVariables() const { return m_projectFindPackageVariables; }
const QHash<QString, Utils::Link> &dotCMakeFilesHash() const { return m_dotCMakeFilesHash; }
signals: signals:
void configurationCleared(); void configurationCleared();
@@ -228,6 +229,7 @@ private:
QList<CMakeBuildTarget> m_buildTargets; QList<CMakeBuildTarget> m_buildTargets;
QSet<CMakeFileInfo> m_cmakeFiles; QSet<CMakeFileInfo> m_cmakeFiles;
QHash<QString, Utils::Link> m_cmakeSymbolsHash; QHash<QString, Utils::Link> m_cmakeSymbolsHash;
QHash<QString, Utils::Link> m_dotCMakeFilesHash;
CMakeKeywords m_projectKeywords; CMakeKeywords m_projectKeywords;
QStringList m_projectImportedTargets; QStringList m_projectImportedTargets;
QStringList m_projectFindPackageVariables; QStringList m_projectFindPackageVariables;

View File

@@ -153,6 +153,11 @@ static bool isValidUrlChar(const QChar &c)
return (c.isLetterOrNumber() || urlChars.contains(c)) && !c.isSpace(); return (c.isLetterOrNumber() || urlChars.contains(c)) && !c.isSpace();
} }
static bool isValidIdentifierChar(const QChar &chr)
{
return chr.isLetterOrNumber() || chr == '_' || chr == '-';
}
QHash<QString, Utils::Link> getLocalSymbolsHash(const QByteArray &content, const Utils::FilePath &filePath) QHash<QString, Utils::Link> getLocalSymbolsHash(const QByteArray &content, const Utils::FilePath &filePath)
{ {
cmListFile cmakeListFile; cmListFile cmakeListFile;
@@ -266,6 +271,43 @@ void CMakeEditorWidget::findLinkAt(const QTextCursor &cursor,
buffer.replace("${CMAKE_CURRENT_SOURCE_DIR}", dir.path()); buffer.replace("${CMAKE_CURRENT_SOURCE_DIR}", dir.path());
buffer.replace("${CMAKE_CURRENT_LIST_DIR}", dir.path()); buffer.replace("${CMAKE_CURRENT_LIST_DIR}", dir.path());
// Lambdas to find the CMake function name
auto findFunctionStart = [cursor, this]() -> int {
int pos = cursor.position();
QChar chr;
do {
chr = textDocument()->characterAt(--pos);
} while (pos > 0 && chr != '(');
if (pos > 0 && chr == '(') {
// allow space between function name and (
do {
chr = textDocument()->characterAt(--pos);
} while (pos > 0 && chr.isSpace());
++pos;
}
return pos;
};
auto findFunctionEnd = [cursor, this]() -> int {
int pos = cursor.position();
QChar chr;
do {
chr = textDocument()->characterAt(--pos);
} while (pos > 0 && chr != ')');
return pos;
};
auto findWordStart = [cursor, this](int pos) -> int {
// Find start position
QChar chr;
do {
chr = textDocument()->characterAt(--pos);
} while (pos > 0 && isValidIdentifierChar(chr));
return ++pos;
};
const int funcStart = findFunctionStart();
const int funcEnd = findFunctionEnd();
if (auto project = ProjectTree::currentProject()) { if (auto project = ProjectTree::currentProject()) {
buffer.replace("${CMAKE_SOURCE_DIR}", project->projectDirectory().path()); buffer.replace("${CMAKE_SOURCE_DIR}", project->projectDirectory().path());
if (auto bs = ProjectTree::currentBuildSystem()) { if (auto bs = ProjectTree::currentBuildSystem()) {
@@ -295,20 +337,24 @@ void CMakeEditorWidget::findLinkAt(const QTextCursor &cursor,
addTextStartEndToLink(link); addTextStartEndToLink(link);
return processLinkCallback(link); return processLinkCallback(link);
} }
// Handle include(CMakeFileWithoutSuffix)
QString functionName;
if (funcStart > funcEnd) {
int funcStartPos = findWordStart(funcStart);
functionName = textDocument()->textAt(funcStartPos, funcStart - funcStartPos);
if (functionName == "include" && cbs->dotCMakeFilesHash().contains(buffer)) {
link = cbs->dotCMakeFilesHash().value(buffer);
addTextStartEndToLink(link);
return processLinkCallback(link);
}
}
} }
} }
// TODO: Resolve more variables // TODO: Resolve more variables
// Resolve local variables and functions // Resolve local variables and functions
auto findFunctionEnd = [cursor, this]() -> int { auto hash = getLocalSymbolsHash(textDocument()->textAt(0, funcEnd + 1).toUtf8(),
int pos = cursor.position();
QChar chr;
do {
chr = textDocument()->characterAt(--pos);
} while (pos > 0 && chr != ')');
return pos;
};
auto hash = getLocalSymbolsHash(textDocument()->textAt(0, findFunctionEnd() + 1).toUtf8(),
textDocument()->filePath()); textDocument()->filePath());
// Strip variable coating // Strip variable coating