forked from qt-creator/qt-creator
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:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user