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:
David Schulz
2022-11-15 14:19:06 +01:00
parent aa6633ca21
commit 0e4b0a26d3
43 changed files with 325 additions and 321 deletions

View File

@@ -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)

View File

@@ -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;
}; };

View File

@@ -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)

View File

@@ -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

View File

@@ -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();

View File

@@ -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

View File

@@ -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;
}; };

View File

@@ -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,

View File

@@ -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);
} }

View File

@@ -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;

View File

@@ -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));
} }
}; };

View File

@@ -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);

View File

@@ -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();

View File

@@ -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)));
} }

View File

@@ -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) {

View File

@@ -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

View File

@@ -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);
} }

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;
} }

View File

@@ -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;
}; };

View File

@@ -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;
}; };

View File

@@ -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());
} }

View File

@@ -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();

View File

@@ -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))

View File

@@ -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;
}; };

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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()));
} }
}; };

View File

@@ -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);
} }
}; };

View File

@@ -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;
} }

View File

@@ -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;
}; };

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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()
*/

View File

@@ -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

View File

@@ -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));

View File

@@ -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);

View File

@@ -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

View File

@@ -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);