forked from qt-creator/qt-creator
Editor: move ownership of assist interface to processor
This way the base class can manage the lifetime of the interface object and it doesn't need to be done in each implementation of perform. Change-Id: Ie1ce742e31b688a337533ee6c57d376146e25ace Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -46,7 +46,7 @@ public:
|
|||||||
unsigned completionOperator, CustomAssistMode mode);
|
unsigned completionOperator, CustomAssistMode mode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IAssistProposal *perform(AssistInterface *interface) override;
|
IAssistProposal *perform() override;
|
||||||
|
|
||||||
AssistProposalItemInterface *createItem(const QString &text, const QIcon &icon) const;
|
AssistProposalItemInterface *createItem(const QString &text, const QIcon &icon) const;
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ public:
|
|||||||
~ClangdCompletionAssistProcessor();
|
~ClangdCompletionAssistProcessor();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IAssistProposal *perform(AssistInterface *interface) override;
|
IAssistProposal *perform() override;
|
||||||
QList<AssistProposalItemInterface *> generateCompletionItems(
|
QList<AssistProposalItemInterface *> generateCompletionItems(
|
||||||
const QList<LanguageServerProtocol::CompletionItem> &items) const override;
|
const QList<LanguageServerProtocol::CompletionItem> &items) const override;
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ public:
|
|||||||
ClangdFunctionHintProcessor(ClangdClient *client);
|
ClangdFunctionHintProcessor(ClangdClient *client);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IAssistProposal *perform(AssistInterface *interface) override;
|
IAssistProposal *perform() override;
|
||||||
|
|
||||||
ClangdClient * const m_client;
|
ClangdClient * const m_client;
|
||||||
};
|
};
|
||||||
@@ -152,11 +152,7 @@ IAssistProcessor *ClangdCompletionAssistProvider::createProcessor(
|
|||||||
if (contextAnalyzer.completionAction()
|
if (contextAnalyzer.completionAction()
|
||||||
!= ClangCompletionContextAnalyzer::CompleteIncludePath) {
|
!= ClangCompletionContextAnalyzer::CompleteIncludePath) {
|
||||||
class NoOpProcessor : public IAssistProcessor {
|
class NoOpProcessor : public IAssistProcessor {
|
||||||
IAssistProposal *perform(AssistInterface *interface) override
|
IAssistProposal *perform() override { return nullptr; }
|
||||||
{
|
|
||||||
delete interface;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
return new NoOpProcessor;
|
return new NoOpProcessor;
|
||||||
}
|
}
|
||||||
@@ -406,7 +402,7 @@ CustomAssistProcessor::CustomAssistProcessor(ClangdClient *client, int position,
|
|||||||
, m_mode(mode)
|
, m_mode(mode)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
IAssistProposal *CustomAssistProcessor::perform(AssistInterface *interface)
|
IAssistProposal *CustomAssistProcessor::perform()
|
||||||
{
|
{
|
||||||
QList<AssistProposalItemInterface *> completions;
|
QList<AssistProposalItemInterface *> completions;
|
||||||
switch (m_mode) {
|
switch (m_mode) {
|
||||||
@@ -422,21 +418,20 @@ IAssistProposal *CustomAssistProcessor::perform(AssistInterface *interface)
|
|||||||
: CppCompletionAssistProcessor::preprocessorCompletions()) {
|
: CppCompletionAssistProcessor::preprocessorCompletions()) {
|
||||||
completions << createItem(completion, macroIcon);
|
completions << createItem(completion, macroIcon);
|
||||||
}
|
}
|
||||||
if (ProjectFile::isObjC(interface->filePath().toString()))
|
if (ProjectFile::isObjC(interface()->filePath().toString()))
|
||||||
completions << createItem("import", macroIcon);
|
completions << createItem("import", macroIcon);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CustomAssistMode::IncludePath: {
|
case CustomAssistMode::IncludePath: {
|
||||||
HeaderPaths headerPaths;
|
HeaderPaths headerPaths;
|
||||||
const ProjectPart::ConstPtr projectPart
|
const ProjectPart::ConstPtr projectPart
|
||||||
= projectPartForFile(interface->filePath().toString());
|
= projectPartForFile(interface()->filePath().toString());
|
||||||
if (projectPart)
|
if (projectPart)
|
||||||
headerPaths = projectPart->headerPaths;
|
headerPaths = projectPart->headerPaths;
|
||||||
completions = completeInclude(m_endPos, m_completionOperator, interface, headerPaths);
|
completions = completeInclude(m_endPos, m_completionOperator, interface(), headerPaths);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete interface;
|
|
||||||
GenericProposalModelPtr model(new GenericProposalModel);
|
GenericProposalModelPtr model(new GenericProposalModel);
|
||||||
model->loadContent(completions);
|
model->loadContent(completions);
|
||||||
const auto proposal = new GenericProposal(m_position, model);
|
const auto proposal = new GenericProposal(m_position, model);
|
||||||
@@ -572,14 +567,14 @@ ClangdCompletionAssistProcessor::~ClangdCompletionAssistProcessor()
|
|||||||
<< "ClangdCompletionAssistProcessor took: " << m_timer.elapsed() << " ms";
|
<< "ClangdCompletionAssistProcessor took: " << m_timer.elapsed() << " ms";
|
||||||
}
|
}
|
||||||
|
|
||||||
IAssistProposal *ClangdCompletionAssistProcessor::perform(AssistInterface *interface)
|
IAssistProposal *ClangdCompletionAssistProcessor::perform()
|
||||||
{
|
{
|
||||||
if (m_client->testingEnabled()) {
|
if (m_client->testingEnabled()) {
|
||||||
setAsyncCompletionAvailableHandler([this](IAssistProposal *proposal) {
|
setAsyncCompletionAvailableHandler([this](IAssistProposal *proposal) {
|
||||||
emit m_client->proposalReady(proposal);
|
emit m_client->proposalReady(proposal);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return LanguageClientCompletionAssistProcessor::perform(interface);
|
return LanguageClientCompletionAssistProcessor::perform();
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<AssistProposalItemInterface *> ClangdCompletionAssistProcessor::generateCompletionItems(
|
QList<AssistProposalItemInterface *> ClangdCompletionAssistProcessor::generateCompletionItems(
|
||||||
@@ -618,14 +613,14 @@ ClangdFunctionHintProcessor::ClangdFunctionHintProcessor(ClangdClient *client)
|
|||||||
, m_client(client)
|
, m_client(client)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
IAssistProposal *ClangdFunctionHintProcessor::perform(AssistInterface *interface)
|
IAssistProposal *ClangdFunctionHintProcessor::perform()
|
||||||
{
|
{
|
||||||
if (m_client->testingEnabled()) {
|
if (m_client->testingEnabled()) {
|
||||||
setAsyncCompletionAvailableHandler([this](IAssistProposal *proposal) {
|
setAsyncCompletionAvailableHandler([this](IAssistProposal *proposal) {
|
||||||
emit m_client->proposalReady(proposal);
|
emit m_client->proposalReady(proposal);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return FunctionHintProcessor::perform(interface);
|
return FunctionHintProcessor::perform();
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangdCompletionCapabilities::ClangdCompletionCapabilities(const JsonObject &object)
|
ClangdCompletionCapabilities::ClangdCompletionCapabilities(const JsonObject &object)
|
||||||
|
@@ -42,9 +42,8 @@ public:
|
|||||||
void resetData(bool resetFollowSymbolData);
|
void resetData(bool resetFollowSymbolData);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IAssistProposal *perform(AssistInterface *interface) override
|
IAssistProposal *perform() override
|
||||||
{
|
{
|
||||||
delete interface;
|
|
||||||
return createProposal(false);
|
return createProposal(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +60,7 @@ public:
|
|||||||
: m_followSymbol(followSymbol) {}
|
: m_followSymbol(followSymbol) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IAssistProcessor *createProcessor(const AssistInterface *) const override;
|
IAssistProcessor *createProcessor(const AssistInterface *interface) const override;
|
||||||
|
|
||||||
const QPointer<ClangdFollowSymbol> m_followSymbol;
|
const QPointer<ClangdFollowSymbol> m_followSymbol;
|
||||||
};
|
};
|
||||||
|
@@ -47,15 +47,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IAssistProposal *perform(AssistInterface *interface) override
|
IAssistProposal *perform() override
|
||||||
{
|
{
|
||||||
m_interface = interface;
|
|
||||||
|
|
||||||
// Step 1: Collect clangd code actions asynchronously
|
// Step 1: Collect clangd code actions asynchronously
|
||||||
LanguageClientQuickFixAssistProcessor::perform(interface);
|
LanguageClientQuickFixAssistProcessor::perform();
|
||||||
|
|
||||||
// Step 2: Collect built-in quickfixes synchronously
|
// Step 2: Collect built-in quickfixes synchronously
|
||||||
m_builtinOps = CppEditor::quickFixOperations(interface);
|
m_builtinOps = CppEditor::quickFixOperations(interface());
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -82,13 +80,12 @@ private:
|
|||||||
ops << op;
|
ops << op;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return GenericProposal::createProposal(m_interface, ops + m_builtinOps);
|
return GenericProposal::createProposal(interface(), ops + m_builtinOps);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QuickFixOperations m_builtinOps;
|
QuickFixOperations m_builtinOps;
|
||||||
const AssistInterface *m_interface = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ClangdQuickFixProvider::ClangdQuickFixProvider(ClangdClient *client)
|
ClangdQuickFixProvider::ClangdQuickFixProvider(ClangdClient *client)
|
||||||
|
@@ -24,7 +24,7 @@ class CMakeFileCompletionAssist : public KeywordsCompletionAssistProcessor
|
|||||||
public:
|
public:
|
||||||
CMakeFileCompletionAssist();
|
CMakeFileCompletionAssist();
|
||||||
|
|
||||||
IAssistProposal *performAsync(AssistInterface *interface) final;
|
IAssistProposal *performAsync() final;
|
||||||
};
|
};
|
||||||
|
|
||||||
CMakeFileCompletionAssist::CMakeFileCompletionAssist() :
|
CMakeFileCompletionAssist::CMakeFileCompletionAssist() :
|
||||||
@@ -34,10 +34,10 @@ CMakeFileCompletionAssist::CMakeFileCompletionAssist() :
|
|||||||
setDynamicCompletionFunction(&TextEditor::pathComplete);
|
setDynamicCompletionFunction(&TextEditor::pathComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
IAssistProposal *CMakeFileCompletionAssist::performAsync(AssistInterface *interface)
|
IAssistProposal *CMakeFileCompletionAssist::performAsync()
|
||||||
{
|
{
|
||||||
Keywords kw;
|
Keywords kw;
|
||||||
const Utils::FilePath &filePath = interface->filePath();
|
const Utils::FilePath &filePath = interface()->filePath();
|
||||||
if (!filePath.isEmpty() && filePath.toFileInfo().isFile()) {
|
if (!filePath.isEmpty() && filePath.toFileInfo().isFile()) {
|
||||||
Project *p = SessionManager::projectForFile(filePath);
|
Project *p = SessionManager::projectForFile(filePath);
|
||||||
if (p && p->activeTarget()) {
|
if (p && p->activeTarget()) {
|
||||||
@@ -48,7 +48,7 @@ IAssistProposal *CMakeFileCompletionAssist::performAsync(AssistInterface *interf
|
|||||||
}
|
}
|
||||||
|
|
||||||
setKeywords(kw);
|
setKeywords(kw);
|
||||||
return KeywordsCompletionAssistProcessor::performAsync(interface);
|
return KeywordsCompletionAssistProcessor::performAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
IAssistProcessor *CMakeFileCompletionAssistProvider::createProcessor(const AssistInterface *) const
|
IAssistProcessor *CMakeFileCompletionAssistProvider::createProcessor(const AssistInterface *) const
|
||||||
|
@@ -86,17 +86,19 @@ public:
|
|||||||
QTextCursor textCursor = m_editorWidget->textCursor();
|
QTextCursor textCursor = m_editorWidget->textCursor();
|
||||||
textCursor.setPosition(m_position);
|
textCursor.setPosition(m_position);
|
||||||
m_editorWidget->setTextCursor(textCursor);
|
m_editorWidget->setTextCursor(textCursor);
|
||||||
CppCompletionAssistInterface *ai
|
std::unique_ptr<CppCompletionAssistInterface> ai(
|
||||||
= new CppCompletionAssistInterface(m_editorWidget->textDocument()->filePath(),
|
new CppCompletionAssistInterface(m_editorWidget->textDocument()->filePath(),
|
||||||
m_editorWidget,
|
m_editorWidget,
|
||||||
ExplicitlyInvoked, m_snapshot,
|
ExplicitlyInvoked,
|
||||||
|
m_snapshot,
|
||||||
ProjectExplorer::HeaderPaths(),
|
ProjectExplorer::HeaderPaths(),
|
||||||
languageFeatures);
|
languageFeatures));
|
||||||
ai->prepareForAsyncUse();
|
ai->prepareForAsyncUse();
|
||||||
ai->recreateTextDocument();
|
ai->recreateTextDocument();
|
||||||
InternalCppCompletionAssistProcessor processor;
|
InternalCppCompletionAssistProcessor processor;
|
||||||
|
processor.setupAssistInterface(std::move(ai));
|
||||||
|
|
||||||
const QScopedPointer<IAssistProposal> proposal(processor.performAsync(ai));
|
const QScopedPointer<IAssistProposal> proposal(processor.performAsync());
|
||||||
if (!proposal)
|
if (!proposal)
|
||||||
return completions;
|
return completions;
|
||||||
ProposalModelPtr model = proposal->model();
|
ProposalModelPtr model = proposal->model();
|
||||||
|
@@ -400,7 +400,7 @@ IAssistProcessor *InternalCompletionAssistProvider::createProcessor(const Assist
|
|||||||
return new InternalCppCompletionAssistProcessor;
|
return new InternalCppCompletionAssistProcessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssistInterface *InternalCompletionAssistProvider::createAssistInterface(
|
std::unique_ptr<AssistInterface> InternalCompletionAssistProvider::createAssistInterface(
|
||||||
const Utils::FilePath &filePath,
|
const Utils::FilePath &filePath,
|
||||||
const TextEditorWidget *textEditorWidget,
|
const TextEditorWidget *textEditorWidget,
|
||||||
const LanguageFeatures &languageFeatures,
|
const LanguageFeatures &languageFeatures,
|
||||||
@@ -408,7 +408,8 @@ AssistInterface *InternalCompletionAssistProvider::createAssistInterface(
|
|||||||
{
|
{
|
||||||
QTC_ASSERT(textEditorWidget, return nullptr);
|
QTC_ASSERT(textEditorWidget, return nullptr);
|
||||||
|
|
||||||
return new CppCompletionAssistInterface(filePath,
|
return std::make_unique<CppCompletionAssistInterface>(
|
||||||
|
filePath,
|
||||||
textEditorWidget,
|
textEditorWidget,
|
||||||
BuiltinEditorDocumentParser::get(filePath.toString()),
|
BuiltinEditorDocumentParser::get(filePath.toString()),
|
||||||
languageFeatures,
|
languageFeatures,
|
||||||
@@ -794,11 +795,9 @@ InternalCppCompletionAssistProcessor::InternalCppCompletionAssistProcessor()
|
|||||||
|
|
||||||
InternalCppCompletionAssistProcessor::~InternalCppCompletionAssistProcessor() = default;
|
InternalCppCompletionAssistProcessor::~InternalCppCompletionAssistProcessor() = default;
|
||||||
|
|
||||||
IAssistProposal * InternalCppCompletionAssistProcessor::performAsync(AssistInterface *interface)
|
IAssistProposal * InternalCppCompletionAssistProcessor::performAsync()
|
||||||
{
|
{
|
||||||
m_interface.reset(static_cast<const CppCompletionAssistInterface *>(interface));
|
if (interface()->reason() != ExplicitlyInvoked && !accepts())
|
||||||
|
|
||||||
if (interface->reason() != ExplicitlyInvoked && !accepts())
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
int index = startCompletionHelper();
|
int index = startCompletionHelper();
|
||||||
@@ -814,13 +813,13 @@ IAssistProposal * InternalCppCompletionAssistProcessor::performAsync(AssistInter
|
|||||||
|
|
||||||
bool InternalCppCompletionAssistProcessor::accepts() const
|
bool InternalCppCompletionAssistProcessor::accepts() const
|
||||||
{
|
{
|
||||||
const int pos = m_interface->position();
|
const int pos = interface()->position();
|
||||||
unsigned token = T_EOF_SYMBOL;
|
unsigned token = T_EOF_SYMBOL;
|
||||||
|
|
||||||
const int start = startOfOperator(pos, &token, /*want function call=*/ true);
|
const int start = startOfOperator(pos, &token, /*want function call=*/ true);
|
||||||
if (start != pos) {
|
if (start != pos) {
|
||||||
if (token == T_POUND) {
|
if (token == T_POUND) {
|
||||||
const int column = pos - m_interface->textDocument()->findBlock(start).position();
|
const int column = pos - interface()->textDocument()->findBlock(start).position();
|
||||||
if (column != 1)
|
if (column != 1)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -828,15 +827,15 @@ bool InternalCppCompletionAssistProcessor::accepts() const
|
|||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// Trigger completion after n characters of a name have been typed, when not editing an existing name
|
// Trigger completion after n characters of a name have been typed, when not editing an existing name
|
||||||
QChar characterUnderCursor = m_interface->characterAt(pos);
|
QChar characterUnderCursor = interface()->characterAt(pos);
|
||||||
|
|
||||||
if (!isValidIdentifierChar(characterUnderCursor)) {
|
if (!isValidIdentifierChar(characterUnderCursor)) {
|
||||||
const int startOfName = findStartOfName(pos);
|
const int startOfName = findStartOfName(pos);
|
||||||
if (pos - startOfName >= TextEditorSettings::completionSettings().m_characterThreshold) {
|
if (pos - startOfName >= TextEditorSettings::completionSettings().m_characterThreshold) {
|
||||||
const QChar firstCharacter = m_interface->characterAt(startOfName);
|
const QChar firstCharacter = interface()->characterAt(startOfName);
|
||||||
if (isValidFirstIdentifierChar(firstCharacter)) {
|
if (isValidFirstIdentifierChar(firstCharacter)) {
|
||||||
return !isInCommentOrString(m_interface.data(),
|
return !isInCommentOrString(interface(),
|
||||||
m_interface->languageFeatures());
|
cppInterface()->languageFeatures());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -887,9 +886,9 @@ int InternalCppCompletionAssistProcessor::startOfOperator(int positionInDocument
|
|||||||
unsigned *kind,
|
unsigned *kind,
|
||||||
bool wantFunctionCall) const
|
bool wantFunctionCall) const
|
||||||
{
|
{
|
||||||
const QChar ch = m_interface->characterAt(positionInDocument - 1);
|
const QChar ch = interface()->characterAt(positionInDocument - 1);
|
||||||
const QChar ch2 = m_interface->characterAt(positionInDocument - 2);
|
const QChar ch2 = interface()->characterAt(positionInDocument - 2);
|
||||||
const QChar ch3 = m_interface->characterAt(positionInDocument - 3);
|
const QChar ch3 = interface()->characterAt(positionInDocument - 3);
|
||||||
|
|
||||||
int start = positionInDocument
|
int start = positionInDocument
|
||||||
- CppCompletionAssistProvider::activationSequenceChar(ch, ch2, ch3, kind,
|
- CppCompletionAssistProvider::activationSequenceChar(ch, ch2, ch3, kind,
|
||||||
@@ -898,18 +897,18 @@ int InternalCppCompletionAssistProcessor::startOfOperator(int positionInDocument
|
|||||||
|
|
||||||
const auto dotAtIncludeCompletionHandler = [this](int &start, unsigned *kind) {
|
const auto dotAtIncludeCompletionHandler = [this](int &start, unsigned *kind) {
|
||||||
start = findStartOfName(start);
|
start = findStartOfName(start);
|
||||||
const QChar ch4 = m_interface->characterAt(start - 1);
|
const QChar ch4 = interface()->characterAt(start - 1);
|
||||||
const QChar ch5 = m_interface->characterAt(start - 2);
|
const QChar ch5 = interface()->characterAt(start - 2);
|
||||||
const QChar ch6 = m_interface->characterAt(start - 3);
|
const QChar ch6 = interface()->characterAt(start - 3);
|
||||||
start = start - CppCompletionAssistProvider::activationSequenceChar(
|
start = start - CppCompletionAssistProvider::activationSequenceChar(
|
||||||
ch4, ch5, ch6, kind, false, false);
|
ch4, ch5, ch6, kind, false, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
CppCompletionAssistProcessor::startOfOperator(m_interface->textDocument(),
|
CppCompletionAssistProcessor::startOfOperator(cppInterface()->textDocument(),
|
||||||
positionInDocument,
|
positionInDocument,
|
||||||
kind,
|
kind,
|
||||||
start,
|
start,
|
||||||
m_interface->languageFeatures(),
|
cppInterface()->languageFeatures(),
|
||||||
/*adjustForQt5SignalSlotCompletion=*/ true,
|
/*adjustForQt5SignalSlotCompletion=*/ true,
|
||||||
dotAtIncludeCompletionHandler);
|
dotAtIncludeCompletionHandler);
|
||||||
return start;
|
return start;
|
||||||
@@ -918,12 +917,12 @@ int InternalCppCompletionAssistProcessor::startOfOperator(int positionInDocument
|
|||||||
int InternalCppCompletionAssistProcessor::findStartOfName(int pos) const
|
int InternalCppCompletionAssistProcessor::findStartOfName(int pos) const
|
||||||
{
|
{
|
||||||
if (pos == -1)
|
if (pos == -1)
|
||||||
pos = m_interface->position();
|
pos = interface()->position();
|
||||||
QChar chr;
|
QChar chr;
|
||||||
|
|
||||||
// Skip to the start of a name
|
// Skip to the start of a name
|
||||||
do {
|
do {
|
||||||
chr = m_interface->characterAt(--pos);
|
chr = interface()->characterAt(--pos);
|
||||||
} while (isValidIdentifierChar(chr));
|
} while (isValidIdentifierChar(chr));
|
||||||
|
|
||||||
return pos + 1;
|
return pos + 1;
|
||||||
@@ -931,7 +930,7 @@ int InternalCppCompletionAssistProcessor::findStartOfName(int pos) const
|
|||||||
|
|
||||||
int InternalCppCompletionAssistProcessor::startCompletionHelper()
|
int InternalCppCompletionAssistProcessor::startCompletionHelper()
|
||||||
{
|
{
|
||||||
if (m_interface->languageFeatures().objCEnabled) {
|
if (cppInterface()->languageFeatures().objCEnabled) {
|
||||||
if (tryObjCCompletion())
|
if (tryObjCCompletion())
|
||||||
return m_positionForProposal;
|
return m_positionForProposal;
|
||||||
}
|
}
|
||||||
@@ -943,7 +942,7 @@ int InternalCppCompletionAssistProcessor::startCompletionHelper()
|
|||||||
int endOfOperator = m_positionForProposal;
|
int endOfOperator = m_positionForProposal;
|
||||||
|
|
||||||
// Skip whitespace preceding this position
|
// Skip whitespace preceding this position
|
||||||
while (m_interface->characterAt(endOfOperator - 1).isSpace())
|
while (interface()->characterAt(endOfOperator - 1).isSpace())
|
||||||
--endOfOperator;
|
--endOfOperator;
|
||||||
|
|
||||||
int endOfExpression = startOfOperator(endOfOperator,
|
int endOfExpression = startOfOperator(endOfOperator,
|
||||||
@@ -968,15 +967,15 @@ int InternalCppCompletionAssistProcessor::startCompletionHelper()
|
|||||||
|| m_model->m_completionOperator == T_ANGLE_STRING_LITERAL
|
|| m_model->m_completionOperator == T_ANGLE_STRING_LITERAL
|
||||||
|| m_model->m_completionOperator == T_SLASH) {
|
|| m_model->m_completionOperator == T_SLASH) {
|
||||||
|
|
||||||
QTextCursor c(m_interface->textDocument());
|
QTextCursor c(interface()->textDocument());
|
||||||
c.setPosition(endOfExpression);
|
c.setPosition(endOfExpression);
|
||||||
if (completeInclude(c))
|
if (completeInclude(c))
|
||||||
m_positionForProposal = endOfExpression + 1;
|
m_positionForProposal = endOfExpression + 1;
|
||||||
return m_positionForProposal;
|
return m_positionForProposal;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionUnderCursor expressionUnderCursor(m_interface->languageFeatures());
|
ExpressionUnderCursor expressionUnderCursor(cppInterface()->languageFeatures());
|
||||||
QTextCursor tc(m_interface->textDocument());
|
QTextCursor tc(interface()->textDocument());
|
||||||
|
|
||||||
if (m_model->m_completionOperator == T_COMMA) {
|
if (m_model->m_completionOperator == T_COMMA) {
|
||||||
tc.setPosition(endOfExpression);
|
tc.setPosition(endOfExpression);
|
||||||
@@ -992,7 +991,7 @@ int InternalCppCompletionAssistProcessor::startCompletionHelper()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString expression;
|
QString expression;
|
||||||
int startOfExpression = m_interface->position();
|
int startOfExpression = interface()->position();
|
||||||
tc.setPosition(endOfExpression);
|
tc.setPosition(endOfExpression);
|
||||||
|
|
||||||
if (m_model->m_completionOperator) {
|
if (m_model->m_completionOperator) {
|
||||||
@@ -1004,7 +1003,7 @@ int InternalCppCompletionAssistProcessor::startCompletionHelper()
|
|||||||
// "connect(sender, &" or
|
// "connect(sender, &" or
|
||||||
// "connect(otherSender, &Foo::signal1, receiver, &"
|
// "connect(otherSender, &Foo::signal1, receiver, &"
|
||||||
const int beforeExpression = startOfExpression - 1;
|
const int beforeExpression = startOfExpression - 1;
|
||||||
if (canCompleteClassNameAt2ndOr4thConnectArgument(m_interface.data(),
|
if (canCompleteClassNameAt2ndOr4thConnectArgument(cppInterface(),
|
||||||
beforeExpression)) {
|
beforeExpression)) {
|
||||||
m_model->m_completionOperator = CompleteQt5SignalOrSlotClassNameTrigger;
|
m_model->m_completionOperator = CompleteQt5SignalOrSlotClassNameTrigger;
|
||||||
} else { // Ensure global completion
|
} else { // Ensure global completion
|
||||||
@@ -1017,45 +1016,45 @@ int InternalCppCompletionAssistProcessor::startCompletionHelper()
|
|||||||
// "connect(sender, &Foo::" or
|
// "connect(sender, &Foo::" or
|
||||||
// "connect(sender, &Bar::signal1, receiver, &Foo::"
|
// "connect(sender, &Bar::signal1, receiver, &Foo::"
|
||||||
const int beforeExpression = startOfExpression - 1;
|
const int beforeExpression = startOfExpression - 1;
|
||||||
if (canCompleteConnectSignalAt2ndArgument(m_interface.data(), beforeExpression))
|
if (canCompleteConnectSignalAt2ndArgument(cppInterface(), beforeExpression))
|
||||||
m_model->m_completionOperator = CompleteQt5SignalTrigger;
|
m_model->m_completionOperator = CompleteQt5SignalTrigger;
|
||||||
else if (canCompleteConnectSignalAt4thArgument(m_interface.data(), beforeExpression))
|
else if (canCompleteConnectSignalAt4thArgument(cppInterface(), beforeExpression))
|
||||||
m_model->m_completionOperator = CompleteQt5SlotTrigger;
|
m_model->m_completionOperator = CompleteQt5SlotTrigger;
|
||||||
} else if (m_model->m_completionOperator == T_LPAREN) {
|
} else if (m_model->m_completionOperator == T_LPAREN) {
|
||||||
if (expression.endsWith(QLatin1String("SIGNAL"))) {
|
if (expression.endsWith(QLatin1String("SIGNAL"))) {
|
||||||
m_model->m_completionOperator = T_SIGNAL;
|
m_model->m_completionOperator = T_SIGNAL;
|
||||||
} else if (expression.endsWith(QLatin1String("SLOT"))) {
|
} else if (expression.endsWith(QLatin1String("SLOT"))) {
|
||||||
m_model->m_completionOperator = T_SLOT;
|
m_model->m_completionOperator = T_SLOT;
|
||||||
} else if (m_interface->position() != endOfOperator) {
|
} else if (interface()->position() != endOfOperator) {
|
||||||
// We don't want a function completion when the cursor isn't at the opening brace
|
// We don't want a function completion when the cursor isn't at the opening brace
|
||||||
expression.clear();
|
expression.clear();
|
||||||
m_model->m_completionOperator = T_EOF_SYMBOL;
|
m_model->m_completionOperator = T_EOF_SYMBOL;
|
||||||
m_positionForProposal = startOfName;
|
m_positionForProposal = startOfName;
|
||||||
startOfExpression = m_interface->position();
|
startOfExpression = interface()->position();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (expression.isEmpty()) {
|
} else if (expression.isEmpty()) {
|
||||||
while (startOfExpression > 0 && m_interface->characterAt(startOfExpression).isSpace())
|
while (startOfExpression > 0 && interface()->characterAt(startOfExpression).isSpace())
|
||||||
--startOfExpression;
|
--startOfExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
int line = 0, column = 0;
|
int line = 0, column = 0;
|
||||||
Utils::Text::convertPosition(m_interface->textDocument(), startOfExpression, &line, &column);
|
Utils::Text::convertPosition(interface()->textDocument(), startOfExpression, &line, &column);
|
||||||
const QString fileName = m_interface->filePath().toString();
|
const QString fileName = interface()->filePath().toString();
|
||||||
return startCompletionInternal(fileName, line, column - 1, expression, endOfExpression);
|
return startCompletionInternal(fileName, line, column - 1, expression, endOfExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InternalCppCompletionAssistProcessor::tryObjCCompletion()
|
bool InternalCppCompletionAssistProcessor::tryObjCCompletion()
|
||||||
{
|
{
|
||||||
int end = m_interface->position();
|
int end = interface()->position();
|
||||||
while (m_interface->characterAt(end).isSpace())
|
while (interface()->characterAt(end).isSpace())
|
||||||
++end;
|
++end;
|
||||||
if (m_interface->characterAt(end) != QLatin1Char(']'))
|
if (interface()->characterAt(end) != QLatin1Char(']'))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QTextCursor tc(m_interface->textDocument());
|
QTextCursor tc(interface()->textDocument());
|
||||||
tc.setPosition(end);
|
tc.setPosition(end);
|
||||||
BackwardsScanner tokens(tc, m_interface->languageFeatures());
|
BackwardsScanner tokens(tc, cppInterface()->languageFeatures());
|
||||||
if (tokens[tokens.startToken() - 1].isNot(T_RBRACKET))
|
if (tokens[tokens.startToken() - 1].isNot(T_RBRACKET))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -1064,23 +1063,23 @@ bool InternalCppCompletionAssistProcessor::tryObjCCompletion()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
const int startPos = tokens[start].bytesBegin() + tokens.startPosition();
|
const int startPos = tokens[start].bytesBegin() + tokens.startPosition();
|
||||||
const QString expr = m_interface->textAt(startPos, m_interface->position() - startPos);
|
const QString expr = interface()->textAt(startPos, interface()->position() - startPos);
|
||||||
|
|
||||||
Document::Ptr thisDocument = m_interface->snapshot().document(m_interface->filePath());
|
Document::Ptr thisDocument = cppInterface()->snapshot().document(interface()->filePath());
|
||||||
if (!thisDocument)
|
if (!thisDocument)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_model->m_typeOfExpression->init(thisDocument, m_interface->snapshot());
|
m_model->m_typeOfExpression->init(thisDocument, cppInterface()->snapshot());
|
||||||
|
|
||||||
int line = 0, column = 0;
|
int line = 0, column = 0;
|
||||||
Utils::Text::convertPosition(m_interface->textDocument(), m_interface->position(), &line,
|
Utils::Text::convertPosition(interface()->textDocument(), interface()->position(), &line,
|
||||||
&column);
|
&column);
|
||||||
Scope *scope = thisDocument->scopeAt(line, column - 1);
|
Scope *scope = thisDocument->scopeAt(line, column - 1);
|
||||||
if (!scope)
|
if (!scope)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const QList<LookupItem> items = (*m_model->m_typeOfExpression)(expr.toUtf8(), scope);
|
const QList<LookupItem> items = (*m_model->m_typeOfExpression)(expr.toUtf8(), scope);
|
||||||
LookupContext lookupContext(thisDocument, m_interface->snapshot());
|
LookupContext lookupContext(thisDocument, cppInterface()->snapshot());
|
||||||
|
|
||||||
for (const LookupItem &item : items) {
|
for (const LookupItem &item : items) {
|
||||||
FullySpecifiedType ty = item.type().simplified();
|
FullySpecifiedType ty = item.type().simplified();
|
||||||
@@ -1102,7 +1101,7 @@ bool InternalCppCompletionAssistProcessor::tryObjCCompletion()
|
|||||||
if (m_completions.isEmpty())
|
if (m_completions.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_positionForProposal = m_interface->position();
|
m_positionForProposal = interface()->position();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1210,9 +1209,9 @@ bool InternalCppCompletionAssistProcessor::completeInclude(const QTextCursor &cu
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make completion for all relevant includes
|
// Make completion for all relevant includes
|
||||||
ProjectExplorer::HeaderPaths headerPaths = m_interface->headerPaths();
|
ProjectExplorer::HeaderPaths headerPaths = cppInterface()->headerPaths();
|
||||||
const auto currentFilePath = ProjectExplorer::HeaderPath::makeUser(
|
const auto currentFilePath = ProjectExplorer::HeaderPath::makeUser(
|
||||||
m_interface->filePath().toFileInfo().path());
|
interface()->filePath().toFileInfo().path());
|
||||||
if (!headerPaths.contains(currentFilePath))
|
if (!headerPaths.contains(currentFilePath))
|
||||||
headerPaths.append(currentFilePath);
|
headerPaths.append(currentFilePath);
|
||||||
|
|
||||||
@@ -1261,10 +1260,10 @@ void InternalCppCompletionAssistProcessor::completePreprocessor()
|
|||||||
|
|
||||||
bool InternalCppCompletionAssistProcessor::objcKeywordsWanted() const
|
bool InternalCppCompletionAssistProcessor::objcKeywordsWanted() const
|
||||||
{
|
{
|
||||||
if (!m_interface->languageFeatures().objCEnabled)
|
if (!cppInterface()->languageFeatures().objCEnabled)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const Utils::MimeType mt = Utils::mimeTypeForFile(m_interface->filePath());
|
const Utils::MimeType mt = Utils::mimeTypeForFile(interface()->filePath());
|
||||||
return mt.matchesName(QLatin1String(CppEditor::Constants::OBJECTIVE_C_SOURCE_MIMETYPE))
|
return mt.matchesName(QLatin1String(CppEditor::Constants::OBJECTIVE_C_SOURCE_MIMETYPE))
|
||||||
|| mt.matchesName(QLatin1String(CppEditor::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE));
|
|| mt.matchesName(QLatin1String(CppEditor::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE));
|
||||||
}
|
}
|
||||||
@@ -1277,11 +1276,11 @@ int InternalCppCompletionAssistProcessor::startCompletionInternal(const QString
|
|||||||
{
|
{
|
||||||
QString expression = expr.trimmed();
|
QString expression = expr.trimmed();
|
||||||
|
|
||||||
Document::Ptr thisDocument = m_interface->snapshot().document(fileName);
|
Document::Ptr thisDocument = cppInterface()->snapshot().document(fileName);
|
||||||
if (!thisDocument)
|
if (!thisDocument)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
m_model->m_typeOfExpression->init(thisDocument, m_interface->snapshot());
|
m_model->m_typeOfExpression->init(thisDocument, cppInterface()->snapshot());
|
||||||
|
|
||||||
Scope *scope = thisDocument->scopeAt(line, positionInBlock);
|
Scope *scope = thisDocument->scopeAt(line, positionInBlock);
|
||||||
QTC_ASSERT(scope, return -1);
|
QTC_ASSERT(scope, return -1);
|
||||||
@@ -1315,14 +1314,14 @@ int InternalCppCompletionAssistProcessor::startCompletionInternal(const QString
|
|||||||
} else if (m_model->m_completionOperator == T_LPAREN) {
|
} else if (m_model->m_completionOperator == T_LPAREN) {
|
||||||
// Find the expression that precedes the current name
|
// Find the expression that precedes the current name
|
||||||
int index = endOfExpression;
|
int index = endOfExpression;
|
||||||
while (m_interface->characterAt(index - 1).isSpace())
|
while (interface()->characterAt(index - 1).isSpace())
|
||||||
--index;
|
--index;
|
||||||
index = findStartOfName(index);
|
index = findStartOfName(index);
|
||||||
|
|
||||||
QTextCursor tc(m_interface->textDocument());
|
QTextCursor tc(interface()->textDocument());
|
||||||
tc.setPosition(index);
|
tc.setPosition(index);
|
||||||
|
|
||||||
ExpressionUnderCursor expressionUnderCursor(m_interface->languageFeatures());
|
ExpressionUnderCursor expressionUnderCursor(cppInterface()->languageFeatures());
|
||||||
const QString baseExpression = expressionUnderCursor(tc);
|
const QString baseExpression = expressionUnderCursor(tc);
|
||||||
|
|
||||||
// Resolve the type of this expression
|
// Resolve the type of this expression
|
||||||
@@ -1506,7 +1505,7 @@ bool InternalCppCompletionAssistProcessor::completeMember(const QList<LookupItem
|
|||||||
ResolveExpression resolveExpression(context);
|
ResolveExpression resolveExpression(context);
|
||||||
|
|
||||||
bool *replaceDotForArrow = nullptr;
|
bool *replaceDotForArrow = nullptr;
|
||||||
if (!m_interface->languageFeatures().objCEnabled)
|
if (!cppInterface()->languageFeatures().objCEnabled)
|
||||||
replaceDotForArrow = &m_model->m_replaceDotForArrow;
|
replaceDotForArrow = &m_model->m_replaceDotForArrow;
|
||||||
|
|
||||||
if (ClassOrNamespace *binding =
|
if (ClassOrNamespace *binding =
|
||||||
@@ -1836,7 +1835,7 @@ void InternalCppCompletionAssistProcessor::addKeywords()
|
|||||||
addKeywordCompletionItem(QLatin1String(Token::name(i)));
|
addKeywordCompletionItem(QLatin1String(Token::name(i)));
|
||||||
|
|
||||||
// "Identifiers with special meaning"
|
// "Identifiers with special meaning"
|
||||||
if (m_interface->languageFeatures().cxx11Enabled) {
|
if (cppInterface()->languageFeatures().cxx11Enabled) {
|
||||||
addKeywordCompletionItem(QLatin1String("override"));
|
addKeywordCompletionItem(QLatin1String("override"));
|
||||||
addKeywordCompletionItem(QLatin1String("final"));
|
addKeywordCompletionItem(QLatin1String("final"));
|
||||||
}
|
}
|
||||||
@@ -1879,6 +1878,11 @@ void InternalCppCompletionAssistProcessor::addMacros_helper(const Snapshot &snap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CppCompletionAssistInterface *InternalCppCompletionAssistProcessor::cppInterface() const
|
||||||
|
{
|
||||||
|
return static_cast<const CppCompletionAssistInterface *>(interface());
|
||||||
|
}
|
||||||
|
|
||||||
bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const QList<LookupItem> &results,
|
bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const QList<LookupItem> &results,
|
||||||
int endOfExpression,
|
int endOfExpression,
|
||||||
bool toolTipOnly)
|
bool toolTipOnly)
|
||||||
@@ -1983,7 +1987,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
|
|||||||
|
|
||||||
// get current line and column
|
// get current line and column
|
||||||
int lineSigned = 0, columnSigned = 0;
|
int lineSigned = 0, columnSigned = 0;
|
||||||
Utils::Text::convertPosition(m_interface->textDocument(), m_interface->position(),
|
Utils::Text::convertPosition(interface()->textDocument(), interface()->position(),
|
||||||
&lineSigned, &columnSigned);
|
&lineSigned, &columnSigned);
|
||||||
unsigned line = lineSigned, column = columnSigned - 1;
|
unsigned line = lineSigned, column = columnSigned - 1;
|
||||||
|
|
||||||
@@ -1997,9 +2001,9 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
|
|||||||
// declaration, we should be certain that it isn't.
|
// declaration, we should be certain that it isn't.
|
||||||
bool autocompleteSignature = false;
|
bool autocompleteSignature = false;
|
||||||
|
|
||||||
QTextCursor tc(m_interface->textDocument());
|
QTextCursor tc(interface()->textDocument());
|
||||||
tc.setPosition(endOfExpression);
|
tc.setPosition(endOfExpression);
|
||||||
BackwardsScanner bs(tc, m_interface->languageFeatures());
|
BackwardsScanner bs(tc, cppInterface()->languageFeatures());
|
||||||
const int startToken = bs.startToken();
|
const int startToken = bs.startToken();
|
||||||
int lineStartToken = bs.startOfLine(startToken);
|
int lineStartToken = bs.startOfLine(startToken);
|
||||||
// make sure the required tokens are actually available
|
// make sure the required tokens are actually available
|
||||||
|
@@ -61,7 +61,7 @@ class InternalCompletionAssistProvider : public CppCompletionAssistProvider
|
|||||||
public:
|
public:
|
||||||
TextEditor::IAssistProcessor *createProcessor(const TextEditor::AssistInterface *) const override;
|
TextEditor::IAssistProcessor *createProcessor(const TextEditor::AssistInterface *) const override;
|
||||||
|
|
||||||
TextEditor::AssistInterface *createAssistInterface(
|
std::unique_ptr<TextEditor::AssistInterface> createAssistInterface(
|
||||||
const Utils::FilePath &filePath,
|
const Utils::FilePath &filePath,
|
||||||
const TextEditor::TextEditorWidget *textEditorWidget,
|
const TextEditor::TextEditorWidget *textEditorWidget,
|
||||||
const CPlusPlus::LanguageFeatures &languageFeatures,
|
const CPlusPlus::LanguageFeatures &languageFeatures,
|
||||||
@@ -74,7 +74,7 @@ public:
|
|||||||
InternalCppCompletionAssistProcessor();
|
InternalCppCompletionAssistProcessor();
|
||||||
~InternalCppCompletionAssistProcessor() override;
|
~InternalCppCompletionAssistProcessor() override;
|
||||||
|
|
||||||
TextEditor::IAssistProposal *performAsync(TextEditor::AssistInterface *interface) override;
|
TextEditor::IAssistProposal *performAsync() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TextEditor::IAssistProposal *createContentProposal();
|
TextEditor::IAssistProposal *createContentProposal();
|
||||||
@@ -135,6 +135,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
QScopedPointer<const CppCompletionAssistInterface> m_interface;
|
QScopedPointer<const CppCompletionAssistInterface> m_interface;
|
||||||
|
const CppCompletionAssistInterface *cppInterface() const;
|
||||||
CppAssistProposalModelPtr m_model;
|
CppAssistProposalModelPtr m_model;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -33,7 +33,7 @@ public:
|
|||||||
bool isActivationCharSequence(const QString &sequence) const override;
|
bool isActivationCharSequence(const QString &sequence) const override;
|
||||||
bool isContinuationChar(const QChar &c) const override;
|
bool isContinuationChar(const QChar &c) const override;
|
||||||
|
|
||||||
virtual TextEditor::AssistInterface *createAssistInterface(
|
virtual std::unique_ptr<TextEditor::AssistInterface> createAssistInterface(
|
||||||
const Utils::FilePath &filePath,
|
const Utils::FilePath &filePath,
|
||||||
const TextEditor::TextEditorWidget *textEditorWidget,
|
const TextEditor::TextEditorWidget *textEditorWidget,
|
||||||
const CPlusPlus::LanguageFeatures &languageFeatures,
|
const CPlusPlus::LanguageFeatures &languageFeatures,
|
||||||
|
@@ -981,7 +981,7 @@ void CppEditorWidget::processKeyNormally(QKeyEvent *e)
|
|||||||
TextEditorWidget::keyPressEvent(e);
|
TextEditorWidget::keyPressEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addRefactoringActions(QMenu *menu, AssistInterface *iface)
|
static void addRefactoringActions(QMenu *menu, std::unique_ptr<AssistInterface> iface)
|
||||||
{
|
{
|
||||||
if (!iface || !menu)
|
if (!iface || !menu)
|
||||||
return;
|
return;
|
||||||
@@ -990,8 +990,8 @@ static void addRefactoringActions(QMenu *menu, AssistInterface *iface)
|
|||||||
using Proposal = QScopedPointer<IAssistProposal>;
|
using Proposal = QScopedPointer<IAssistProposal>;
|
||||||
|
|
||||||
const Processor processor(
|
const Processor processor(
|
||||||
CppEditorPlugin::instance()->quickFixProvider()->createProcessor(iface));
|
CppEditorPlugin::instance()->quickFixProvider()->createProcessor(iface.get()));
|
||||||
const Proposal proposal(processor->perform(iface)); // OK, perform() takes ownership of iface.
|
const Proposal proposal(processor->start(std::move(iface)));
|
||||||
if (proposal) {
|
if (proposal) {
|
||||||
auto model = proposal->model().staticCast<GenericProposalModel>();
|
auto model = proposal->model().staticCast<GenericProposalModel>();
|
||||||
for (int index = 0; index < model->size(); ++index) {
|
for (int index = 0; index < model->size(); ++index) {
|
||||||
@@ -1174,7 +1174,8 @@ bool CppEditorWidget::isOldStyleSignalOrSlot() const
|
|||||||
== CppEditor::SignalSlotType::OldStyleSignal;
|
== CppEditor::SignalSlotType::OldStyleSignal;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssistInterface *CppEditorWidget::createAssistInterface(AssistKind kind, AssistReason reason) const
|
std::unique_ptr<AssistInterface> CppEditorWidget::createAssistInterface(AssistKind kind,
|
||||||
|
AssistReason reason) const
|
||||||
{
|
{
|
||||||
if (kind == Completion || kind == FunctionHint) {
|
if (kind == Completion || kind == FunctionHint) {
|
||||||
CppCompletionAssistProvider * const cap = kind == Completion
|
CppCompletionAssistProvider * const cap = kind == Completion
|
||||||
@@ -1190,10 +1191,7 @@ AssistInterface *CppEditorWidget::createAssistInterface(AssistKind kind, AssistR
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (cap)
|
if (cap)
|
||||||
return cap->createAssistInterface(textDocument()->filePath(),
|
return cap->createAssistInterface(textDocument()->filePath(), this, getFeatures(), reason);
|
||||||
this,
|
|
||||||
getFeatures(),
|
|
||||||
reason);
|
|
||||||
else {
|
else {
|
||||||
if (isOldStyleSignalOrSlot())
|
if (isOldStyleSignalOrSlot())
|
||||||
return CppModelManager::instance()
|
return CppModelManager::instance()
|
||||||
@@ -1203,7 +1201,7 @@ AssistInterface *CppEditorWidget::createAssistInterface(AssistKind kind, AssistR
|
|||||||
}
|
}
|
||||||
} else if (kind == QuickFix) {
|
} else if (kind == QuickFix) {
|
||||||
if (isSemanticInfoValid())
|
if (isSemanticInfoValid())
|
||||||
return new CppQuickFixInterface(const_cast<CppEditorWidget *>(this), reason);
|
return std::make_unique<CppQuickFixInterface>(const_cast<CppEditorWidget *>(this), reason);
|
||||||
} else {
|
} else {
|
||||||
return TextEditorWidget::createAssistInterface(kind, reason);
|
return TextEditorWidget::createAssistInterface(kind, reason);
|
||||||
}
|
}
|
||||||
|
@@ -43,7 +43,7 @@ public:
|
|||||||
QSharedPointer<Internal::FunctionDeclDefLink> declDefLink() const;
|
QSharedPointer<Internal::FunctionDeclDefLink> declDefLink() const;
|
||||||
void applyDeclDefLinkChanges(bool jumpToMatch);
|
void applyDeclDefLinkChanges(bool jumpToMatch);
|
||||||
|
|
||||||
TextEditor::AssistInterface *createAssistInterface(
|
std::unique_ptr<TextEditor::AssistInterface> createAssistInterface(
|
||||||
TextEditor::AssistKind kind,
|
TextEditor::AssistKind kind,
|
||||||
TextEditor::AssistReason reason) const override;
|
TextEditor::AssistReason reason) const override;
|
||||||
|
|
||||||
|
@@ -29,10 +29,9 @@ namespace Internal {
|
|||||||
// -------------------------
|
// -------------------------
|
||||||
class CppQuickFixAssistProcessor : public IAssistProcessor
|
class CppQuickFixAssistProcessor : public IAssistProcessor
|
||||||
{
|
{
|
||||||
IAssistProposal *perform(AssistInterface *interface) override
|
IAssistProposal *perform() override
|
||||||
{
|
{
|
||||||
QSharedPointer<const AssistInterface> dummy(interface); // FIXME: Surely this cannot be our way of doing memory management???
|
return GenericProposal::createProposal(interface(), quickFixOperations(interface()));
|
||||||
return GenericProposal::createProposal(interface, quickFixOperations(interface));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -87,7 +87,7 @@ public:
|
|||||||
: m_params(params)
|
: m_params(params)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
IAssistProposal *immediateProposal(AssistInterface *) override
|
IAssistProposal *immediateProposal() override
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_params.function, return nullptr);
|
QTC_ASSERT(m_params.function, return nullptr);
|
||||||
|
|
||||||
@@ -102,10 +102,8 @@ public:
|
|||||||
return new VirtualFunctionProposal(m_params.cursorPosition, items, m_params.openInNextSplit);
|
return new VirtualFunctionProposal(m_params.cursorPosition, items, m_params.openInNextSplit);
|
||||||
}
|
}
|
||||||
|
|
||||||
IAssistProposal *performAsync(AssistInterface *assistInterface) override
|
IAssistProposal *performAsync() override
|
||||||
{
|
{
|
||||||
delete assistInterface;
|
|
||||||
|
|
||||||
QTC_ASSERT(m_params.function, return nullptr);
|
QTC_ASSERT(m_params.function, return nullptr);
|
||||||
QTC_ASSERT(m_params.staticClass, return nullptr);
|
QTC_ASSERT(m_params.staticClass, return nullptr);
|
||||||
QTC_ASSERT(!m_params.snapshot.isEmpty(), return nullptr);
|
QTC_ASSERT(!m_params.snapshot.isEmpty(), return nullptr);
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
#include <projectexplorer/kitmanager.h>
|
#include <projectexplorer/kitmanager.h>
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
|
|
||||||
|
#include <texteditor/codeassist/assistinterface.h>
|
||||||
#include <texteditor/codeassist/asyncprocessor.h>
|
#include <texteditor/codeassist/asyncprocessor.h>
|
||||||
#include <texteditor/codeassist/genericproposalmodel.h>
|
#include <texteditor/codeassist/genericproposalmodel.h>
|
||||||
#include <texteditor/codeassist/iassistprocessor.h>
|
#include <texteditor/codeassist/iassistprocessor.h>
|
||||||
@@ -119,14 +120,13 @@ public:
|
|||||||
{
|
{
|
||||||
VirtualFunctionAssistProvider::configure(params);
|
VirtualFunctionAssistProvider::configure(params);
|
||||||
|
|
||||||
AssistInterface *assistInterface
|
std::unique_ptr<AssistInterface> assistInterface
|
||||||
= m_editorWidget->createAssistInterface(FollowSymbol, ExplicitlyInvoked);
|
= m_editorWidget->createAssistInterface(FollowSymbol, ExplicitlyInvoked);
|
||||||
const QScopedPointer<AsyncProcessor> processor(
|
const QScopedPointer<AsyncProcessor> processor(
|
||||||
dynamic_cast<AsyncProcessor *>(createProcessor(assistInterface)));
|
dynamic_cast<AsyncProcessor *>(createProcessor(assistInterface.get())));
|
||||||
const QScopedPointer<IAssistProposal> immediateProposal(
|
processor->setupAssistInterface(std::move(assistInterface));
|
||||||
processor->immediateProposal(assistInterface));
|
const QScopedPointer<IAssistProposal> immediateProposal(processor->immediateProposal());
|
||||||
const QScopedPointer<IAssistProposal> finalProposal(
|
const QScopedPointer<IAssistProposal> finalProposal(processor->performAsync());
|
||||||
processor->performAsync(assistInterface));
|
|
||||||
|
|
||||||
VirtualFunctionAssistProvider::clearParams();
|
VirtualFunctionAssistProvider::clearParams();
|
||||||
|
|
||||||
|
@@ -1045,14 +1045,14 @@ public:
|
|||||||
: m_provider(static_cast<const FakeVimCompletionAssistProvider *>(provider))
|
: m_provider(static_cast<const FakeVimCompletionAssistProvider *>(provider))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
IAssistProposal *performAsync(AssistInterface *interface) override
|
IAssistProposal *performAsync() override
|
||||||
{
|
{
|
||||||
const QString &needle = m_provider->needle();
|
const QString &needle = m_provider->needle();
|
||||||
|
|
||||||
const int basePosition = interface->position() - needle.size();
|
const int basePosition = interface()->position() - needle.size();
|
||||||
|
|
||||||
QTextCursor tc(interface->textDocument());
|
QTextCursor tc(interface()->textDocument());
|
||||||
tc.setPosition(interface->position());
|
tc.setPosition(interface()->position());
|
||||||
tc.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
|
tc.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
|
||||||
|
|
||||||
QList<AssistProposalItemInterface *> items;
|
QList<AssistProposalItemInterface *> items;
|
||||||
@@ -1078,7 +1078,6 @@ public:
|
|||||||
}
|
}
|
||||||
//qDebug() << "COMPLETIONS" << completions->size();
|
//qDebug() << "COMPLETIONS" << completions->size();
|
||||||
|
|
||||||
delete interface;
|
|
||||||
return new GenericProposal(basePosition,
|
return new GenericProposal(basePosition,
|
||||||
GenericProposalModelPtr(new FakeVimAssistProposalModel(items)));
|
GenericProposalModelPtr(new FakeVimAssistProposalModel(items)));
|
||||||
}
|
}
|
||||||
|
@@ -290,17 +290,17 @@ static AssistProposalItem *createCompletionItem(const QString &text, const QIcon
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
IAssistProposal *GlslCompletionAssistProcessor::performAsync(AssistInterface *interface)
|
IAssistProposal *GlslCompletionAssistProcessor::performAsync()
|
||||||
{
|
{
|
||||||
m_interface.reset(static_cast<const GlslCompletionAssistInterface *>(interface));
|
auto interface = static_cast<const GlslCompletionAssistInterface *>(this->interface());
|
||||||
|
|
||||||
if (interface->reason() == IdleEditor && !acceptsIdleEditor())
|
if (interface->reason() == IdleEditor && !acceptsIdleEditor())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
int pos = m_interface->position() - 1;
|
int pos = interface->position() - 1;
|
||||||
QChar ch = m_interface->characterAt(pos);
|
QChar ch = interface->characterAt(pos);
|
||||||
while (ch.isLetterOrNumber() || ch == QLatin1Char('_'))
|
while (ch.isLetterOrNumber() || ch == QLatin1Char('_'))
|
||||||
ch = m_interface->characterAt(--pos);
|
ch = interface->characterAt(--pos);
|
||||||
|
|
||||||
CPlusPlus::ExpressionUnderCursor expressionUnderCursor(
|
CPlusPlus::ExpressionUnderCursor expressionUnderCursor(
|
||||||
CPlusPlus::LanguageFeatures::defaultFeatures());
|
CPlusPlus::LanguageFeatures::defaultFeatures());
|
||||||
@@ -310,16 +310,16 @@ IAssistProposal *GlslCompletionAssistProcessor::performAsync(AssistInterface *in
|
|||||||
QStringList specialMembers;
|
QStringList specialMembers;
|
||||||
QList<AssistProposalItemInterface *> m_completions;
|
QList<AssistProposalItemInterface *> m_completions;
|
||||||
|
|
||||||
bool functionCall = (ch == QLatin1Char('(') && pos == m_interface->position() - 1);
|
bool functionCall = (ch == QLatin1Char('(') && pos == interface->position() - 1);
|
||||||
|
|
||||||
if (ch == QLatin1Char(',')) {
|
if (ch == QLatin1Char(',')) {
|
||||||
QTextCursor tc(m_interface->textDocument());
|
QTextCursor tc(interface->textDocument());
|
||||||
tc.setPosition(pos);
|
tc.setPosition(pos);
|
||||||
const int start = expressionUnderCursor.startOfFunctionCall(tc);
|
const int start = expressionUnderCursor.startOfFunctionCall(tc);
|
||||||
if (start == -1)
|
if (start == -1)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (m_interface->characterAt(start) == QLatin1Char('(')) {
|
if (interface->characterAt(start) == QLatin1Char('(')) {
|
||||||
pos = start;
|
pos = start;
|
||||||
ch = QLatin1Char('(');
|
ch = QLatin1Char('(');
|
||||||
functionCall = true;
|
functionCall = true;
|
||||||
@@ -328,7 +328,7 @@ IAssistProposal *GlslCompletionAssistProcessor::performAsync(AssistInterface *in
|
|||||||
|
|
||||||
if (ch == QLatin1Char('.') || functionCall) {
|
if (ch == QLatin1Char('.') || functionCall) {
|
||||||
const bool memberCompletion = ! functionCall;
|
const bool memberCompletion = ! functionCall;
|
||||||
QTextCursor tc(m_interface->textDocument());
|
QTextCursor tc(interface->textDocument());
|
||||||
tc.setPosition(pos);
|
tc.setPosition(pos);
|
||||||
|
|
||||||
// get the expression under cursor
|
// get the expression under cursor
|
||||||
@@ -337,7 +337,7 @@ IAssistProposal *GlslCompletionAssistProcessor::performAsync(AssistInterface *in
|
|||||||
|
|
||||||
// parse the expression
|
// parse the expression
|
||||||
GLSL::Engine engine;
|
GLSL::Engine engine;
|
||||||
GLSL::Parser parser(&engine, code, code.size(), languageVariant(m_interface->mimeType()));
|
GLSL::Parser parser(&engine, code, code.size(), languageVariant(interface->mimeType()));
|
||||||
GLSL::ExpressionAST *expr = parser.parseExpression();
|
GLSL::ExpressionAST *expr = parser.parseExpression();
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@@ -347,7 +347,7 @@ IAssistProposal *GlslCompletionAssistProcessor::performAsync(AssistInterface *in
|
|||||||
dump(expr);
|
dump(expr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (Document::Ptr doc = m_interface->glslDocument()) {
|
if (Document::Ptr doc = interface->glslDocument()) {
|
||||||
GLSL::Scope *currentScope = doc->scopeAt(pos);
|
GLSL::Scope *currentScope = doc->scopeAt(pos);
|
||||||
|
|
||||||
GLSL::Semantic sem;
|
GLSL::Semantic sem;
|
||||||
@@ -396,7 +396,7 @@ IAssistProposal *GlslCompletionAssistProcessor::performAsync(AssistInterface *in
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// it's a global completion
|
// it's a global completion
|
||||||
if (Document::Ptr doc = m_interface->glslDocument()) {
|
if (Document::Ptr doc = interface->glslDocument()) {
|
||||||
GLSL::Scope *currentScope = doc->scopeAt(pos);
|
GLSL::Scope *currentScope = doc->scopeAt(pos);
|
||||||
bool isGlobal = !currentScope || !currentScope->scope();
|
bool isGlobal = !currentScope || !currentScope->scope();
|
||||||
|
|
||||||
@@ -435,12 +435,12 @@ IAssistProposal *GlslCompletionAssistProcessor::performAsync(AssistInterface *in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (m_keywordVariant != languageVariant(m_interface->mimeType())) {
|
// if (m_keywordVariant != languageVariant(interface->mimeType())) {
|
||||||
QStringList keywords = GLSL::Lexer::keywords(languageVariant(m_interface->mimeType()));
|
QStringList keywords = GLSL::Lexer::keywords(languageVariant(interface->mimeType()));
|
||||||
// m_keywordCompletions.clear();
|
// m_keywordCompletions.clear();
|
||||||
for (int index = 0; index < keywords.size(); ++index)
|
for (int index = 0; index < keywords.size(); ++index)
|
||||||
m_completions << createCompletionItem(keywords.at(index), glslIcon(IconTypeKeyword));
|
m_completions << createCompletionItem(keywords.at(index), glslIcon(IconTypeKeyword));
|
||||||
// m_keywordVariant = languageVariant(m_interface->mimeType());
|
// m_keywordVariant = languageVariant(interface->mimeType());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// m_completions += m_keywordCompletions;
|
// m_completions += m_keywordCompletions;
|
||||||
@@ -491,22 +491,22 @@ IAssistProposal *GlslCompletionAssistProcessor::createHintProposal(
|
|||||||
|
|
||||||
bool GlslCompletionAssistProcessor::acceptsIdleEditor() const
|
bool GlslCompletionAssistProcessor::acceptsIdleEditor() const
|
||||||
{
|
{
|
||||||
const int cursorPosition = m_interface->position();
|
const int cursorPosition = interface()->position();
|
||||||
const QChar ch = m_interface->characterAt(cursorPosition - 1);
|
const QChar ch = interface()->characterAt(cursorPosition - 1);
|
||||||
|
|
||||||
const QChar characterUnderCursor = m_interface->characterAt(cursorPosition);
|
const QChar characterUnderCursor = interface()->characterAt(cursorPosition);
|
||||||
|
|
||||||
if (isIdentifierChar(ch) && (characterUnderCursor.isSpace() ||
|
if (isIdentifierChar(ch) && (characterUnderCursor.isSpace() ||
|
||||||
characterUnderCursor.isNull() ||
|
characterUnderCursor.isNull() ||
|
||||||
isDelimiter(characterUnderCursor))) {
|
isDelimiter(characterUnderCursor))) {
|
||||||
int pos = m_interface->position() - 1;
|
int pos = interface()->position() - 1;
|
||||||
for (; pos != -1; --pos) {
|
for (; pos != -1; --pos) {
|
||||||
if (! isIdentifierChar(m_interface->characterAt(pos)))
|
if (! isIdentifierChar(interface()->characterAt(pos)))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++pos;
|
++pos;
|
||||||
|
|
||||||
const QString word = m_interface->textAt(pos, cursorPosition - pos);
|
const QString word = interface()->textAt(pos, cursorPosition - pos);
|
||||||
if (word.length() >= TextEditorSettings::completionSettings().m_characterThreshold
|
if (word.length() >= TextEditorSettings::completionSettings().m_characterThreshold
|
||||||
&& checkStartOfIdentifier(word)) {
|
&& checkStartOfIdentifier(word)) {
|
||||||
for (auto character : word) {
|
for (auto character : word) {
|
||||||
|
@@ -72,14 +72,13 @@ class GlslCompletionAssistProcessor : public TextEditor::AsyncProcessor
|
|||||||
public:
|
public:
|
||||||
~GlslCompletionAssistProcessor() override;
|
~GlslCompletionAssistProcessor() override;
|
||||||
|
|
||||||
TextEditor::IAssistProposal *performAsync(TextEditor::AssistInterface *interface) override;
|
TextEditor::IAssistProposal *performAsync() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TextEditor::IAssistProposal *createHintProposal(const QVector<GLSL::Function *> &symbols);
|
TextEditor::IAssistProposal *createHintProposal(const QVector<GLSL::Function *> &symbols);
|
||||||
bool acceptsIdleEditor() const;
|
bool acceptsIdleEditor() const;
|
||||||
|
|
||||||
int m_startPosition = 0;
|
int m_startPosition = 0;
|
||||||
QScopedPointer<const GlslCompletionAssistInterface> m_interface;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GlslCompletionAssistInterface : public TextEditor::AssistInterface
|
class GlslCompletionAssistInterface : public TextEditor::AssistInterface
|
||||||
|
@@ -143,7 +143,8 @@ public:
|
|||||||
|
|
||||||
QSet<QString> identifiers() const;
|
QSet<QString> identifiers() const;
|
||||||
|
|
||||||
AssistInterface *createAssistInterface(AssistKind assistKind, AssistReason reason) const override;
|
std::unique_ptr<AssistInterface> createAssistInterface(AssistKind assistKind,
|
||||||
|
AssistReason reason) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateDocumentNow();
|
void updateDocumentNow();
|
||||||
@@ -343,16 +344,17 @@ int languageVariant(const QString &type)
|
|||||||
return variant;
|
return variant;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssistInterface *GlslEditorWidget::createAssistInterface(
|
std::unique_ptr<AssistInterface> GlslEditorWidget::createAssistInterface(
|
||||||
AssistKind kind, AssistReason reason) const
|
AssistKind kind, AssistReason reason) const
|
||||||
{
|
{
|
||||||
if (kind == Completion)
|
if (kind != Completion)
|
||||||
return new GlslCompletionAssistInterface(textCursor(),
|
return TextEditorWidget::createAssistInterface(kind, reason);
|
||||||
|
|
||||||
|
return std::make_unique<GlslCompletionAssistInterface>(textCursor(),
|
||||||
textDocument()->filePath(),
|
textDocument()->filePath(),
|
||||||
reason,
|
reason,
|
||||||
textDocument()->mimeType(),
|
textDocument()->mimeType(),
|
||||||
m_glslDocument);
|
m_glslDocument);
|
||||||
return TextEditorWidget::createAssistInterface(kind, reason);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -293,8 +293,7 @@ LanguageClientCompletionAssistProcessor::~LanguageClientCompletionAssistProcesso
|
|||||||
|
|
||||||
QTextDocument *LanguageClientCompletionAssistProcessor::document() const
|
QTextDocument *LanguageClientCompletionAssistProcessor::document() const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_assistInterface, return nullptr);
|
return interface()->textDocument();
|
||||||
return m_assistInterface->textDocument();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<AssistProposalItemInterface *> LanguageClientCompletionAssistProcessor::generateCompletionItems(
|
QList<AssistProposalItemInterface *> LanguageClientCompletionAssistProcessor::generateCompletionItems(
|
||||||
@@ -314,26 +313,25 @@ static QString assistReasonString(AssistReason reason)
|
|||||||
return QString("unknown reason");
|
return QString("unknown reason");
|
||||||
}
|
}
|
||||||
|
|
||||||
IAssistProposal *LanguageClientCompletionAssistProcessor::perform(AssistInterface *interface)
|
IAssistProposal *LanguageClientCompletionAssistProcessor::perform()
|
||||||
{
|
{
|
||||||
m_assistInterface.reset(interface);
|
|
||||||
QTC_ASSERT(m_client, return nullptr);
|
QTC_ASSERT(m_client, return nullptr);
|
||||||
m_pos = interface->position();
|
m_pos = interface()->position();
|
||||||
m_basePos = m_pos;
|
m_basePos = m_pos;
|
||||||
auto isIdentifierChar = [](const QChar &c) { return c.isLetterOrNumber() || c == '_'; };
|
auto isIdentifierChar = [](const QChar &c) { return c.isLetterOrNumber() || c == '_'; };
|
||||||
while (m_basePos > 0 && isIdentifierChar(interface->characterAt(m_basePos - 1)))
|
while (m_basePos > 0 && isIdentifierChar(interface()->characterAt(m_basePos - 1)))
|
||||||
--m_basePos;
|
--m_basePos;
|
||||||
if (interface->reason() == IdleEditor) {
|
if (interface()->reason() == IdleEditor) {
|
||||||
// Trigger an automatic completion request only when we are on a word with at least n "identifier" characters
|
// Trigger an automatic completion request only when we are on a word with at least n "identifier" characters
|
||||||
if (m_pos - m_basePos < TextEditorSettings::completionSettings().m_characterThreshold)
|
if (m_pos - m_basePos < TextEditorSettings::completionSettings().m_characterThreshold)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (m_client->documentUpdatePostponed(interface->filePath())) {
|
if (m_client->documentUpdatePostponed(interface()->filePath())) {
|
||||||
m_postponedUpdateConnection
|
m_postponedUpdateConnection
|
||||||
= QObject::connect(m_client,
|
= QObject::connect(m_client,
|
||||||
&Client::documentUpdated,
|
&Client::documentUpdated,
|
||||||
[this, interface](TextEditor::TextDocument *document) {
|
[this](TextEditor::TextDocument *document) {
|
||||||
if (document->filePath() == interface->filePath())
|
if (document->filePath() == interface()->filePath())
|
||||||
perform(interface);
|
perform();
|
||||||
});
|
});
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -341,9 +339,9 @@ IAssistProposal *LanguageClientCompletionAssistProcessor::perform(AssistInterfac
|
|||||||
if (m_postponedUpdateConnection)
|
if (m_postponedUpdateConnection)
|
||||||
QObject::disconnect(m_postponedUpdateConnection);
|
QObject::disconnect(m_postponedUpdateConnection);
|
||||||
CompletionParams::CompletionContext context;
|
CompletionParams::CompletionContext context;
|
||||||
if (interface->reason() == ActivationCharacter) {
|
if (interface()->reason() == ActivationCharacter) {
|
||||||
context.setTriggerKind(CompletionParams::TriggerCharacter);
|
context.setTriggerKind(CompletionParams::TriggerCharacter);
|
||||||
QChar triggerCharacter = interface->characterAt(interface->position() - 1);
|
QChar triggerCharacter = interface()->characterAt(interface()->position() - 1);
|
||||||
if (!triggerCharacter.isNull())
|
if (!triggerCharacter.isNull())
|
||||||
context.setTriggerCharacter(triggerCharacter);
|
context.setTriggerCharacter(triggerCharacter);
|
||||||
} else {
|
} else {
|
||||||
@@ -352,13 +350,14 @@ IAssistProposal *LanguageClientCompletionAssistProcessor::perform(AssistInterfac
|
|||||||
CompletionParams params;
|
CompletionParams params;
|
||||||
int line;
|
int line;
|
||||||
int column;
|
int column;
|
||||||
if (!Utils::Text::convertPosition(interface->textDocument(), m_pos, &line, &column))
|
if (!Utils::Text::convertPosition(interface()->textDocument(), m_pos, &line, &column))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
--line; // line is 0 based in the protocol
|
--line; // line is 0 based in the protocol
|
||||||
--column; // column is 0 based in the protocol
|
--column; // column is 0 based in the protocol
|
||||||
params.setPosition({line, column});
|
params.setPosition({line, column});
|
||||||
params.setContext(context);
|
params.setContext(context);
|
||||||
params.setTextDocument(TextDocumentIdentifier(DocumentUri::fromFilePath(interface->filePath())));
|
params.setTextDocument(
|
||||||
|
TextDocumentIdentifier(DocumentUri::fromFilePath(interface()->filePath())));
|
||||||
if (const int limit = m_client->completionResultsLimit(); limit >= 0)
|
if (const int limit = m_client->completionResultsLimit(); limit >= 0)
|
||||||
params.setLimit(limit);
|
params.setLimit(limit);
|
||||||
CompletionRequest completionRequest(params);
|
CompletionRequest completionRequest(params);
|
||||||
@@ -368,10 +367,10 @@ IAssistProposal *LanguageClientCompletionAssistProcessor::perform(AssistInterfac
|
|||||||
m_client->sendMessage(completionRequest);
|
m_client->sendMessage(completionRequest);
|
||||||
m_client->addAssistProcessor(this);
|
m_client->addAssistProcessor(this);
|
||||||
m_currentRequest = completionRequest.id();
|
m_currentRequest = completionRequest.id();
|
||||||
m_filePath = interface->filePath();
|
m_filePath = interface()->filePath();
|
||||||
qCDebug(LOGLSPCOMPLETION) << QTime::currentTime()
|
qCDebug(LOGLSPCOMPLETION) << QTime::currentTime()
|
||||||
<< " : request completions at " << m_pos
|
<< " : request completions at " << m_pos
|
||||||
<< " by " << assistReasonString(interface->reason());
|
<< " by " << assistReasonString(interface()->reason());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -59,7 +59,7 @@ class LANGUAGECLIENT_EXPORT LanguageClientCompletionAssistProcessor
|
|||||||
public:
|
public:
|
||||||
LanguageClientCompletionAssistProcessor(Client *client, const QString &snippetsGroup);
|
LanguageClientCompletionAssistProcessor(Client *client, const QString &snippetsGroup);
|
||||||
~LanguageClientCompletionAssistProcessor() override;
|
~LanguageClientCompletionAssistProcessor() override;
|
||||||
TextEditor::IAssistProposal *perform(TextEditor::AssistInterface *interface) override;
|
TextEditor::IAssistProposal *perform() override;
|
||||||
bool running() override;
|
bool running() override;
|
||||||
bool needsRestart() const override { return true; }
|
bool needsRestart() const override { return true; }
|
||||||
void cancel() override;
|
void cancel() override;
|
||||||
@@ -74,7 +74,6 @@ protected:
|
|||||||
private:
|
private:
|
||||||
void handleCompletionResponse(const LanguageServerProtocol::CompletionRequest::Response &response);
|
void handleCompletionResponse(const LanguageServerProtocol::CompletionRequest::Response &response);
|
||||||
|
|
||||||
QScopedPointer<const TextEditor::AssistInterface> m_assistInterface;
|
|
||||||
Utils::FilePath m_filePath;
|
Utils::FilePath m_filePath;
|
||||||
QPointer<Client> m_client;
|
QPointer<Client> m_client;
|
||||||
std::optional<LanguageServerProtocol::MessageId> m_currentRequest;
|
std::optional<LanguageServerProtocol::MessageId> m_currentRequest;
|
||||||
|
@@ -66,14 +66,13 @@ FunctionHintProcessor::FunctionHintProcessor(Client *client)
|
|||||||
: m_client(client)
|
: m_client(client)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
IAssistProposal *FunctionHintProcessor::perform(AssistInterface *interface)
|
IAssistProposal *FunctionHintProcessor::perform()
|
||||||
{
|
{
|
||||||
const QScopedPointer<const AssistInterface> deleter(interface);
|
|
||||||
QTC_ASSERT(m_client, return nullptr);
|
QTC_ASSERT(m_client, return nullptr);
|
||||||
m_pos = interface->position();
|
m_pos = interface()->position();
|
||||||
QTextCursor cursor(interface->textDocument());
|
QTextCursor cursor(interface()->textDocument());
|
||||||
cursor.setPosition(m_pos);
|
cursor.setPosition(m_pos);
|
||||||
auto uri = DocumentUri::fromFilePath(interface->filePath());
|
auto uri = DocumentUri::fromFilePath(interface()->filePath());
|
||||||
SignatureHelpRequest request((TextDocumentPositionParams(TextDocumentIdentifier(uri), Position(cursor))));
|
SignatureHelpRequest request((TextDocumentPositionParams(TextDocumentIdentifier(uri), Position(cursor))));
|
||||||
request.setResponseCallback([this](auto response) { this->handleSignatureResponse(response); });
|
request.setResponseCallback([this](auto response) { this->handleSignatureResponse(response); });
|
||||||
m_client->addAssistProcessor(this);
|
m_client->addAssistProcessor(this);
|
||||||
@@ -118,7 +117,7 @@ FunctionHintAssistProvider::FunctionHintAssistProvider(Client *client)
|
|||||||
, m_client(client)
|
, m_client(client)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
TextEditor::IAssistProcessor *FunctionHintAssistProvider::createProcessor(
|
IAssistProcessor *FunctionHintAssistProvider::createProcessor(
|
||||||
const AssistInterface *) const
|
const AssistInterface *) const
|
||||||
{
|
{
|
||||||
return new FunctionHintProcessor(m_client);
|
return new FunctionHintProcessor(m_client);
|
||||||
|
@@ -44,7 +44,7 @@ class LANGUAGECLIENT_EXPORT FunctionHintProcessor : public TextEditor::IAssistPr
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit FunctionHintProcessor(Client *client);
|
explicit FunctionHintProcessor(Client *client);
|
||||||
TextEditor::IAssistProposal *perform(TextEditor::AssistInterface *interface) override;
|
TextEditor::IAssistProposal *perform() override;
|
||||||
bool running() override { return m_currentRequest.has_value(); }
|
bool running() override { return m_currentRequest.has_value(); }
|
||||||
bool needsRestart() const override { return true; }
|
bool needsRestart() const override { return true; }
|
||||||
void cancel() override;
|
void cancel() override;
|
||||||
|
@@ -45,13 +45,11 @@ void CommandQuickFixOperation::perform()
|
|||||||
m_client->executeCommand(m_command);
|
m_client->executeCommand(m_command);
|
||||||
}
|
}
|
||||||
|
|
||||||
IAssistProposal *LanguageClientQuickFixAssistProcessor::perform(AssistInterface *interface)
|
IAssistProposal *LanguageClientQuickFixAssistProcessor::perform()
|
||||||
{
|
{
|
||||||
m_assistInterface = QSharedPointer<const AssistInterface>(interface);
|
|
||||||
|
|
||||||
CodeActionParams params;
|
CodeActionParams params;
|
||||||
params.setContext({});
|
params.setContext({});
|
||||||
QTextCursor cursor = interface->cursor();
|
QTextCursor cursor = interface()->cursor();
|
||||||
if (!cursor.hasSelection()) {
|
if (!cursor.hasSelection()) {
|
||||||
if (cursor.atBlockEnd() || cursor.atBlockStart())
|
if (cursor.atBlockEnd() || cursor.atBlockStart())
|
||||||
cursor.select(QTextCursor::LineUnderCursor);
|
cursor.select(QTextCursor::LineUnderCursor);
|
||||||
@@ -62,7 +60,7 @@ IAssistProposal *LanguageClientQuickFixAssistProcessor::perform(AssistInterface
|
|||||||
cursor.select(QTextCursor::LineUnderCursor);
|
cursor.select(QTextCursor::LineUnderCursor);
|
||||||
Range range(cursor);
|
Range range(cursor);
|
||||||
params.setRange(range);
|
params.setRange(range);
|
||||||
auto uri = DocumentUri::fromFilePath(interface->filePath());
|
auto uri = DocumentUri::fromFilePath(interface()->filePath());
|
||||||
params.setTextDocument(TextDocumentIdentifier(uri));
|
params.setTextDocument(TextDocumentIdentifier(uri));
|
||||||
CodeActionParams::CodeActionContext context;
|
CodeActionParams::CodeActionContext context;
|
||||||
context.setDiagnostics(m_client->diagnosticsAt(uri, cursor));
|
context.setDiagnostics(m_client->diagnosticsAt(uri, cursor));
|
||||||
@@ -110,7 +108,7 @@ GenericProposal *LanguageClientQuickFixAssistProcessor::handleCodeActionResult(c
|
|||||||
else if (auto command = std::get_if<Command>(&item))
|
else if (auto command = std::get_if<Command>(&item))
|
||||||
ops << new CommandQuickFixOperation(*command, m_client);
|
ops << new CommandQuickFixOperation(*command, m_client);
|
||||||
}
|
}
|
||||||
return GenericProposal::createProposal(m_assistInterface.data(), ops);
|
return GenericProposal::createProposal(interface(), ops);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@@ -63,7 +63,7 @@ class LANGUAGECLIENT_EXPORT LanguageClientQuickFixAssistProcessor
|
|||||||
public:
|
public:
|
||||||
explicit LanguageClientQuickFixAssistProcessor(Client *client) : m_client(client) {}
|
explicit LanguageClientQuickFixAssistProcessor(Client *client) : m_client(client) {}
|
||||||
bool running() override { return m_currentRequest.has_value(); }
|
bool running() override { return m_currentRequest.has_value(); }
|
||||||
TextEditor::IAssistProposal *perform(TextEditor::AssistInterface *interface) override;
|
TextEditor::IAssistProposal *perform() override;
|
||||||
void cancel() override;
|
void cancel() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -76,7 +76,6 @@ private:
|
|||||||
virtual TextEditor::GenericProposal *handleCodeActionResult(
|
virtual TextEditor::GenericProposal *handleCodeActionResult(
|
||||||
const LanguageServerProtocol::CodeActionResult &result);
|
const LanguageServerProtocol::CodeActionResult &result);
|
||||||
|
|
||||||
QSharedPointer<const TextEditor::AssistInterface> m_assistInterface;
|
|
||||||
Client *m_client = nullptr; // not owned
|
Client *m_client = nullptr; // not owned
|
||||||
std::optional<LanguageServerProtocol::MessageId> m_currentRequest;
|
std::optional<LanguageServerProtocol::MessageId> m_currentRequest;
|
||||||
};
|
};
|
||||||
|
@@ -43,25 +43,24 @@ class NimCompletionAssistProcessor : public QObject, public TextEditor::IAssistP
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TextEditor::IAssistProposal *perform(TextEditor::AssistInterface *interface) final
|
TextEditor::IAssistProposal *perform() final
|
||||||
{
|
{
|
||||||
QTC_ASSERT(this->thread() == qApp->thread(), return nullptr);
|
QTC_ASSERT(this->thread() == qApp->thread(), return nullptr);
|
||||||
|
|
||||||
if (interface->reason() == IdleEditor && !acceptsIdleEditor(interface))
|
if (interface()->reason() == IdleEditor && !acceptsIdleEditor(interface()))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
Suggest::NimSuggest *suggest = nimSuggestInstance(interface);
|
Suggest::NimSuggest *suggest = nimSuggestInstance(interface());
|
||||||
QTC_ASSERT(suggest, return nullptr);
|
QTC_ASSERT(suggest, return nullptr);
|
||||||
|
|
||||||
if (suggest->executablePath().isEmpty() || suggest->projectFile().isEmpty())
|
if (suggest->executablePath().isEmpty() || suggest->projectFile().isEmpty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (!suggest->isReady()) {
|
if (!suggest->isReady()) {
|
||||||
m_interface = interface;
|
|
||||||
QObject::connect(suggest, &Suggest::NimSuggest::readyChanged, this,
|
QObject::connect(suggest, &Suggest::NimSuggest::readyChanged, this,
|
||||||
[this, suggest](bool ready) { onNimSuggestReady(suggest, ready); });
|
[this, suggest](bool ready) { onNimSuggestReady(suggest, ready); });
|
||||||
} else {
|
} else {
|
||||||
doPerform(interface, suggest);
|
doPerform(interface(), suggest);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_running = true;
|
m_running = true;
|
||||||
@@ -76,13 +75,13 @@ public:
|
|||||||
private:
|
private:
|
||||||
void onNimSuggestReady(Suggest::NimSuggest *suggest, bool ready)
|
void onNimSuggestReady(Suggest::NimSuggest *suggest, bool ready)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_interface, return);
|
QTC_ASSERT(interface(), return);
|
||||||
|
|
||||||
if (!ready) {
|
if (!ready) {
|
||||||
m_running = false;
|
m_running = false;
|
||||||
setAsyncProposalAvailable(nullptr);
|
setAsyncProposalAvailable(nullptr);
|
||||||
} else {
|
} else {
|
||||||
doPerform(m_interface, suggest);
|
doPerform(interface(), suggest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +230,6 @@ private:
|
|||||||
std::weak_ptr<Suggest::NimSuggest> m_suggest;
|
std::weak_ptr<Suggest::NimSuggest> m_suggest;
|
||||||
std::shared_ptr<Suggest::NimSuggestClientRequest> m_request;
|
std::shared_ptr<Suggest::NimSuggestClientRequest> m_request;
|
||||||
std::unique_ptr<QTemporaryFile> m_dirtyFile;
|
std::unique_ptr<QTemporaryFile> m_dirtyFile;
|
||||||
const TextEditor::AssistInterface *m_interface = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -76,10 +76,10 @@ bool BindingEditorWidget::event(QEvent *event)
|
|||||||
return QmlJSEditor::QmlJSEditorWidget::event(event);
|
return QmlJSEditor::QmlJSEditorWidget::event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextEditor::AssistInterface *BindingEditorWidget::createAssistInterface(
|
std::unique_ptr<TextEditor::AssistInterface> BindingEditorWidget::createAssistInterface(
|
||||||
[[maybe_unused]] TextEditor::AssistKind assistKind, TextEditor::AssistReason assistReason) const
|
[[maybe_unused]] TextEditor::AssistKind assistKind, TextEditor::AssistReason assistReason) const
|
||||||
{
|
{
|
||||||
return new QmlJSEditor::QmlJSCompletionAssistInterface(
|
return std::make_unique<QmlJSEditor::QmlJSCompletionAssistInterface>(
|
||||||
textCursor(), Utils::FilePath(),
|
textCursor(), Utils::FilePath(),
|
||||||
assistReason, qmljsdocument->semanticInfo());
|
assistReason, qmljsdocument->semanticInfo());
|
||||||
}
|
}
|
||||||
|
@@ -29,8 +29,8 @@ public:
|
|||||||
|
|
||||||
bool event(QEvent *event) override;
|
bool event(QEvent *event) override;
|
||||||
|
|
||||||
TextEditor::AssistInterface *createAssistInterface(TextEditor::AssistKind assistKind,
|
std::unique_ptr<TextEditor::AssistInterface> createAssistInterface(
|
||||||
TextEditor::AssistReason assistReason) const override;
|
TextEditor::AssistKind assistKind, TextEditor::AssistReason assistReason) const override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void returnKeyClicked();
|
void returnKeyClicked();
|
||||||
|
@@ -315,14 +315,9 @@ QStringList qmlJSAutoComplete(QTextDocument *textDocument,
|
|||||||
QmlJSCompletionAssistProcessor processor;
|
QmlJSCompletionAssistProcessor processor;
|
||||||
QTextCursor cursor(textDocument);
|
QTextCursor cursor(textDocument);
|
||||||
cursor.setPosition(position);
|
cursor.setPosition(position);
|
||||||
QScopedPointer<IAssistProposal> proposal(processor.perform( /* The processor takes ownership. */
|
std::unique_ptr<QmlJSCompletionAssistInterface>
|
||||||
new QmlJSCompletionAssistInterface(
|
interface = std::make_unique<QmlJSCompletionAssistInterface>(cursor, fileName, reason, info);
|
||||||
cursor,
|
if (QScopedPointer<IAssistProposal> proposal{processor.start(std::move(interface))}) {
|
||||||
fileName,
|
|
||||||
reason,
|
|
||||||
info)));
|
|
||||||
|
|
||||||
if (proposal) {
|
|
||||||
GenericProposalModelPtr model = proposal->model().staticCast<GenericProposalModel>();
|
GenericProposalModelPtr model = proposal->model().staticCast<GenericProposalModel>();
|
||||||
|
|
||||||
int basePosition = proposal->basePosition();
|
int basePosition = proposal->basePosition();
|
||||||
@@ -525,21 +520,19 @@ IAssistProposal *QmlJSCompletionAssistProcessor::createHintProposal(
|
|||||||
return new FunctionHintProposal(m_startPosition, model);
|
return new FunctionHintProposal(m_startPosition, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
IAssistProposal *QmlJSCompletionAssistProcessor::performAsync(AssistInterface *assistInterface)
|
IAssistProposal *QmlJSCompletionAssistProcessor::performAsync()
|
||||||
{
|
{
|
||||||
m_interface.reset(static_cast<const QmlJSCompletionAssistInterface *>(assistInterface));
|
if (interface()->reason() == IdleEditor && !acceptsIdleEditor())
|
||||||
|
|
||||||
if (assistInterface->reason() == IdleEditor && !acceptsIdleEditor())
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
m_startPosition = assistInterface->position();
|
m_startPosition = interface()->position();
|
||||||
while (isIdentifierChar(m_interface->textDocument()->characterAt(m_startPosition - 1), false, false))
|
while (isIdentifierChar(interface()->textDocument()->characterAt(m_startPosition - 1), false, false))
|
||||||
--m_startPosition;
|
--m_startPosition;
|
||||||
const bool onIdentifier = m_startPosition != assistInterface->position();
|
const bool onIdentifier = m_startPosition != interface()->position();
|
||||||
|
|
||||||
m_completions.clear();
|
m_completions.clear();
|
||||||
|
|
||||||
auto qmlInterface = static_cast<const QmlJSCompletionAssistInterface *>(assistInterface);
|
auto qmlInterface = static_cast<const QmlJSCompletionAssistInterface *>(interface());
|
||||||
const SemanticInfo &semanticInfo = qmlInterface->semanticInfo();
|
const SemanticInfo &semanticInfo = qmlInterface->semanticInfo();
|
||||||
if (!semanticInfo.isValid())
|
if (!semanticInfo.isValid())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -547,10 +540,10 @@ IAssistProposal *QmlJSCompletionAssistProcessor::performAsync(AssistInterface *a
|
|||||||
const Document::Ptr document = semanticInfo.document;
|
const Document::Ptr document = semanticInfo.document;
|
||||||
|
|
||||||
bool isQmlFile = false;
|
bool isQmlFile = false;
|
||||||
if (m_interface->filePath().endsWith(".qml"))
|
if (interface()->filePath().endsWith(".qml"))
|
||||||
isQmlFile = true;
|
isQmlFile = true;
|
||||||
|
|
||||||
const QList<AST::Node *> path = semanticInfo.rangePath(m_interface->position());
|
const QList<AST::Node *> path = semanticInfo.rangePath(interface()->position());
|
||||||
const ContextPtr &context = semanticInfo.context;
|
const ContextPtr &context = semanticInfo.context;
|
||||||
const ScopeChain &scopeChain = semanticInfo.scopeChain(path);
|
const ScopeChain &scopeChain = semanticInfo.scopeChain(path);
|
||||||
|
|
||||||
@@ -561,7 +554,7 @@ IAssistProposal *QmlJSCompletionAssistProcessor::performAsync(AssistInterface *a
|
|||||||
// a +b<complete> -> '+'
|
// a +b<complete> -> '+'
|
||||||
QChar completionOperator;
|
QChar completionOperator;
|
||||||
if (m_startPosition > 0)
|
if (m_startPosition > 0)
|
||||||
completionOperator = m_interface->textDocument()->characterAt(m_startPosition - 1);
|
completionOperator = interface()->textDocument()->characterAt(m_startPosition - 1);
|
||||||
|
|
||||||
QTextCursor startPositionCursor(qmlInterface->textDocument());
|
QTextCursor startPositionCursor(qmlInterface->textDocument());
|
||||||
startPositionCursor.setPosition(m_startPosition);
|
startPositionCursor.setPosition(m_startPosition);
|
||||||
@@ -709,7 +702,7 @@ IAssistProposal *QmlJSCompletionAssistProcessor::performAsync(AssistInterface *a
|
|||||||
}
|
}
|
||||||
} else if (value
|
} else if (value
|
||||||
&& completionOperator == QLatin1Char('(')
|
&& completionOperator == QLatin1Char('(')
|
||||||
&& m_startPosition == m_interface->position()) {
|
&& m_startPosition == interface()->position()) {
|
||||||
// function completion
|
// function completion
|
||||||
if (const FunctionValue *f = value->asFunctionValue()) {
|
if (const FunctionValue *f = value->asFunctionValue()) {
|
||||||
QString functionName = expressionUnderCursor.text();
|
QString functionName = expressionUnderCursor.text();
|
||||||
@@ -733,7 +726,7 @@ IAssistProposal *QmlJSCompletionAssistProcessor::performAsync(AssistInterface *a
|
|||||||
}
|
}
|
||||||
|
|
||||||
// global completion
|
// global completion
|
||||||
if (onIdentifier || assistInterface->reason() == ExplicitlyInvoked) {
|
if (onIdentifier || interface()->reason() == ExplicitlyInvoked) {
|
||||||
|
|
||||||
bool doGlobalCompletion = true;
|
bool doGlobalCompletion = true;
|
||||||
bool doQmlKeywordCompletion = true;
|
bool doQmlKeywordCompletion = true;
|
||||||
@@ -845,14 +838,14 @@ IAssistProposal *QmlJSCompletionAssistProcessor::performAsync(AssistInterface *a
|
|||||||
|
|
||||||
bool QmlJSCompletionAssistProcessor::acceptsIdleEditor() const
|
bool QmlJSCompletionAssistProcessor::acceptsIdleEditor() const
|
||||||
{
|
{
|
||||||
const int cursorPos = m_interface->position();
|
const int cursorPos = interface()->position();
|
||||||
|
|
||||||
bool maybeAccept = false;
|
bool maybeAccept = false;
|
||||||
const QChar &charBeforeCursor = m_interface->textDocument()->characterAt(cursorPos - 1);
|
const QChar &charBeforeCursor = interface()->textDocument()->characterAt(cursorPos - 1);
|
||||||
if (isActivationChar(charBeforeCursor)) {
|
if (isActivationChar(charBeforeCursor)) {
|
||||||
maybeAccept = true;
|
maybeAccept = true;
|
||||||
} else {
|
} else {
|
||||||
const QChar &charUnderCursor = m_interface->textDocument()->characterAt(cursorPos);
|
const QChar &charUnderCursor = interface()->textDocument()->characterAt(cursorPos);
|
||||||
if (isValidIdentifierChar(charUnderCursor))
|
if (isValidIdentifierChar(charUnderCursor))
|
||||||
return false;
|
return false;
|
||||||
if (isIdentifierChar(charBeforeCursor)
|
if (isIdentifierChar(charBeforeCursor)
|
||||||
@@ -863,12 +856,12 @@ bool QmlJSCompletionAssistProcessor::acceptsIdleEditor() const
|
|||||||
|
|
||||||
int startPos = cursorPos - 1;
|
int startPos = cursorPos - 1;
|
||||||
for (; startPos != -1; --startPos) {
|
for (; startPos != -1; --startPos) {
|
||||||
if (!isIdentifierChar(m_interface->textDocument()->characterAt(startPos)))
|
if (!isIdentifierChar(interface()->textDocument()->characterAt(startPos)))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++startPos;
|
++startPos;
|
||||||
|
|
||||||
const QString &word = m_interface->textAt(startPos, cursorPos - startPos);
|
const QString &word = interface()->textAt(startPos, cursorPos - startPos);
|
||||||
if (word.length() >= TextEditorSettings::completionSettings().m_characterThreshold
|
if (word.length() >= TextEditorSettings::completionSettings().m_characterThreshold
|
||||||
&& isIdentifierChar(word.at(0), true)) {
|
&& isIdentifierChar(word.at(0), true)) {
|
||||||
for (int i = 1; i < word.length(); ++i) {
|
for (int i = 1; i < word.length(); ++i) {
|
||||||
@@ -881,15 +874,15 @@ bool QmlJSCompletionAssistProcessor::acceptsIdleEditor() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (maybeAccept) {
|
if (maybeAccept) {
|
||||||
QTextCursor tc(m_interface->textDocument());
|
QTextCursor tc(interface()->textDocument());
|
||||||
tc.setPosition(m_interface->position());
|
tc.setPosition(interface()->position());
|
||||||
const QTextBlock &block = tc.block();
|
const QTextBlock &block = tc.block();
|
||||||
const QString &blockText = block.text();
|
const QString &blockText = block.text();
|
||||||
const int blockState = qMax(0, block.previous().userState()) & 0xff;
|
const int blockState = qMax(0, block.previous().userState()) & 0xff;
|
||||||
|
|
||||||
Scanner scanner;
|
Scanner scanner;
|
||||||
const QList<Token> tokens = scanner(blockText, blockState);
|
const QList<Token> tokens = scanner(blockText, blockState);
|
||||||
const int column = block.position() - m_interface->position();
|
const int column = block.position() - interface()->position();
|
||||||
for (const Token &tk : tokens) {
|
for (const Token &tk : tokens) {
|
||||||
if (column >= tk.begin() && column <= tk.end()) {
|
if (column >= tk.begin() && column <= tk.end()) {
|
||||||
if (charBeforeCursor == QLatin1Char('/') && tk.is(Token::String))
|
if (charBeforeCursor == QLatin1Char('/') && tk.is(Token::String))
|
||||||
|
@@ -57,7 +57,7 @@ public:
|
|||||||
QmlJSCompletionAssistProcessor();
|
QmlJSCompletionAssistProcessor();
|
||||||
~QmlJSCompletionAssistProcessor() override;
|
~QmlJSCompletionAssistProcessor() override;
|
||||||
|
|
||||||
TextEditor::IAssistProposal *performAsync(TextEditor::AssistInterface *interface) override;
|
TextEditor::IAssistProposal *performAsync() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TextEditor::IAssistProposal *createContentProposal() const;
|
TextEditor::IAssistProposal *createContentProposal() const;
|
||||||
@@ -73,7 +73,6 @@ private:
|
|||||||
const QStringList &patterns = QStringList());
|
const QStringList &patterns = QStringList());
|
||||||
|
|
||||||
int m_startPosition;
|
int m_startPosition;
|
||||||
QScopedPointer<const QmlJSCompletionAssistInterface> m_interface;
|
|
||||||
QList<TextEditor::AssistProposalItemInterface *> m_completions;
|
QList<TextEditor::AssistProposalItemInterface *> m_completions;
|
||||||
TextEditor::SnippetAssistCollector m_snippetCollector;
|
TextEditor::SnippetAssistCollector m_snippetCollector;
|
||||||
};
|
};
|
||||||
|
@@ -857,11 +857,11 @@ void QmlJSEditorWidget::contextMenuEvent(QContextMenuEvent *e)
|
|||||||
QMenu *refactoringMenu = new QMenu(Tr::tr("Refactoring"), menu);
|
QMenu *refactoringMenu = new QMenu(Tr::tr("Refactoring"), menu);
|
||||||
|
|
||||||
if (!m_qmlJsEditorDocument->isSemanticInfoOutdated()) {
|
if (!m_qmlJsEditorDocument->isSemanticInfoOutdated()) {
|
||||||
AssistInterface *interface = createAssistInterface(QuickFix, ExplicitlyInvoked);
|
std::unique_ptr<AssistInterface> interface = createAssistInterface(QuickFix, ExplicitlyInvoked);
|
||||||
if (interface) {
|
if (interface) {
|
||||||
QScopedPointer<IAssistProcessor> processor(
|
QScopedPointer<IAssistProcessor> processor(
|
||||||
Internal::QmlJSEditorPlugin::quickFixAssistProvider()->createProcessor(interface));
|
Internal::QmlJSEditorPlugin::quickFixAssistProvider()->createProcessor(interface.get()));
|
||||||
QScopedPointer<IAssistProposal> proposal(processor->perform(interface));
|
QScopedPointer<IAssistProposal> proposal(processor->start(std::move(interface)));
|
||||||
if (!proposal.isNull()) {
|
if (!proposal.isNull()) {
|
||||||
GenericProposalModelPtr model = proposal->model().staticCast<GenericProposalModel>();
|
GenericProposalModelPtr model = proposal->model().staticCast<GenericProposalModel>();
|
||||||
for (int index = 0; index < model->size(); ++index) {
|
for (int index = 0; index < model->size(); ++index) {
|
||||||
@@ -999,15 +999,16 @@ bool QmlJSEditorWidget::hideContextPane()
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssistInterface *QmlJSEditorWidget::createAssistInterface(
|
std::unique_ptr<AssistInterface> QmlJSEditorWidget::createAssistInterface(
|
||||||
AssistKind assistKind,
|
AssistKind assistKind,
|
||||||
AssistReason reason) const
|
AssistReason reason) const
|
||||||
{
|
{
|
||||||
if (assistKind == Completion) {
|
if (assistKind == Completion) {
|
||||||
return new QmlJSCompletionAssistInterface(textCursor(), textDocument()->filePath(),
|
return std::make_unique<QmlJSCompletionAssistInterface>(
|
||||||
reason, m_qmlJsEditorDocument->semanticInfo());
|
textCursor(), textDocument()->filePath(), reason, m_qmlJsEditorDocument->semanticInfo());
|
||||||
} else if (assistKind == QuickFix) {
|
} else if (assistKind == QuickFix) {
|
||||||
return new Internal::QmlJSQuickFixAssistInterface(const_cast<QmlJSEditorWidget *>(this), reason);
|
return std::make_unique<Internal::QmlJSQuickFixAssistInterface>(
|
||||||
|
const_cast<QmlJSEditorWidget *>(this), reason);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@@ -44,8 +44,8 @@ public:
|
|||||||
void updateOutlineIndexNow();
|
void updateOutlineIndexNow();
|
||||||
bool isOutlineCursorChangesBlocked();
|
bool isOutlineCursorChangesBlocked();
|
||||||
|
|
||||||
TextEditor::AssistInterface *createAssistInterface(TextEditor::AssistKind assistKind,
|
std::unique_ptr<TextEditor::AssistInterface> createAssistInterface(
|
||||||
TextEditor::AssistReason reason) const override;
|
TextEditor::AssistKind assistKind, TextEditor::AssistReason reason) const override;
|
||||||
|
|
||||||
void inspectElementUnderCursor() const;
|
void inspectElementUnderCursor() const;
|
||||||
|
|
||||||
|
@@ -48,9 +48,9 @@ QmlJSRefactoringFilePtr QmlJSQuickFixAssistInterface::currentFile() const
|
|||||||
// ---------------------------
|
// ---------------------------
|
||||||
class QmlJSQuickFixAssistProcessor : public IAssistProcessor
|
class QmlJSQuickFixAssistProcessor : public IAssistProcessor
|
||||||
{
|
{
|
||||||
IAssistProposal *perform(AssistInterface *interface) override
|
IAssistProposal *perform() override
|
||||||
{
|
{
|
||||||
return GenericProposal::createProposal(interface, findQmlJSQuickFixes(interface));
|
return GenericProposal::createProposal(interface(), findQmlJSQuickFixes(interface()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -63,12 +63,8 @@ private:
|
|||||||
class ClipboardAssistProcessor: public IAssistProcessor
|
class ClipboardAssistProcessor: public IAssistProcessor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
IAssistProposal *perform(AssistInterface *interface) override
|
IAssistProposal *perform() override
|
||||||
{
|
{
|
||||||
if (!interface)
|
|
||||||
return nullptr;
|
|
||||||
const QScopedPointer<const AssistInterface> AssistInterface(interface);
|
|
||||||
|
|
||||||
QIcon icon = QIcon::fromTheme(QLatin1String("edit-paste"), Utils::Icons::PASTE.icon()).pixmap(16);
|
QIcon icon = QIcon::fromTheme(QLatin1String("edit-paste"), Utils::Icons::PASTE.icon()).pixmap(16);
|
||||||
CircularClipboard * clipboard = CircularClipboard::instance();
|
CircularClipboard * clipboard = CircularClipboard::instance();
|
||||||
QList<AssistProposalItemInterface *> items;
|
QList<AssistProposalItemInterface *> items;
|
||||||
@@ -82,7 +78,7 @@ public:
|
|||||||
items.append(item);
|
items.append(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GenericProposal(interface->position(), items);
|
return new GenericProposal(interface()->position(), items);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -17,14 +17,13 @@ AsyncProcessor::AsyncProcessor()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
IAssistProposal *AsyncProcessor::perform(AssistInterface *interface)
|
IAssistProposal *AsyncProcessor::perform()
|
||||||
{
|
{
|
||||||
IAssistProposal *result = immediateProposal(interface);
|
IAssistProposal *result = immediateProposal();
|
||||||
m_interface = interface;
|
interface()->prepareForAsyncUse();
|
||||||
m_interface->prepareForAsyncUse();
|
|
||||||
m_watcher.setFuture(Utils::runAsync([this]() {
|
m_watcher.setFuture(Utils::runAsync([this]() {
|
||||||
m_interface->recreateTextDocument();
|
interface()->recreateTextDocument();
|
||||||
return performAsync(m_interface);
|
return performAsync();
|
||||||
}));
|
}));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -44,9 +43,8 @@ void AsyncProcessor::cancel()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
IAssistProposal *AsyncProcessor::immediateProposal(AssistInterface *interface)
|
IAssistProposal *AsyncProcessor::immediateProposal()
|
||||||
{
|
{
|
||||||
Q_UNUSED(interface)
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,18 +14,17 @@ class TEXTEDITOR_EXPORT AsyncProcessor : public TextEditor::IAssistProcessor
|
|||||||
public:
|
public:
|
||||||
AsyncProcessor();
|
AsyncProcessor();
|
||||||
|
|
||||||
IAssistProposal *perform(AssistInterface *interface) final;
|
IAssistProposal *perform() final;
|
||||||
bool running() override;
|
bool running() override;
|
||||||
void cancel() override;
|
void cancel() override;
|
||||||
|
|
||||||
virtual IAssistProposal *performAsync(AssistInterface *interface) = 0;
|
virtual IAssistProposal *performAsync() = 0;
|
||||||
virtual IAssistProposal *immediateProposal(AssistInterface *interface);
|
virtual IAssistProposal *immediateProposal();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool isCanceled() const;
|
bool isCanceled() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AssistInterface *m_interface = nullptr;
|
|
||||||
QFutureWatcher<IAssistProposal *> m_watcher;
|
QFutureWatcher<IAssistProposal *> m_watcher;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -176,7 +176,8 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssistInterface *assistInterface = m_editorWidget->createAssistInterface(kind, reason);
|
std::unique_ptr<AssistInterface> assistInterface =
|
||||||
|
m_editorWidget->createAssistInterface(kind, reason);
|
||||||
if (!assistInterface)
|
if (!assistInterface)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -185,8 +186,7 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason,
|
|||||||
|
|
||||||
m_assistKind = kind;
|
m_assistKind = kind;
|
||||||
m_requestProvider = provider;
|
m_requestProvider = provider;
|
||||||
IAssistProcessor *processor = provider->createProcessor(assistInterface);
|
IAssistProcessor *processor = provider->createProcessor(assistInterface.get());
|
||||||
|
|
||||||
processor->setAsyncCompletionAvailableHandler([this, reason, processor](
|
processor->setAsyncCompletionAvailableHandler([this, reason, processor](
|
||||||
IAssistProposal *newProposal) {
|
IAssistProposal *newProposal) {
|
||||||
if (!processor->running()) {
|
if (!processor->running()) {
|
||||||
@@ -211,7 +211,7 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason,
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (IAssistProposal *newProposal = processor->perform(assistInterface))
|
if (IAssistProposal *newProposal = processor->start(std::move(assistInterface)))
|
||||||
displayProposal(newProposal, reason);
|
displayProposal(newProposal, reason);
|
||||||
if (!processor->running()) {
|
if (!processor->running()) {
|
||||||
if (isUpdate)
|
if (isUpdate)
|
||||||
|
@@ -29,7 +29,7 @@ public:
|
|||||||
DocumentContentCompletionProcessor(const QString &snippetGroupId);
|
DocumentContentCompletionProcessor(const QString &snippetGroupId);
|
||||||
~DocumentContentCompletionProcessor() final;
|
~DocumentContentCompletionProcessor() final;
|
||||||
|
|
||||||
IAssistProposal *performAsync(AssistInterface *interface) override;
|
IAssistProposal *performAsync() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_snippetGroup;
|
QString m_snippetGroup;
|
||||||
@@ -53,23 +53,21 @@ DocumentContentCompletionProcessor::~DocumentContentCompletionProcessor()
|
|||||||
cancel();
|
cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
IAssistProposal *DocumentContentCompletionProcessor::performAsync(AssistInterface *interface)
|
IAssistProposal *DocumentContentCompletionProcessor::performAsync()
|
||||||
{
|
{
|
||||||
QScopedPointer<AssistInterface> interfaceDeleter(interface);
|
int pos = interface()->position();
|
||||||
|
|
||||||
int pos = interface->position();
|
|
||||||
|
|
||||||
QChar chr;
|
QChar chr;
|
||||||
// Skip to the start of a name
|
// Skip to the start of a name
|
||||||
do {
|
do {
|
||||||
chr = interface->characterAt(--pos);
|
chr = interface()->characterAt(--pos);
|
||||||
} while (chr.isLetterOrNumber() || chr == '_');
|
} while (chr.isLetterOrNumber() || chr == '_');
|
||||||
|
|
||||||
++pos;
|
++pos;
|
||||||
int length = interface->position() - pos;
|
int length = interface()->position() - pos;
|
||||||
|
|
||||||
if (interface->reason() == IdleEditor) {
|
if (interface()->reason() == IdleEditor) {
|
||||||
QChar characterUnderCursor = interface->characterAt(interface->position());
|
QChar characterUnderCursor = interface()->characterAt(interface()->position());
|
||||||
if (characterUnderCursor.isLetterOrNumber()
|
if (characterUnderCursor.isLetterOrNumber()
|
||||||
|| length < TextEditorSettings::completionSettings().m_characterThreshold) {
|
|| length < TextEditorSettings::completionSettings().m_characterThreshold) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -80,8 +78,8 @@ IAssistProposal *DocumentContentCompletionProcessor::performAsync(AssistInterfac
|
|||||||
m_snippetGroup, QIcon(":/texteditor/images/snippet.png"));
|
m_snippetGroup, QIcon(":/texteditor/images/snippet.png"));
|
||||||
QList<AssistProposalItemInterface *> items = snippetCollector.collect();
|
QList<AssistProposalItemInterface *> items = snippetCollector.collect();
|
||||||
|
|
||||||
const QString wordUnderCursor = interface->textAt(pos, length);
|
const QString wordUnderCursor = interface()->textAt(pos, length);
|
||||||
const QString text = interface->textDocument()->toPlainText();
|
const QString text = interface()->textDocument()->toPlainText();
|
||||||
|
|
||||||
const QRegularExpression wordRE("([\\p{L}_][\\p{L}0-9_]{2,})");
|
const QRegularExpression wordRE("([\\p{L}_][\\p{L}0-9_]{2,})");
|
||||||
QSet<QString> words;
|
QSet<QString> words;
|
||||||
|
@@ -17,7 +17,7 @@ public:
|
|||||||
DocumentContentCompletionProvider(
|
DocumentContentCompletionProvider(
|
||||||
const QString &snippetGroup = QString(Constants::TEXT_SNIPPET_GROUP_ID));
|
const QString &snippetGroup = QString(Constants::TEXT_SNIPPET_GROUP_ID));
|
||||||
|
|
||||||
IAssistProcessor *createProcessor(const AssistInterface *) const override;
|
IAssistProcessor *createProcessor(const AssistInterface *interface) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_snippetGroup;
|
QString m_snippetGroup;
|
||||||
|
@@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
#include "iassistprocessor.h"
|
#include "iassistprocessor.h"
|
||||||
|
|
||||||
|
#include "assistinterface.h"
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -18,6 +22,14 @@ IAssistProcessor::IAssistProcessor() = default;
|
|||||||
|
|
||||||
IAssistProcessor::~IAssistProcessor() = default;
|
IAssistProcessor::~IAssistProcessor() = default;
|
||||||
|
|
||||||
|
IAssistProposal *IAssistProcessor::start(std::unique_ptr<AssistInterface> &&interface)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(!running(), return nullptr);
|
||||||
|
m_interface = std::move(interface);
|
||||||
|
QTC_ASSERT(m_interface, return nullptr);
|
||||||
|
return perform();
|
||||||
|
}
|
||||||
|
|
||||||
void IAssistProcessor::setAsyncProposalAvailable(IAssistProposal *proposal)
|
void IAssistProcessor::setAsyncProposalAvailable(IAssistProposal *proposal)
|
||||||
{
|
{
|
||||||
if (m_asyncCompletionsAvailableHandler)
|
if (m_asyncCompletionsAvailableHandler)
|
||||||
@@ -30,15 +42,27 @@ void IAssistProcessor::setAsyncCompletionAvailableHandler(
|
|||||||
m_asyncCompletionsAvailableHandler = handler;
|
m_asyncCompletionsAvailableHandler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IAssistProcessor::running() { return false; }
|
||||||
|
|
||||||
|
bool IAssistProcessor::needsRestart() const { return false; }
|
||||||
|
|
||||||
|
void IAssistProcessor::cancel() {}
|
||||||
|
|
||||||
|
AssistInterface *IAssistProcessor::interface() { return m_interface.get(); }
|
||||||
|
const AssistInterface *IAssistProcessor::interface() const { return m_interface.get(); }
|
||||||
|
|
||||||
|
#ifdef WITH_TESTS
|
||||||
|
void IAssistProcessor::setupAssistInterface(std::unique_ptr<AssistInterface> &&interface)
|
||||||
|
{
|
||||||
|
m_interface = std::move(interface);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn IAssistProposal *TextEditor::IAssistProcessor::perform(const AssistInterface *interface)
|
\fn IAssistProposal *TextEditor::IAssistProcessor::start()
|
||||||
|
|
||||||
Computes a proposal and returns it. Access to the document is made through the \a interface.
|
Computes a proposal and returns it. Access to the document is made through the \a interface.
|
||||||
If this is an asynchronous processor the \a interface will be detached.
|
|
||||||
|
|
||||||
The processor takes ownership of the interface. Also, one should be careful in the case of
|
The processor takes ownership of the interface. Also, one should be careful in the case of
|
||||||
sharing data across asynchronous processors since there might be more than one instance of
|
sharing data across asynchronous processors since there might be more than one instance of
|
||||||
them computing a proposal at a particular time.
|
them computing a proposal at a particular time.*/
|
||||||
|
|
||||||
\sa AssistInterface::detach()
|
|
||||||
*/
|
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
#include <texteditor/texteditor_global.h>
|
#include <texteditor/texteditor_global.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace TextEditor {
|
namespace TextEditor {
|
||||||
|
|
||||||
@@ -18,21 +19,30 @@ public:
|
|||||||
IAssistProcessor();
|
IAssistProcessor();
|
||||||
virtual ~IAssistProcessor();
|
virtual ~IAssistProcessor();
|
||||||
|
|
||||||
virtual IAssistProposal *perform(AssistInterface *interface) = 0; // takes ownership
|
IAssistProposal *start(std::unique_ptr<AssistInterface> &&interface);
|
||||||
|
|
||||||
void setAsyncProposalAvailable(IAssistProposal *proposal);
|
|
||||||
|
|
||||||
// Internal, used by CodeAssist
|
// Internal, used by CodeAssist
|
||||||
using AsyncCompletionsAvailableHandler
|
using AsyncCompletionsAvailableHandler
|
||||||
= std::function<void (IAssistProposal *proposal)>;
|
= std::function<void (IAssistProposal *proposal)>;
|
||||||
void setAsyncCompletionAvailableHandler(const AsyncCompletionsAvailableHandler &handler);
|
void setAsyncCompletionAvailableHandler(const AsyncCompletionsAvailableHandler &handler);
|
||||||
|
void setAsyncProposalAvailable(IAssistProposal *proposal);
|
||||||
|
|
||||||
virtual bool running() { return false; }
|
virtual bool running();
|
||||||
virtual bool needsRestart() const { return false; }
|
virtual bool needsRestart() const;
|
||||||
virtual void cancel() {}
|
virtual void cancel();
|
||||||
|
|
||||||
|
#ifdef WITH_TESTS
|
||||||
|
void setupAssistInterface(std::unique_ptr<AssistInterface> &&interface);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual IAssistProposal *perform() = 0;
|
||||||
|
AssistInterface *interface();
|
||||||
|
const AssistInterface *interface() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AsyncCompletionsAvailableHandler m_asyncCompletionsAvailableHandler;
|
AsyncCompletionsAvailableHandler m_asyncCompletionsAvailableHandler;
|
||||||
|
std::unique_ptr<AssistInterface> m_interface;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // TextEditor
|
} // TextEditor
|
||||||
|
@@ -150,34 +150,33 @@ KeywordsCompletionAssistProcessor::KeywordsCompletionAssistProcessor(const Keywo
|
|||||||
, m_keywords(keywords)
|
, m_keywords(keywords)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
IAssistProposal *KeywordsCompletionAssistProcessor::performAsync(AssistInterface *interface)
|
IAssistProposal *KeywordsCompletionAssistProcessor::performAsync()
|
||||||
{
|
{
|
||||||
QScopedPointer<const AssistInterface> assistInterface(interface);
|
if (isInComment(interface()))
|
||||||
if (isInComment(interface))
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
int pos = interface->position();
|
int pos = interface()->position();
|
||||||
|
|
||||||
// Find start position
|
// Find start position
|
||||||
QChar chr = interface->characterAt(pos - 1);
|
QChar chr = interface()->characterAt(pos - 1);
|
||||||
if (chr == '(')
|
if (chr == '(')
|
||||||
--pos;
|
--pos;
|
||||||
// Skip to the start of a name
|
// Skip to the start of a name
|
||||||
do {
|
do {
|
||||||
chr = interface->characterAt(--pos);
|
chr = interface()->characterAt(--pos);
|
||||||
} while (chr.isLetterOrNumber() || chr == '_');
|
} while (chr.isLetterOrNumber() || chr == '_');
|
||||||
|
|
||||||
++pos;
|
++pos;
|
||||||
|
|
||||||
int startPosition = pos;
|
int startPosition = pos;
|
||||||
|
|
||||||
if (interface->reason() == IdleEditor) {
|
if (interface()->reason() == IdleEditor) {
|
||||||
QChar characterUnderCursor = interface->characterAt(interface->position());
|
QChar characterUnderCursor = interface()->characterAt(interface()->position());
|
||||||
if (characterUnderCursor.isLetterOrNumber() || interface->position() - startPosition
|
if (characterUnderCursor.isLetterOrNumber() || interface()->position() - startPosition
|
||||||
< TextEditorSettings::completionSettings().m_characterThreshold) {
|
< TextEditorSettings::completionSettings().m_characterThreshold) {
|
||||||
QList<AssistProposalItemInterface *> items;
|
QList<AssistProposalItemInterface *> items;
|
||||||
if (m_dynamicCompletionFunction)
|
if (m_dynamicCompletionFunction)
|
||||||
m_dynamicCompletionFunction(interface, &items, startPosition);
|
m_dynamicCompletionFunction(interface(), &items, startPosition);
|
||||||
if (items.isEmpty())
|
if (items.isEmpty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return new GenericProposal(startPosition, items);
|
return new GenericProposal(startPosition, items);
|
||||||
@@ -187,11 +186,11 @@ IAssistProposal *KeywordsCompletionAssistProcessor::performAsync(AssistInterface
|
|||||||
// extract word
|
// extract word
|
||||||
QString word;
|
QString word;
|
||||||
do {
|
do {
|
||||||
word += interface->characterAt(pos);
|
word += interface()->characterAt(pos);
|
||||||
chr = interface->characterAt(++pos);
|
chr = interface()->characterAt(++pos);
|
||||||
} while ((chr.isLetterOrNumber() || chr == '_') && chr != '(');
|
} while ((chr.isLetterOrNumber() || chr == '_') && chr != '(');
|
||||||
|
|
||||||
if (m_keywords.isFunction(word) && interface->characterAt(pos) == '(') {
|
if (m_keywords.isFunction(word) && interface()->characterAt(pos) == '(') {
|
||||||
QStringList functionSymbols = m_keywords.argsForFunction(word);
|
QStringList functionSymbols = m_keywords.argsForFunction(word);
|
||||||
if (functionSymbols.size() == 0)
|
if (functionSymbols.size() == 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -201,7 +200,7 @@ IAssistProposal *KeywordsCompletionAssistProcessor::performAsync(AssistInterface
|
|||||||
const int originalStartPos = startPosition;
|
const int originalStartPos = startPosition;
|
||||||
QList<AssistProposalItemInterface *> items;
|
QList<AssistProposalItemInterface *> items;
|
||||||
if (m_dynamicCompletionFunction)
|
if (m_dynamicCompletionFunction)
|
||||||
m_dynamicCompletionFunction(interface, &items, startPosition);
|
m_dynamicCompletionFunction(interface(), &items, startPosition);
|
||||||
if (startPosition == originalStartPos) {
|
if (startPosition == originalStartPos) {
|
||||||
items.append(m_snippetCollector.collect());
|
items.append(m_snippetCollector.collect());
|
||||||
items.append(generateProposalList(m_keywords.variables(), m_variableIcon));
|
items.append(generateProposalList(m_keywords.variables(), m_variableIcon));
|
||||||
|
@@ -85,7 +85,7 @@ public:
|
|||||||
KeywordsCompletionAssistProcessor(const Keywords &keywords);
|
KeywordsCompletionAssistProcessor(const Keywords &keywords);
|
||||||
~KeywordsCompletionAssistProcessor() override = default;
|
~KeywordsCompletionAssistProcessor() override = default;
|
||||||
|
|
||||||
IAssistProposal *performAsync(AssistInterface *interface) override;
|
IAssistProposal *performAsync() override;
|
||||||
|
|
||||||
void setSnippetGroup(const QString &id);
|
void setSnippetGroup(const QString &id);
|
||||||
|
|
||||||
|
@@ -8534,11 +8534,11 @@ void TextEditorWidget::invokeAssist(AssistKind kind, IAssistProvider *provider)
|
|||||||
setOverwriteMode(previousMode);
|
setOverwriteMode(previousMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
AssistInterface *TextEditorWidget::createAssistInterface(AssistKind kind,
|
std::unique_ptr<AssistInterface> TextEditorWidget::createAssistInterface(AssistKind kind,
|
||||||
AssistReason reason) const
|
AssistReason reason) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(kind)
|
Q_UNUSED(kind)
|
||||||
return new AssistInterface(textCursor(), d->m_document->filePath(), reason);
|
return std::make_unique<AssistInterface>(textCursor(), d->m_document->filePath(), reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TextEditorWidget::foldReplacementText(const QTextBlock &) const
|
QString TextEditorWidget::foldReplacementText(const QTextBlock &) const
|
||||||
|
@@ -23,7 +23,9 @@
|
|||||||
|
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QToolBar;
|
class QToolBar;
|
||||||
@@ -259,7 +261,7 @@ public:
|
|||||||
|
|
||||||
void invokeAssist(AssistKind assistKind, IAssistProvider *provider = nullptr);
|
void invokeAssist(AssistKind assistKind, IAssistProvider *provider = nullptr);
|
||||||
|
|
||||||
virtual TextEditor::AssistInterface *createAssistInterface(AssistKind assistKind,
|
virtual std::unique_ptr<AssistInterface> createAssistInterface(AssistKind assistKind,
|
||||||
AssistReason assistReason) const;
|
AssistReason assistReason) const;
|
||||||
static QMimeData *duplicateMimeData(const QMimeData *source);
|
static QMimeData *duplicateMimeData(const QMimeData *source);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user