2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2016 The Qt Company Ltd.
|
2022-12-21 10:12:09 +01:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
2011-02-18 10:36:52 +01:00
|
|
|
|
2012-09-06 22:38:25 +08:00
|
|
|
#include "cmakefilecompletionassist.h"
|
2020-04-17 15:30:05 +02:00
|
|
|
|
2023-09-17 20:19:04 +02:00
|
|
|
#include "cmakebuildsystem.h"
|
|
|
|
|
#include "cmakebuildtarget.h"
|
2023-08-21 17:20:02 +02:00
|
|
|
#include "cmakekitaspect.h"
|
2023-09-17 20:19:04 +02:00
|
|
|
#include "cmakeproject.h"
|
2020-04-17 15:30:05 +02:00
|
|
|
#include "cmakeprojectconstants.h"
|
|
|
|
|
#include "cmaketool.h"
|
2023-09-21 13:36:17 +02:00
|
|
|
#include "cmaketoolmanager.h"
|
2010-11-08 14:01:50 +01:00
|
|
|
|
2023-09-22 12:29:25 +02:00
|
|
|
#include "3rdparty/cmake/cmListFileCache.h"
|
|
|
|
|
|
2017-12-04 13:53:38 +01:00
|
|
|
#include <projectexplorer/project.h>
|
2023-09-17 20:19:04 +02:00
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
|
|
|
|
#include <projectexplorer/projectexplorericons.h>
|
2023-02-14 15:47:22 +01:00
|
|
|
#include <projectexplorer/projectmanager.h>
|
2023-09-17 20:19:04 +02:00
|
|
|
#include <projectexplorer/projectnodes.h>
|
2015-02-24 21:57:00 +01:00
|
|
|
#include <projectexplorer/target.h>
|
2023-02-14 15:47:22 +01:00
|
|
|
|
2022-07-08 17:07:33 +02:00
|
|
|
#include <texteditor/codeassist/assistinterface.h>
|
2023-09-17 20:19:04 +02:00
|
|
|
#include <texteditor/codeassist/genericproposal.h>
|
|
|
|
|
#include <texteditor/texteditorsettings.h>
|
|
|
|
|
|
|
|
|
|
#include <utils/fsengine/fileiconprovider.h>
|
|
|
|
|
#include <utils/utilsicons.h>
|
2015-02-24 21:57:00 +01:00
|
|
|
|
2012-09-06 22:38:25 +08:00
|
|
|
using namespace TextEditor;
|
2015-02-24 21:57:00 +01:00
|
|
|
using namespace ProjectExplorer;
|
2023-09-17 20:19:04 +02:00
|
|
|
using namespace Utils;
|
2010-11-08 14:01:50 +01:00
|
|
|
|
2022-09-29 15:26:31 +02:00
|
|
|
namespace CMakeProjectManager::Internal {
|
2010-11-08 14:01:50 +01:00
|
|
|
|
2023-09-17 20:19:04 +02:00
|
|
|
class CMakeFileCompletionAssist : public AsyncProcessor
|
2012-09-06 22:38:25 +08:00
|
|
|
{
|
2022-09-29 15:26:31 +02:00
|
|
|
public:
|
|
|
|
|
CMakeFileCompletionAssist();
|
|
|
|
|
|
2022-11-15 14:19:06 +01:00
|
|
|
IAssistProposal *performAsync() final;
|
2023-09-17 20:19:04 +02:00
|
|
|
|
|
|
|
|
const QIcon m_variableIcon;
|
|
|
|
|
const QIcon m_projectVariableIcon;
|
|
|
|
|
const QIcon m_functionIcon;
|
|
|
|
|
const QIcon m_projectFunctionIcon;
|
|
|
|
|
const QIcon m_propertyIcon;
|
|
|
|
|
const QIcon m_argsIcon;
|
|
|
|
|
const QIcon m_genexIcon;
|
|
|
|
|
const QIcon m_moduleIcon;
|
|
|
|
|
const QIcon m_targetsIcon;
|
|
|
|
|
|
|
|
|
|
TextEditor::SnippetAssistCollector m_snippetCollector;
|
2022-09-29 15:26:31 +02:00
|
|
|
};
|
2015-02-24 21:57:00 +01:00
|
|
|
|
2023-09-17 20:19:04 +02:00
|
|
|
CMakeFileCompletionAssist::CMakeFileCompletionAssist()
|
|
|
|
|
: m_variableIcon(CodeModelIcon::iconForType(CodeModelIcon::VarPublic))
|
|
|
|
|
, m_projectVariableIcon(CodeModelIcon::iconForType(CodeModelIcon::VarPublicStatic))
|
|
|
|
|
, m_functionIcon(CodeModelIcon::iconForType(CodeModelIcon::FuncPublic))
|
|
|
|
|
, m_projectFunctionIcon(CodeModelIcon::iconForType(CodeModelIcon::FuncPublicStatic))
|
|
|
|
|
, m_propertyIcon(CodeModelIcon::iconForType(CodeModelIcon::Property))
|
|
|
|
|
, m_argsIcon(CodeModelIcon::iconForType(CodeModelIcon::Enum))
|
|
|
|
|
, m_genexIcon(CodeModelIcon::iconForType(CodeModelIcon::Class))
|
|
|
|
|
, m_moduleIcon(
|
|
|
|
|
ProjectExplorer::DirectoryIcon(ProjectExplorer::Constants::FILEOVERLAY_MODULES).icon())
|
|
|
|
|
, m_targetsIcon(ProjectExplorer::Icons::BUILD.icon())
|
|
|
|
|
, m_snippetCollector(Constants::CMAKE_SNIPPETS_GROUP_ID,
|
2023-09-19 17:22:19 +02:00
|
|
|
FileIconProvider::icon(FilePath::fromString("CMakeLists.txt")))
|
2023-09-17 20:19:04 +02:00
|
|
|
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
static bool isInComment(const AssistInterface *interface)
|
|
|
|
|
{
|
|
|
|
|
QTextCursor tc(interface->textDocument());
|
|
|
|
|
tc.setPosition(interface->position());
|
|
|
|
|
tc.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
|
|
|
|
|
return tc.selectedText().contains('#');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool isValidIdentifierChar(const QChar &chr)
|
|
|
|
|
{
|
|
|
|
|
return chr.isLetterOrNumber() || chr == '_' || chr == '-';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int findWordStart(const AssistInterface *interface, int pos)
|
|
|
|
|
{
|
|
|
|
|
// Find start position
|
|
|
|
|
QChar chr;
|
|
|
|
|
do {
|
|
|
|
|
chr = interface->characterAt(--pos);
|
|
|
|
|
} while (pos > 0 && isValidIdentifierChar(chr));
|
|
|
|
|
|
|
|
|
|
return ++pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int findFunctionStart(const AssistInterface *interface)
|
|
|
|
|
{
|
|
|
|
|
int pos = interface->position();
|
|
|
|
|
|
|
|
|
|
QChar chr;
|
|
|
|
|
do {
|
|
|
|
|
chr = interface->characterAt(--pos);
|
|
|
|
|
} while (pos > 0 && chr != '(');
|
|
|
|
|
|
|
|
|
|
if (pos > 0 && chr == '(') {
|
|
|
|
|
// allow space between function name and (
|
|
|
|
|
do {
|
|
|
|
|
chr = interface->characterAt(--pos);
|
|
|
|
|
} while (pos > 0 && chr.isSpace());
|
|
|
|
|
++pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int findFunctionEnd(const AssistInterface *interface)
|
|
|
|
|
{
|
|
|
|
|
int pos = interface->position();
|
|
|
|
|
|
|
|
|
|
QChar chr;
|
|
|
|
|
do {
|
|
|
|
|
chr = interface->characterAt(--pos);
|
|
|
|
|
} while (pos > 0 && chr != ')');
|
|
|
|
|
|
|
|
|
|
return pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int findPathStart(const AssistInterface *interface)
|
|
|
|
|
{
|
|
|
|
|
// For pragmatic reasons, we don't support spaces in file names here.
|
|
|
|
|
static const auto canOccurInFilePath = [](const QChar &c) {
|
|
|
|
|
return c.isLetterOrNumber() || c == '.' || c == '/' || c == '_' || c == '-';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int pos = interface->position();
|
|
|
|
|
QChar chr;
|
|
|
|
|
// Skip to the start of a name
|
|
|
|
|
do {
|
|
|
|
|
chr = interface->characterAt(--pos);
|
|
|
|
|
} while (canOccurInFilePath(chr));
|
|
|
|
|
|
|
|
|
|
return ++pos;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-20 14:17:18 +02:00
|
|
|
template<typename T>
|
|
|
|
|
QList<AssistProposalItemInterface *> generateList(const T &words, const QIcon &icon)
|
2016-08-18 15:39:13 +02:00
|
|
|
{
|
2023-09-20 14:17:18 +02:00
|
|
|
return transform<QList>(words, [&icon](const QString &word) -> AssistProposalItemInterface * {
|
2023-09-17 20:19:04 +02:00
|
|
|
AssistProposalItem *item = new AssistProposalItem();
|
|
|
|
|
item->setText(word);
|
|
|
|
|
item->setIcon(icon);
|
|
|
|
|
return item;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-22 22:47:31 +02:00
|
|
|
QString readFirstParagraphs(const QString &element, const FilePath &helpFile)
|
|
|
|
|
{
|
2023-09-18 22:08:23 +02:00
|
|
|
static QMap<FilePath, QString> map;
|
|
|
|
|
if (map.contains(helpFile))
|
|
|
|
|
return map.value(helpFile);
|
|
|
|
|
|
2023-09-22 22:47:31 +02:00
|
|
|
auto content = helpFile.fileContents(1024).value_or(QByteArray());
|
2023-09-18 22:08:23 +02:00
|
|
|
const QString firstParagraphs
|
|
|
|
|
= QString("```\n%1\n```").arg(QString::fromUtf8(content.left(content.lastIndexOf("\n"))));
|
|
|
|
|
|
|
|
|
|
map[helpFile] = firstParagraphs;
|
|
|
|
|
return firstParagraphs;
|
2023-09-22 22:47:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QList<AssistProposalItemInterface *> generateList(const QMap<QString, FilePath> &words,
|
|
|
|
|
const QIcon &icon)
|
|
|
|
|
{
|
|
|
|
|
struct MarkDownAssitProposalItem : public AssistProposalItem
|
|
|
|
|
{
|
|
|
|
|
Qt::TextFormat detailFormat() const { return Qt::MarkdownText; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
QList<AssistProposalItemInterface *> list;
|
2023-09-26 07:35:01 +02:00
|
|
|
for (auto it = words.cbegin(); it != words.cend(); ++it) {
|
2023-09-22 22:47:31 +02:00
|
|
|
MarkDownAssitProposalItem *item = new MarkDownAssitProposalItem();
|
2023-09-26 07:35:01 +02:00
|
|
|
item->setText(it.key());
|
|
|
|
|
if (!it.value().isEmpty())
|
|
|
|
|
item->setDetail(readFirstParagraphs(it.key(), it.value()));
|
2023-09-22 22:47:31 +02:00
|
|
|
item->setIcon(icon);
|
|
|
|
|
list << item;
|
|
|
|
|
};
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-17 20:19:04 +02:00
|
|
|
static int addFilePathItems(const AssistInterface *interface,
|
|
|
|
|
QList<AssistProposalItemInterface *> &items,
|
|
|
|
|
int symbolStartPos)
|
|
|
|
|
{
|
|
|
|
|
if (interface->filePath().isEmpty())
|
|
|
|
|
return symbolStartPos;
|
|
|
|
|
|
|
|
|
|
const int startPos = findPathStart(interface);
|
|
|
|
|
|
|
|
|
|
if (interface->reason() == IdleEditor
|
|
|
|
|
&& interface->position() - startPos
|
|
|
|
|
< TextEditorSettings::completionSettings().m_characterThreshold)
|
|
|
|
|
return symbolStartPos;
|
|
|
|
|
|
|
|
|
|
const QString word = interface->textAt(startPos, interface->position() - startPos);
|
|
|
|
|
FilePath baseDir = interface->filePath().absoluteFilePath().parentDir();
|
|
|
|
|
const int lastSlashPos = word.lastIndexOf(QLatin1Char('/'));
|
|
|
|
|
|
|
|
|
|
QString prefix = word;
|
|
|
|
|
if (lastSlashPos != -1) {
|
|
|
|
|
prefix = word.mid(lastSlashPos + 1);
|
|
|
|
|
baseDir = baseDir.pathAppended(word.left(lastSlashPos));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FilePaths filesPaths = baseDir.dirEntries(
|
|
|
|
|
FileFilter({QString("%1*").arg(prefix)}, QDir::AllEntries | QDir::NoDotAndDotDot));
|
|
|
|
|
for (const auto &file : filesPaths) {
|
|
|
|
|
AssistProposalItem *item = new AssistProposalItem;
|
|
|
|
|
QString fileName = file.fileName();
|
|
|
|
|
if (file.isDir())
|
|
|
|
|
fileName.append("/");
|
|
|
|
|
item->setText(fileName);
|
|
|
|
|
item->setIcon(FileIconProvider::icon(file));
|
|
|
|
|
|
|
|
|
|
items << item;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return startPos;
|
2016-08-18 15:39:13 +02:00
|
|
|
}
|
2015-02-24 21:57:00 +01:00
|
|
|
|
2023-09-22 12:29:25 +02:00
|
|
|
QPair<QStringList, QStringList> getLocalFunctionsAndVariables(const QByteArray &content)
|
|
|
|
|
{
|
|
|
|
|
cmListFile cmakeListFile;
|
|
|
|
|
std::string errorString;
|
|
|
|
|
if (!content.isEmpty()) {
|
|
|
|
|
const std::string fileName = "buffer";
|
|
|
|
|
if (!cmakeListFile.ParseString(content.toStdString(), fileName, errorString))
|
|
|
|
|
return {{}, {}};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStringList variables;
|
|
|
|
|
QStringList functions;
|
|
|
|
|
for (const auto &func : cmakeListFile.Functions) {
|
|
|
|
|
if (func.Arguments().size() == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (func.LowerCaseName() == "macro" || func.LowerCaseName() == "function")
|
|
|
|
|
functions << QString::fromUtf8(func.Arguments()[0].Value);
|
|
|
|
|
if (func.LowerCaseName() == "set" || func.LowerCaseName() == "option")
|
|
|
|
|
variables << QString::fromUtf8(func.Arguments()[0].Value);
|
|
|
|
|
}
|
|
|
|
|
return {functions, variables};
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-15 14:19:06 +01:00
|
|
|
IAssistProposal *CMakeFileCompletionAssist::performAsync()
|
2015-02-24 21:57:00 +01:00
|
|
|
{
|
2023-09-17 20:19:04 +02:00
|
|
|
CMakeKeywords keywords;
|
|
|
|
|
CMakeKeywords projectKeywords;
|
|
|
|
|
Project *project = nullptr;
|
|
|
|
|
const FilePath &filePath = interface()->filePath();
|
2023-09-14 13:23:37 +02:00
|
|
|
if (!filePath.isEmpty() && filePath.isFile()) {
|
2023-09-21 13:36:17 +02:00
|
|
|
CMakeTool *cmake = nullptr;
|
2023-09-17 20:19:04 +02:00
|
|
|
project = static_cast<CMakeProject *>(ProjectManager::projectForFile(filePath));
|
2023-09-21 13:36:17 +02:00
|
|
|
if (project && project->activeTarget())
|
|
|
|
|
cmake = CMakeKitAspect::cmakeTool(project->activeTarget()->kit());
|
|
|
|
|
|
|
|
|
|
if (!cmake)
|
|
|
|
|
cmake = CMakeToolManager::defaultCMakeTool();
|
|
|
|
|
|
|
|
|
|
if (cmake && cmake->isValid())
|
|
|
|
|
keywords = cmake->keywords();
|
2023-09-17 20:19:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStringList buildTargets;
|
|
|
|
|
if (project && project->activeTarget()) {
|
|
|
|
|
const auto bs = qobject_cast<CMakeBuildSystem *>(project->activeTarget()->buildSystem());
|
|
|
|
|
if (bs) {
|
|
|
|
|
for (const auto &target : std::as_const(bs->buildTargets()))
|
|
|
|
|
if (target.targetType != TargetType::UtilityType)
|
|
|
|
|
buildTargets << target.title;
|
|
|
|
|
projectKeywords = bs->projectKeywords();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isInComment(interface()))
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
const int startPos = findWordStart(interface(), interface()->position());
|
|
|
|
|
|
|
|
|
|
const int functionStart = findFunctionStart(interface());
|
|
|
|
|
const int prevFunctionEnd = findFunctionEnd(interface());
|
|
|
|
|
|
|
|
|
|
QString functionName;
|
|
|
|
|
if (functionStart > prevFunctionEnd) {
|
|
|
|
|
int functionStartPos = findWordStart(interface(), functionStart);
|
|
|
|
|
functionName
|
|
|
|
|
= interface()->textAt(functionStartPos, functionStart - functionStartPos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (interface()->reason() == IdleEditor) {
|
|
|
|
|
const QChar chr = interface()->characterAt(interface()->position());
|
|
|
|
|
const int wordSize = interface()->position() - startPos;
|
|
|
|
|
if (isValidIdentifierChar(chr)
|
|
|
|
|
|| wordSize < TextEditorSettings::completionSettings().m_characterThreshold) {
|
|
|
|
|
return nullptr;
|
2015-02-24 21:57:00 +01:00
|
|
|
}
|
|
|
|
|
}
|
2015-02-04 17:54:46 +01:00
|
|
|
|
2023-09-22 12:29:25 +02:00
|
|
|
auto [localFunctions, localVariables] = getLocalFunctionsAndVariables(
|
|
|
|
|
interface()->textAt(0, prevFunctionEnd + 1).toUtf8());
|
|
|
|
|
|
2023-09-17 20:19:04 +02:00
|
|
|
QList<AssistProposalItemInterface *> items;
|
|
|
|
|
|
|
|
|
|
const QString varGenexToken = interface()->textAt(startPos - 2, 2);
|
|
|
|
|
if (varGenexToken == "${" || varGenexToken == "$<") {
|
|
|
|
|
if (varGenexToken == "${") {
|
|
|
|
|
items.append(generateList(keywords.variables, m_variableIcon));
|
|
|
|
|
items.append(generateList(projectKeywords.variables, m_projectVariableIcon));
|
|
|
|
|
}
|
|
|
|
|
if (varGenexToken == "$<")
|
|
|
|
|
items.append(generateList(keywords.generatorExpressions, m_genexIcon));
|
|
|
|
|
|
|
|
|
|
return new GenericProposal(startPos, items);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int fileStartPos = startPos;
|
|
|
|
|
const auto onlyFileItems = [&] { return fileStartPos != startPos; };
|
|
|
|
|
|
|
|
|
|
if (functionName == "if" || functionName == "elseif" || functionName == "while"
|
2023-09-19 17:22:19 +02:00
|
|
|
|| functionName == "set" || functionName == "list"
|
|
|
|
|
|| functionName == "cmake_print_variables") {
|
2023-09-17 20:19:04 +02:00
|
|
|
items.append(generateList(keywords.variables, m_variableIcon));
|
|
|
|
|
items.append(generateList(projectKeywords.variables, m_projectVariableIcon));
|
2023-09-22 12:29:25 +02:00
|
|
|
items.append(generateList(localVariables, m_variableIcon));
|
2023-09-17 20:19:04 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-20 22:39:50 +02:00
|
|
|
if (functionName == "if" || functionName == "elseif" || functionName == "cmake_policy")
|
|
|
|
|
items.append(generateList(keywords.policies, m_variableIcon));
|
|
|
|
|
|
2023-09-17 20:19:04 +02:00
|
|
|
if (functionName.contains("path") || functionName.contains("file")
|
|
|
|
|
|| functionName.contains("add_executable") || functionName.contains("add_library")
|
|
|
|
|
|| functionName == "include" || functionName == "add_subdirectory"
|
|
|
|
|
|| functionName == "install" || functionName == "target_sources" || functionName == "set"
|
|
|
|
|
|| functionName == "list") {
|
|
|
|
|
fileStartPos = addFilePathItems(interface(), items, startPos);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-19 17:22:19 +02:00
|
|
|
if (functionName == "set_property" || functionName == "cmake_print_properties")
|
2023-09-17 20:19:04 +02:00
|
|
|
items.append(generateList(keywords.properties, m_propertyIcon));
|
|
|
|
|
|
|
|
|
|
if (functionName == "set_directory_properties")
|
|
|
|
|
items.append(generateList(keywords.directoryProperties, m_propertyIcon));
|
|
|
|
|
if (functionName == "set_source_files_properties")
|
|
|
|
|
items.append(generateList(keywords.sourceProperties, m_propertyIcon));
|
|
|
|
|
if (functionName == "set_target_properties")
|
|
|
|
|
items.append(generateList(keywords.targetProperties, m_propertyIcon));
|
|
|
|
|
if (functionName == "set_tests_properties")
|
|
|
|
|
items.append(generateList(keywords.testProperties, m_propertyIcon));
|
|
|
|
|
|
|
|
|
|
if (functionName == "include" && !onlyFileItems())
|
|
|
|
|
items.append(generateList(keywords.includeStandardModules, m_moduleIcon));
|
|
|
|
|
if (functionName == "find_package")
|
|
|
|
|
items.append(generateList(keywords.findModules, m_moduleIcon));
|
|
|
|
|
|
|
|
|
|
if ((functionName.contains("target") || functionName == "install"
|
|
|
|
|
|| functionName == "add_dependencies" || functionName == "set_property"
|
2023-09-19 17:22:19 +02:00
|
|
|
|| functionName == "export" || functionName == "cmake_print_properties")
|
2023-09-17 20:19:04 +02:00
|
|
|
&& !onlyFileItems())
|
|
|
|
|
items.append(generateList(buildTargets, m_targetsIcon));
|
|
|
|
|
|
|
|
|
|
if (keywords.functionArgs.contains(functionName) && !onlyFileItems()) {
|
|
|
|
|
QStringList functionSymbols = keywords.functionArgs.value(functionName);
|
|
|
|
|
items.append(generateList(functionSymbols, m_argsIcon));
|
|
|
|
|
} else if (functionName.isEmpty()) {
|
|
|
|
|
// On a new line we just want functions
|
|
|
|
|
items.append(generateList(keywords.functions, m_functionIcon));
|
|
|
|
|
items.append(generateList(projectKeywords.functions, m_projectFunctionIcon));
|
2023-09-22 12:29:25 +02:00
|
|
|
items.append(generateList(localFunctions, m_functionIcon));
|
2023-09-19 17:22:19 +02:00
|
|
|
|
|
|
|
|
// Snippets would make more sense only for the top level suggestions
|
|
|
|
|
items.append(m_snippetCollector.collect());
|
2023-09-17 20:19:04 +02:00
|
|
|
} else {
|
|
|
|
|
// Inside an unknown function we could have variables or properties
|
|
|
|
|
fileStartPos = addFilePathItems(interface(), items, startPos);
|
|
|
|
|
if (!onlyFileItems()) {
|
|
|
|
|
items.append(generateList(keywords.variables, m_variableIcon));
|
|
|
|
|
items.append(generateList(projectKeywords.variables, m_projectVariableIcon));
|
2023-09-22 12:29:25 +02:00
|
|
|
items.append(generateList(localVariables, m_variableIcon));
|
|
|
|
|
|
2023-09-17 20:19:04 +02:00
|
|
|
items.append(generateList(keywords.properties, m_propertyIcon));
|
|
|
|
|
items.append(generateList(buildTargets, m_targetsIcon));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new GenericProposal(startPos, items);
|
2012-09-06 22:38:25 +08:00
|
|
|
}
|
2022-09-29 15:26:31 +02:00
|
|
|
|
|
|
|
|
IAssistProcessor *CMakeFileCompletionAssistProvider::createProcessor(const AssistInterface *) const
|
|
|
|
|
{
|
|
|
|
|
return new CMakeFileCompletionAssist;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-17 20:19:04 +02:00
|
|
|
int CMakeFileCompletionAssistProvider::activationCharSequenceLength() const
|
|
|
|
|
{
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CMakeFileCompletionAssistProvider::isActivationCharSequence(const QString &sequence) const
|
|
|
|
|
{
|
|
|
|
|
return sequence.endsWith("${") || sequence.endsWith("$<") || sequence.endsWith("/")
|
|
|
|
|
|| sequence.endsWith("(");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace CMakeProjectManager::Internal
|