Merge remote-tracking branch 'origin/13.0'

Conflicts:
	src/plugins/debugger/gdb/gdbsettings.cpp
	src/plugins/perfprofiler/perfprofilerruncontrol.cpp

Change-Id: I0d5b914f9d9b5499920a5db484ef77af6ae748d5
This commit is contained in:
Eike Ziller
2024-03-12 09:27:39 +01:00
77 changed files with 3193 additions and 972 deletions

View File

@@ -405,6 +405,7 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir, c
setSupportedLanguage(langFilter);
setActivateDocumentAutomatically(true);
setCompletionAssistProvider(new ClangdCompletionAssistProvider(this));
setFunctionHintAssistProvider(new ClangdFunctionHintProvider(this));
setQuickFixAssistProvider(new ClangdQuickFixProvider(this));
symbolSupport().setLimitRenamingToProjects(true);
symbolSupport().setRenameResultsEnhancer([](const SearchResultItems &symbolOccurrencesInCode) {

View File

@@ -102,13 +102,52 @@ private:
QElapsedTimer m_timer;
};
class ClangdFunctionHintProposalModel : public FunctionHintProposalModel
{
public:
using FunctionHintProposalModel::FunctionHintProposalModel;
private:
int activeArgument(const QString &prefix) const override
{
const int arg = activeArgumenForPrefix(prefix);
if (arg < 0)
return -1;
m_currentArg = arg;
return arg;
}
QString text(int index) const override
{
using Parameters = QList<ParameterInformation>;
if (index < 0 || m_sigis.signatures().size() <= index)
return {};
const SignatureInformation signature = m_sigis.signatures().at(index);
QString label = signature.label();
const QList<QString> parameters = Utils::transform(signature.parameters().value_or(Parameters()),
&ParameterInformation::label);
if (parameters.size() <= m_currentArg)
return label;
const QString &parameterText = parameters.at(m_currentArg);
const int start = label.indexOf(parameterText);
const int end = start + parameterText.length();
return label.mid(0, start).toHtmlEscaped() + "<b>" + parameterText.toHtmlEscaped() + "</b>"
+ label.mid(end).toHtmlEscaped();
}
mutable int m_currentArg = 0;
};
class ClangdFunctionHintProcessor : public FunctionHintProcessor
{
public:
ClangdFunctionHintProcessor(ClangdClient *client);
ClangdFunctionHintProcessor(ClangdClient *client, int basePosition);
private:
IAssistProposal *perform() override;
IFunctionHintProposalModel *createModel(const SignatureHelp &signatureHelp) const override;
ClangdClient * const m_client;
};
@@ -138,7 +177,8 @@ IAssistProcessor *ClangdCompletionAssistProvider::createProcessor(
switch (contextAnalyzer.completionAction()) {
case ClangCompletionContextAnalyzer::PassThroughToLibClangAfterLeftParen:
qCDebug(clangdLogCompletion) << "creating function hint processor";
return new ClangdFunctionHintProcessor(m_client);
return new ClangdFunctionHintProcessor(m_client,
contextAnalyzer.positionForProposal());
case ClangCompletionContextAnalyzer::CompletePreprocessorDirective:
qCDebug(clangdLogCompletion) << "creating macro processor";
return new CustomAssistProcessor(m_client,
@@ -606,8 +646,8 @@ QList<AssistProposalItemInterface *> ClangdCompletionAssistProcessor::generateCo
return itemGenerator(items);
}
ClangdFunctionHintProcessor::ClangdFunctionHintProcessor(ClangdClient *client)
: FunctionHintProcessor(client)
ClangdFunctionHintProcessor::ClangdFunctionHintProcessor(ClangdClient *client, int basePosition)
: FunctionHintProcessor(client, basePosition)
, m_client(client)
{}
@@ -621,6 +661,12 @@ IAssistProposal *ClangdFunctionHintProcessor::perform()
return FunctionHintProcessor::perform();
}
IFunctionHintProposalModel *ClangdFunctionHintProcessor::createModel(
const SignatureHelp &signatureHelp) const
{
return new ClangdFunctionHintProposalModel(signatureHelp);
}
ClangdCompletionCapabilities::ClangdCompletionCapabilities(const JsonObject &object)
: TextDocumentClientCapabilities::CompletionCapabilities(object)
{
@@ -631,4 +677,18 @@ ClangdCompletionCapabilities::ClangdCompletionCapabilities(const JsonObject &obj
}
}
ClangdFunctionHintProvider::ClangdFunctionHintProvider(ClangdClient *client)
: FunctionHintAssistProvider(client)
, m_client(client)
{}
IAssistProcessor *ClangdFunctionHintProvider::createProcessor(
const AssistInterface *interface) const
{
ClangCompletionContextAnalyzer contextAnalyzer(interface->textDocument(),
interface->position(), false, {});
contextAnalyzer.analyze();
return new ClangdFunctionHintProcessor(m_client, contextAnalyzer.positionForProposal());
}
} // namespace ClangCodeModel::Internal

View File

@@ -1,11 +1,10 @@
#include <languageclient/languageclientcompletionassist.h>
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include <languageclient/languageclientcompletionassist.h>
#include <languageclient/languageclientfunctionhint.h>
#include <languageserverprotocol/clientcapabilities.h>
namespace TextEditor { class IAssistProcessor; }
@@ -37,4 +36,16 @@ public:
explicit ClangdCompletionCapabilities(const JsonObject &object);
};
class ClangdFunctionHintProvider : public LanguageClient::FunctionHintAssistProvider
{
public:
ClangdFunctionHintProvider(ClangdClient *client);
private:
TextEditor::IAssistProcessor *createProcessor(
const TextEditor::AssistInterface *assistInterface) const override;
ClangdClient * const m_client;
};
} // namespace ClangCodeModel::Internal

View File

@@ -29,6 +29,7 @@
#include <texteditor/blockrange.h>
#include <texteditor/codeassist/assistproposaliteminterface.h>
#include <texteditor/codeassist/genericproposal.h>
#include <texteditor/codeassist/ifunctionhintproposalmodel.h>
#include <texteditor/codeassist/textdocumentmanipulatorinterface.h>
#include <texteditor/semantichighlighter.h>
#include <texteditor/textmark.h>
@@ -1832,12 +1833,12 @@ void ClangdTestCompletion::testFunctionHints()
QVERIFY(proposal);
QVERIFY(hasItem(proposal, "f() -> void"));
QVERIFY(hasItem(proposal, "f(int a) -> void"));
QVERIFY(hasItem(proposal, "f(const QString &s) -> void"));
QVERIFY(hasItem(proposal, "f(char c, int optional = 3) -> void"));
QVERIFY(hasItem(proposal, "f(char c, int optional1 = 3, int optional2 = 3) -> void"));
QVERIFY(hasItem(proposal, "f(const TType<QString> *t) -> void"));
QVERIFY(hasItem(proposal, "f(bool) -> TType<QString>"));
QVERIFY(hasItem(proposal, "f(<b>int a</b>) -&gt; void"));
QVERIFY(hasItem(proposal, "f(<b>const QString &amp;s</b>) -&gt; void"));
QVERIFY(hasItem(proposal, "f(<b>char c</b>, int optional = 3) -&gt; void"));
QVERIFY(hasItem(proposal, "f(<b>char c</b>, int optional1 = 3, int optional2 = 3) -&gt; void"));
QVERIFY(hasItem(proposal, "f(<b>const TType&lt;QString&gt; *t</b>) -&gt; void"));
QVERIFY(hasItem(proposal, "f(<b>bool</b>) -&gt; TType&lt;QString&gt;"));
}
void ClangdTestCompletion::testFunctionHintsFiltered()
@@ -1855,7 +1856,6 @@ void ClangdTestCompletion::testFunctionHintsFiltered()
QVERIFY(proposal);
QCOMPARE(proposal->size(), 2);
QVERIFY(hasItem(proposal, "func(const S &amp;s, <b>int j</b>) -&gt; void"));
QEXPECT_FAIL("", "QTCREATORBUG-26346", Abort);
QVERIFY(hasItem(proposal, "func(const S &amp;s, <b>int j</b>, int k) -&gt; void"));
}
@@ -1868,7 +1868,6 @@ void ClangdTestCompletion::testFunctionHintConstructor()
QVERIFY(!hasItem(proposal, "globalVariable"));
QVERIFY(!hasItem(proposal, " class"));
QVERIFY(hasItem(proposal, "Foo(<b>int</b>)"));
QEXPECT_FAIL("", "QTCREATORBUG-26346", Abort);
QVERIFY(hasItem(proposal, "Foo(<b>int</b>, double)"));
}
@@ -2066,7 +2065,8 @@ void ClangdTestCompletion::getProposal(const QString &fileName,
{
const TextDocument * const doc = document(fileName);
QVERIFY(doc);
const int pos = doc->document()->toPlainText().indexOf(" /* COMPLETE HERE */");
const QString docContent = doc->document()->toPlainText();
const int pos = docContent.indexOf(" /* COMPLETE HERE */");
QVERIFY(pos != -1);
if (cursorPos)
*cursorPos = pos;
@@ -2110,6 +2110,13 @@ void ClangdTestCompletion::getProposal(const QString &fileName,
QVERIFY(timer.isActive());
QVERIFY(proposal);
proposalModel = proposal->model();
if (auto functionHintModel = proposalModel.dynamicCast<IFunctionHintProposalModel>()) {
const int proposalBasePos = proposal->basePosition();
// The language client function hint model expects that activeArgument was called before the
// text of individual hints is accessed. This is usually done by the proposal widget. But
// since we don't have a proposal widget in this test, we have to call it manually.
functionHintModel->activeArgument(docContent.mid(proposalBasePos, pos - proposalBasePos));
}
delete proposal;
// The "dot" test files are only used once.