Make qmlls semantic highlighting optional

Qmlls semantic highlighting in QtC occasionally flickers on editing the
document. Since this might be disturbing to some users, we should be
able to toggle its switch so that they can enable/disable it. By
default, it is disabled.

Add an option in the qml language server preferences to
switch highlighter module.

Add a check in highlighter() to test if there is actually semantic
highlighting request. Otherwise, it is invoked on the initialization of
the language client unconditionally which wouldn't respect the settings.

Task-number: QTCREATORBUG-31215
Change-Id: I1d7df44071053993839860087fb0ab6ede61e145
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Semih Yavuz
2024-10-28 16:51:52 +01:00
parent db5a39311f
commit a6b2cb67db
6 changed files with 49 additions and 2 deletions

View File

@@ -418,6 +418,8 @@ void SemanticTokenSupport::highlight(const Utils::FilePath &filePath, bool force
TextDocument *doc = TextDocument::textDocumentForFilePath(filePath); TextDocument *doc = TextDocument::textDocumentForFilePath(filePath);
if (!doc || LanguageClientManager::clientForDocument(doc) != m_client) if (!doc || LanguageClientManager::clientForDocument(doc) != m_client)
return; return;
if (supportedSemanticRequests(doc).testFlag(SemanticRequestType::None))
return;
SyntaxHighlighter *highlighter = doc->syntaxHighlighter(); SyntaxHighlighter *highlighter = doc->syntaxHighlighter();
if (!highlighter) if (!highlighter)
return; return;

View File

@@ -734,7 +734,7 @@ void QmlJSEditorDocumentPrivate::setSourcesWithCapabilities(
setSemanticWarningSource(QmllsStatus::Source::Qmlls); setSemanticWarningSource(QmllsStatus::Source::Qmlls);
else else
setSemanticWarningSource(QmllsStatus::Source::EmbeddedCodeModel); setSemanticWarningSource(QmllsStatus::Source::EmbeddedCodeModel);
if (cap.semanticTokensProvider()) if (cap.semanticTokensProvider() && settings().enableQmllsSemanticHighlighting())
setSemanticHighlightSource(QmllsStatus::Source::Qmlls); setSemanticHighlightSource(QmllsStatus::Source::Qmlls);
else else
setSemanticHighlightSource(QmllsStatus::Source::EmbeddedCodeModel); setSemanticHighlightSource(QmllsStatus::Source::EmbeddedCodeModel);
@@ -765,8 +765,14 @@ void QmlJSEditorDocumentPrivate::settingsChanged()
return; return;
FilePath newQmlls = qmllsForFile(q->filePath(), ModelManagerInterface::instance()); FilePath newQmlls = qmllsForFile(q->filePath(), ModelManagerInterface::instance());
if (m_qmllsStatus.qmllsPath == newQmlls) if (m_qmllsStatus.qmllsPath == newQmlls) {
if (QmllsClient *client = QmllsClient::clientForQmlls(newQmlls)) {
client->updateQmllsSemanticHighlightingCapability();
setSourcesWithCapabilities(client->capabilities());
client->activateDocument(q);
}
return; return;
}
using namespace LanguageClient; using namespace LanguageClient;
m_qmllsStatus.qmllsPath = newQmlls; m_qmllsStatus.qmllsPath = newQmlls;
@@ -788,6 +794,7 @@ void QmlJSEditorDocumentPrivate::settingsChanged()
if (client == oldClient) if (client == oldClient)
shouldActivate = true; shouldActivate = true;
} }
client->updateQmllsSemanticHighlightingCapability();
switch (client->state()) { switch (client->state()) {
case Client::State::Uninitialized: case Client::State::Uninitialized:
case Client::State::InitializeRequested: case Client::State::InitializeRequested:

View File

@@ -61,6 +61,7 @@ const char USE_GLOBAL_SETTINGS[] = "QmlJSEditor.UseGlobalSettings";
const char USE_QMLLS[] = "QmlJSEditor.UseQmlls"; const char USE_QMLLS[] = "QmlJSEditor.UseQmlls";
const char USE_LATEST_QMLLS[] = "QmlJSEditor.UseLatestQmlls"; const char USE_LATEST_QMLLS[] = "QmlJSEditor.UseLatestQmlls";
const char IGNORE_MINIMUM_QMLLS_VERSION[] = "QmlJSEditor.IgnoreMinimumQmllsVersion"; const char IGNORE_MINIMUM_QMLLS_VERSION[] = "QmlJSEditor.IgnoreMinimumQmllsVersion";
const char USE_QMLLS_SEMANTIC_HIGHLIGHTING[] = "QmlJSEditor.EnableQmllsSemanticHighlighting";
const char DISABLE_BUILTIN_CODEMODEL[] = "QmlJSEditor.DisableBuiltinCodemodel"; const char DISABLE_BUILTIN_CODEMODEL[] = "QmlJSEditor.DisableBuiltinCodemodel";
const char GENERATE_QMLLS_INI_FILES[] = "QmlJSEditor.GenerateQmllsIniFiles"; const char GENERATE_QMLLS_INI_FILES[] = "QmlJSEditor.GenerateQmllsIniFiles";
const char UIQML_OPEN_MODE[] = "QmlJSEditor.openUiQmlMode"; const char UIQML_OPEN_MODE[] = "QmlJSEditor.openUiQmlMode";
@@ -150,6 +151,7 @@ void QmllsSettingsManager::checkForChanges()
&& m_useLatestQmlls == newSettings.useLatestQmlls() && m_useLatestQmlls == newSettings.useLatestQmlls()
&& m_disableBuiltinCodemodel == newSettings.disableBuiltinCodemodel() && m_disableBuiltinCodemodel == newSettings.disableBuiltinCodemodel()
&& m_generateQmllsIniFiles == newSettings.generateQmllsIniFiles() && m_generateQmllsIniFiles == newSettings.generateQmllsIniFiles()
&& m_enableQmllsSemanticHighlighting == newSettings.enableQmllsSemanticHighlighting()
&& newLatest == m_latestQmlls) && newLatest == m_latestQmlls)
return; return;
qCDebug(qmllsLog) << "qmlls settings changed:" << newSettings.useQmlls() qCDebug(qmllsLog) << "qmlls settings changed:" << newSettings.useQmlls()
@@ -160,6 +162,7 @@ void QmllsSettingsManager::checkForChanges()
m_useQmlls = newSettings.useQmlls(); m_useQmlls = newSettings.useQmlls();
m_useLatestQmlls = newSettings.useLatestQmlls(); m_useLatestQmlls = newSettings.useLatestQmlls();
m_disableBuiltinCodemodel = newSettings.disableBuiltinCodemodel(); m_disableBuiltinCodemodel = newSettings.disableBuiltinCodemodel();
m_enableQmllsSemanticHighlighting = newSettings.enableQmllsSemanticHighlighting();
m_generateQmllsIniFiles = newSettings.generateQmllsIniFiles(); m_generateQmllsIniFiles = newSettings.generateQmllsIniFiles();
} }
emit settingsChanged(); emit settingsChanged();
@@ -263,6 +266,10 @@ QmlJsEditingSettings::QmlJsEditingSettings()
Tr::tr("Allow versions below Qt %1") Tr::tr("Allow versions below Qt %1")
.arg(QmlJsEditingSettings::mininumQmllsVersion.toString())); .arg(QmlJsEditingSettings::mininumQmllsVersion.toString()));
enableQmllsSemanticHighlighting.setSettingsKey(group, USE_QMLLS_SEMANTIC_HIGHLIGHTING);
enableQmllsSemanticHighlighting.setLabelText(
Tr::tr("Enable semantic highlighting (experimental)"));
useCustomFormatCommand.setSettingsKey(group, CUSTOM_COMMAND); useCustomFormatCommand.setSettingsKey(group, CUSTOM_COMMAND);
useCustomFormatCommand.setLabelText( useCustomFormatCommand.setLabelText(
Tr::tr("Use custom command instead of built-in formatter")); Tr::tr("Use custom command instead of built-in formatter"));
@@ -296,6 +303,7 @@ QmlJsEditingSettings::QmlJsEditingSettings()
disableBuiltinCodemodel.setEnabler(&useQmlls); disableBuiltinCodemodel.setEnabler(&useQmlls);
generateQmllsIniFiles.setEnabler(&useQmlls); generateQmllsIniFiles.setEnabler(&useQmlls);
ignoreMinimumQmllsVersion.setEnabler(&useQmlls); ignoreMinimumQmllsVersion.setEnabler(&useQmlls);
enableQmllsSemanticHighlighting.setEnabler(&useQmlls);
formatCommand.setEnabler(&useCustomFormatCommand); formatCommand.setEnabler(&useCustomFormatCommand);
formatCommandOptions.setEnabler(&useCustomFormatCommand); formatCommandOptions.setEnabler(&useCustomFormatCommand);
} }
@@ -422,6 +430,7 @@ public:
s.useQmlls, s.useQmlls,
s.ignoreMinimumQmllsVersion, s.ignoreMinimumQmllsVersion,
s.disableBuiltinCodemodel, s.disableBuiltinCodemodel,
s.enableQmllsSemanticHighlighting,
s.useLatestQmlls, s.useLatestQmlls,
s.generateQmllsIniFiles s.generateQmllsIniFiles
}, },

View File

@@ -34,6 +34,7 @@ public:
Utils::BoolAspect useQmlls{this}; Utils::BoolAspect useQmlls{this};
Utils::BoolAspect useLatestQmlls{this}; Utils::BoolAspect useLatestQmlls{this};
Utils::BoolAspect ignoreMinimumQmllsVersion{this}; Utils::BoolAspect ignoreMinimumQmllsVersion{this};
Utils::BoolAspect enableQmllsSemanticHighlighting{this};
Utils::BoolAspect disableBuiltinCodemodel{this}; Utils::BoolAspect disableBuiltinCodemodel{this};
Utils::BoolAspect generateQmllsIniFiles{this}; Utils::BoolAspect generateQmllsIniFiles{this};
Utils::SelectionAspect uiQmlOpenMode{this}; Utils::SelectionAspect uiQmlOpenMode{this};
@@ -67,6 +68,7 @@ private:
bool m_useLatestQmlls = false; bool m_useLatestQmlls = false;
bool m_disableBuiltinCodemodel = false; bool m_disableBuiltinCodemodel = false;
bool m_generateQmllsIniFiles = false; bool m_generateQmllsIniFiles = false;
bool m_enableQmllsSemanticHighlighting = false;
Utils::FilePath m_latestQmlls; Utils::FilePath m_latestQmlls;
}; };

View File

@@ -5,6 +5,7 @@
#include "qmljseditorconstants.h" #include "qmljseditorconstants.h"
#include "qmljseditortr.h" #include "qmljseditortr.h"
#include "qmljseditorsettings.h"
#include <languageclient/languageclientinterface.h> #include <languageclient/languageclientinterface.h>
#include <languageclient/languageclientmanager.h> #include <languageclient/languageclientmanager.h>
@@ -82,6 +83,30 @@ QMap<QString, int> QmllsClient::semanticTokenTypesMap()
return result; return result;
} }
void QmllsClient::updateQmllsSemanticHighlightingCapability()
{
const QString methodName = QStringLiteral("textDocument/semanticTokens");
if (!QmlJSEditor::Internal::settings().enableQmllsSemanticHighlighting()) {
LanguageServerProtocol::Unregistration unregister;
unregister.setMethod(methodName);
unregister.setId({});
this->unregisterCapabilities({unregister});
} else {
const LanguageServerProtocol::ServerCapabilities &caps = this->capabilities();
const std::optional<LanguageServerProtocol::SemanticTokensOptions> &options
= caps.semanticTokensProvider();
if (options) {
LanguageServerProtocol::Registration registeration;
registeration.setMethod(methodName);
registeration.setId({});
registeration.setRegisterOptions({*options});
this->registerCapabilities({registeration});
} else {
qCWarning(qmllsLog) << "qmlls does not support semantic highlighting";
}
}
}
QmllsClient::QmllsClient(StdIOClientInterface *interface) QmllsClient::QmllsClient(StdIOClientInterface *interface)
: Client(interface) : Client(interface)
{ {
@@ -162,6 +187,7 @@ QmllsClient::~QmllsClient()
void QmllsClient::startImpl() void QmllsClient::startImpl()
{ {
updateQmllsSemanticHighlightingCapability();
Client::startImpl(); Client::startImpl();
} }

View File

@@ -55,6 +55,7 @@ public:
void startImpl() override; void startImpl() override;
static QmllsClient *clientForQmlls(const Utils::FilePath &qmlls); static QmllsClient *clientForQmlls(const Utils::FilePath &qmlls);
void updateQmllsSemanticHighlightingCapability();
private: private:
static QMap<QString, int> semanticTokenTypesMap(); static QMap<QString, int> semanticTokenTypesMap();
}; };