LanguageClient: remove semantic highlighting proposal

The semantichighlighting proposal from
https://github.com/microsoft/vscode-languageserver-node/pull/367
was replaced with semantic tokens in the final protocol version 3.16.

This reverts 307f1d8e6e

Task-number: QTCREATORBUG-26624
Change-Id: I635f0b4763a197edabf9edf8d9041143dcf531e3
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
David Schulz
2021-11-29 09:44:46 +01:00
parent 022bf4396c
commit 6aa2c58842
11 changed files with 11 additions and 420 deletions

View File

@@ -102,10 +102,6 @@ Client::Client(BaseClientInterface *clientInterface)
connect(clientInterface, &BaseClientInterface::messageReceived, this, &Client::handleMessage);
connect(clientInterface, &BaseClientInterface::error, this, &Client::setError);
connect(clientInterface, &BaseClientInterface::finished, this, &Client::finished);
connect(TextEditor::TextEditorSettings::instance(),
&TextEditor::TextEditorSettings::fontSettingsChanged,
this,
&Client::rehighlight);
m_tokenSupport.setTokenTypesMap(SemanticTokens::defaultTokenTypesMap());
m_tokenSupport.setTokenModifiersMap(SemanticTokens::defaultTokenModifiersMap());
@@ -142,13 +138,6 @@ Client::~Client()
widget->removeHoverHandler(&m_hoverHandler);
}
}
for (auto it = m_highlights.cbegin(); it != m_highlights.cend(); ++it) {
const DocumentUri &uri = it.key();
if (TextDocument *doc = TextDocument::textDocumentForFilePath(uri.toFilePath())) {
if (TextEditor::SyntaxHighlighter *highlighter = doc->syntaxHighlighter())
highlighter->clearAllExtraFormats();
}
}
for (IAssistProcessor *processor : qAsConst(m_runningAssistProcessors))
processor->setAsyncProposalAvailable(nullptr);
qDeleteAll(m_documentHighlightsTimer);
@@ -199,10 +188,6 @@ static ClientCapabilities generateClientCapabilities()
symbolCapabilities.setHierarchicalDocumentSymbolSupport(true);
documentCapabilities.setDocumentSymbol(symbolCapabilities);
TextDocumentClientCapabilities::SemanticHighlightingCapabilities semanticHighlight;
semanticHighlight.setSemanticHighlighting(true);
documentCapabilities.setSemanticHighlightingCapabilities(semanticHighlight);
TextDocumentClientCapabilities::CompletionCapabilities completionCapabilities;
completionCapabilities.setDynamicRegistration(true);
TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemKindCapabilities
@@ -449,7 +434,6 @@ void Client::closeDocument(TextEditor::TextDocument *document)
{
deactivateDocument(document);
const DocumentUri &uri = DocumentUri::fromFilePath(document->filePath());
m_highlights[uri].clear();
m_postponedDocuments.remove(document);
if (m_openedDocument.remove(document) != 0) {
handleDocumentClosed(document);
@@ -580,7 +564,6 @@ void Client::activateDocument(TextEditor::TextDocument *document)
const FilePath &filePath = document->filePath();
auto uri = DocumentUri::fromFilePath(filePath);
m_diagnosticManager.showDiagnostics(uri, m_documentVersions.value(filePath));
SemanticHighligtingSupport::applyHighlight(document, m_highlights.value(uri), capabilities());
m_tokenSupport.updateSemanticTokens(document);
// only replace the assist provider if the language server support it
updateCompletionProvider(document);
@@ -607,10 +590,7 @@ void Client::deactivateDocument(TextEditor::TextDocument *document)
m_diagnosticManager.hideDiagnostics(document);
resetAssistProviders(document);
document->setFormatter(nullptr);
if (m_serverCapabilities.semanticHighlighting().has_value()) {
if (TextEditor::SyntaxHighlighter *highlighter = document->syntaxHighlighter())
highlighter->clearAllExtraFormats();
}
m_tokenSupport.clearHighlight(document);
for (Core::IEditor *editor : Core::DocumentModel::editorsForDocument(document)) {
if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor)) {
TextEditor::TextEditorWidget *widget = textEditor->editorWidget();
@@ -1249,7 +1229,6 @@ void Client::sendPostponedDocumentUpdates(Schedule semanticTokensSchedule)
TextEditor::TextDocument * const document = elem.first;
const FilePath &filePath = document->filePath();
const auto uri = DocumentUri::fromFilePath(filePath);
m_highlights[uri].clear();
VersionedTextDocumentIdentifier docId(uri);
docId.setVersion(m_documentVersions[filePath]);
DidChangeTextDocumentParams params;
@@ -1327,12 +1306,6 @@ void Client::handleMethod(const QString &method, const MessageId &id, const ICon
log(params);
else
log(invalidParamsErrorMessage(params));
} else if (method == SemanticHighlightNotification::methodName) {
auto params = dynamic_cast<const SemanticHighlightNotification *>(content)->params().value_or(SemanticHighlightingParams());
if (params.isValid())
handleSemanticHighlight(params);
else
log(invalidParamsErrorMessage(params));
} else if (method == ShowMessageNotification::methodName) {
auto params = dynamic_cast<const ShowMessageNotification *>(content)->params().value_or(ShowMessageParams());
if (params.isValid())
@@ -1457,48 +1430,6 @@ void Client::handleDiagnostics(const PublishDiagnosticsParams &params)
}
}
void Client::handleSemanticHighlight(const SemanticHighlightingParams &params)
{
DocumentUri uri;
LanguageClientValue<int> version;
auto textDocument = params.textDocument();
if (Utils::holds_alternative<VersionedTextDocumentIdentifier>(textDocument)) {
uri = Utils::get<VersionedTextDocumentIdentifier>(textDocument).uri();
version = Utils::get<VersionedTextDocumentIdentifier>(textDocument).version();
} else {
uri = Utils::get<TextDocumentIdentifier>(textDocument).uri();
}
m_highlights[uri].clear();
TextEditor::TextDocument *doc = TextEditor::TextDocument::textDocumentForFilePath(
uri.toFilePath());
if (!doc || LanguageClientManager::clientForDocument(doc) != this
|| (!version.isNull() && m_documentVersions.value(uri.toFilePath()) != version.value())) {
return;
}
const TextEditor::HighlightingResults results = SemanticHighligtingSupport::generateResults(
params.lines());
m_highlights[uri] = results;
SemanticHighligtingSupport::applyHighlight(doc, results, capabilities());
}
void Client::rehighlight()
{
using namespace TextEditor;
m_tokenSupport.rehighlight();
for (auto it = m_highlights.begin(), end = m_highlights.end(); it != end; ++it) {
if (TextDocument *doc = TextDocument::textDocumentForFilePath(it.key().toFilePath())) {
if (LanguageClientManager::clientForDocument(doc) == this)
SemanticHighligtingSupport::applyHighlight(doc, it.value(), capabilities());
}
}
}
bool Client::documentUpdatePostponed(const Utils::FilePath &fileName) const
{
return Utils::contains(m_documentsToUpdate, [fileName](const auto &elem) {

View File

@@ -226,8 +226,6 @@ private:
void handleMethod(const QString &method, const LanguageServerProtocol::MessageId &id,
const LanguageServerProtocol::IContent *content);
void handleSemanticHighlight(const LanguageServerProtocol::SemanticHighlightingParams &params);
void initializeCallback(const LanguageServerProtocol::InitializeRequest::Response &initResponse);
void shutDownCallback(const LanguageServerProtocol::ShutdownRequest::Response &shutdownResponse);
bool sendWorkspceFolderChanges() const;
@@ -247,7 +245,6 @@ private:
void requestDocumentHighlights(TextEditor::TextEditorWidget *widget);
LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(TextEditor::TextDocument *document) const;
void handleSemanticTokens(const LanguageServerProtocol::SemanticTokens &tokens);
void rehighlight();
virtual void handleDocumentClosed(TextEditor::TextDocument *) {}
virtual void handleDocumentOpened(TextEditor::TextDocument *) {}

View File

@@ -63,7 +63,6 @@ LanguageClientManager::LanguageClientManager(QObject *parent)
using namespace Core;
using namespace ProjectExplorer;
JsonRpcMessageHandler::registerMessageProvider<PublishDiagnosticsNotification>();
JsonRpcMessageHandler::registerMessageProvider<SemanticHighlightNotification>();
JsonRpcMessageHandler::registerMessageProvider<ApplyWorkspaceEditRequest>();
JsonRpcMessageHandler::registerMessageProvider<LogMessageNotification>();
JsonRpcMessageHandler::registerMessageProvider<ShowMessageRequest>();

View File

@@ -29,6 +29,7 @@
#include "languageclientmanager.h"
#include <texteditor/fontsettings.h>
#include <texteditor/syntaxhighlighter.h>
#include <texteditor/texteditor.h>
#include <texteditor/texteditorsettings.h>
#include <utils/mimetypes/mimedatabase.h>
@@ -42,138 +43,6 @@ namespace LanguageClient {
static Q_LOGGING_CATEGORY(LOGLSPHIGHLIGHT, "qtc.languageclient.highlight", QtWarningMsg);
namespace SemanticHighligtingSupport {
static const QList<QList<QString>> highlightScopes(const ServerCapabilities &capabilities)
{
return capabilities.semanticHighlighting()
.value_or(ServerCapabilities::SemanticHighlightingServerCapabilities())
.scopes().value_or(QList<QList<QString>>());
}
static Utils::optional<TextStyle> styleForScopes(const QList<QString> &scopes)
{
// missing "Minimal Scope Coverage" scopes
// entity.other.inherited-class
// entity.name.section
// entity.name.tag
// entity.other.attribute-name
// variable.language
// variable.parameter
// variable.function
// constant.numeric
// constant.language
// constant.character.escape
// support
// storage.modifier
// keyword.control
// keyword.operator
// keyword.declaration
// invalid
// invalid.deprecated
static const QMap<QString, TextStyle> styleForScopes = {
{"entity.name", C_TYPE},
{"entity.name.function", C_FUNCTION},
{"entity.name.function.method.static", C_GLOBAL},
{"entity.name.function.preprocessor", C_PREPROCESSOR},
{"entity.name.label", C_LABEL},
{"keyword", C_KEYWORD},
{"storage.type", C_KEYWORD},
{"constant.numeric", C_NUMBER},
{"string", C_STRING},
{"comment", C_COMMENT},
{"comment.block.documentation", C_DOXYGEN_COMMENT},
{"variable.function", C_FUNCTION},
{"variable.other", C_LOCAL},
{"variable.other.member", C_FIELD},
{"variable.other.field", C_FIELD},
{"variable.other.field.static", C_GLOBAL},
{"variable.parameter", C_PARAMETER},
};
for (QString scope : scopes) {
while (!scope.isEmpty()) {
auto style = styleForScopes.find(scope);
if (style != styleForScopes.end())
return style.value();
const int index = scope.lastIndexOf('.');
if (index <= 0)
break;
scope = scope.left(index);
}
}
return Utils::nullopt;
}
static QHash<int, QTextCharFormat> scopesToFormatHash(QList<QList<QString>> scopes,
const FontSettings &fontSettings)
{
QHash<int, QTextCharFormat> scopesToFormat;
for (int i = 0; i < scopes.size(); ++i) {
if (Utils::optional<TextStyle> style = styleForScopes(scopes[i]))
scopesToFormat[i] = fontSettings.toTextCharFormat(style.value());
}
return scopesToFormat;
}
HighlightingResult tokenToHighlightingResult(int line, const SemanticHighlightToken &token)
{
return HighlightingResult(unsigned(line) + 1,
unsigned(token.character) + 1,
token.length,
int(token.scope));
}
HighlightingResults generateResults(const QList<SemanticHighlightingInformation> &lines)
{
HighlightingResults results;
for (const SemanticHighlightingInformation &info : lines) {
const int line = info.line();
for (const SemanticHighlightToken &token :
info.tokens().value_or(QList<SemanticHighlightToken>())) {
results << tokenToHighlightingResult(line, token);
}
}
return results;
}
void applyHighlight(TextDocument *doc,
const HighlightingResults &results,
const ServerCapabilities &capabilities)
{
if (!doc->syntaxHighlighter())
return;
if (LOGLSPHIGHLIGHT().isDebugEnabled()) {
auto scopes = highlightScopes(capabilities);
qCDebug(LOGLSPHIGHLIGHT) << "semantic highlight for" << doc->filePath();
for (auto result : results) {
auto b = doc->document()->findBlockByNumber(int(result.line - 1));
const QString &text = b.text().mid(int(result.column - 1), int(result.length));
auto resultScupes = scopes[result.kind];
auto style = styleForScopes(resultScupes).value_or(C_TEXT);
qCDebug(LOGLSPHIGHLIGHT) << result.line - 1 << '\t'
<< result.column - 1 << '\t'
<< result.length << '\t'
<< TextEditor::Constants::nameForStyle(style) << '\t'
<< text
<< resultScupes;
}
}
if (capabilities.semanticHighlighting().has_value()) {
SemanticHighlighter::setExtraAdditionalFormats(
doc->syntaxHighlighter(),
results,
scopesToFormatHash(highlightScopes(capabilities), doc->fontSettings()));
}
}
} // namespace SemanticHighligtingSupport
constexpr int tokenTypeBitOffset = 16;
SemanticTokenSupport::SemanticTokenSupport(Client *client)
@@ -258,6 +127,14 @@ void SemanticTokenSupport::updateSemanticTokens(TextDocument *textDocument)
reloadSemanticTokens(textDocument);
}
void SemanticTokenSupport::clearHighlight(TextEditor::TextDocument *doc)
{
if (m_tokens.contains(doc->filePath())){
if (TextEditor::SyntaxHighlighter *highlighter = doc->syntaxHighlighter())
highlighter->clearAllExtraFormats();
}
}
void SemanticTokenSupport::rehighlight()
{
for (const Utils::FilePath &filePath : m_tokens.keys())

View File

@@ -58,17 +58,6 @@ inline bool operator==(const ExpandedSemanticToken &t1, const ExpandedSemanticTo
using SemanticTokensHandler = std::function<void(TextEditor::TextDocument *,
const QList<ExpandedSemanticToken> &, int, bool)>;
namespace SemanticHighligtingSupport {
TextEditor::HighlightingResults generateResults(
const QList<LanguageServerProtocol::SemanticHighlightingInformation> &lines);
void applyHighlight(TextEditor::TextDocument *doc,
const TextEditor::HighlightingResults &results,
const LanguageServerProtocol::ServerCapabilities &capabilities);
} // namespace SemanticHighligtingSupport
class SemanticTokenSupport : public QObject
{
public:
@@ -77,6 +66,7 @@ public:
void refresh();
void reloadSemanticTokens(TextEditor::TextDocument *doc);
void updateSemanticTokens(TextEditor::TextDocument *doc);
void clearHighlight(TextEditor::TextDocument *doc);
void rehighlight();
void setLegend(const LanguageServerProtocol::SemanticTokensLegend &legend);