forked from qt-creator/qt-creator
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:
@@ -195,25 +195,6 @@ public:
|
|||||||
{ insert(synchronizationKey, synchronization); }
|
{ insert(synchronizationKey, synchronization); }
|
||||||
void clearSynchronization() { remove(synchronizationKey); }
|
void clearSynchronization() { remove(synchronizationKey); }
|
||||||
|
|
||||||
class LANGUAGESERVERPROTOCOL_EXPORT SemanticHighlightingCapabilities : public JsonObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using JsonObject::JsonObject;
|
|
||||||
|
|
||||||
bool semanticHighlighting() const { return typedValue<bool>(semanticHighlightingKey); }
|
|
||||||
void setSemanticHighlighting(bool semanticHighlighting)
|
|
||||||
{ insert(semanticHighlightingKey, semanticHighlighting); }
|
|
||||||
|
|
||||||
bool isValid() const override { return contains(semanticHighlightingKey); }
|
|
||||||
};
|
|
||||||
|
|
||||||
Utils::optional<SemanticHighlightingCapabilities> semanticHighlightingCapabilities() const
|
|
||||||
{ return optionalValue<SemanticHighlightingCapabilities>(semanticHighlightingCapabilitiesKey); }
|
|
||||||
void setSemanticHighlightingCapabilities(
|
|
||||||
const SemanticHighlightingCapabilities &semanticHighlightingCapabilities)
|
|
||||||
{ insert(semanticHighlightingCapabilitiesKey, semanticHighlightingCapabilities); }
|
|
||||||
void clearSemanticHighlightingCapabilities() { remove(semanticHighlightingCapabilitiesKey); }
|
|
||||||
|
|
||||||
class LANGUAGESERVERPROTOCOL_EXPORT CompletionCapabilities : public DynamicRegistrationCapabilities
|
class LANGUAGESERVERPROTOCOL_EXPORT CompletionCapabilities : public DynamicRegistrationCapabilities
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@@ -187,11 +187,8 @@ constexpr char rootUriKey[] = "rootUri";
|
|||||||
constexpr char saveKey[] = "save";
|
constexpr char saveKey[] = "save";
|
||||||
constexpr char schemeKey[] = "scheme";
|
constexpr char schemeKey[] = "scheme";
|
||||||
constexpr char scopeUriKey[] = "scopeUri";
|
constexpr char scopeUriKey[] = "scopeUri";
|
||||||
constexpr char scopesKey[] = "scopes";
|
|
||||||
constexpr char sectionKey[] = "section";
|
constexpr char sectionKey[] = "section";
|
||||||
constexpr char selectionRangeKey[] = "selectionRange";
|
constexpr char selectionRangeKey[] = "selectionRange";
|
||||||
constexpr char semanticHighlightingCapabilitiesKey[] = "semanticHighlightingCapabilities";
|
|
||||||
constexpr char semanticHighlightingKey[] = "semanticHighlighting";
|
|
||||||
constexpr char semanticTokensKey[] = "semanticTokens";
|
constexpr char semanticTokensKey[] = "semanticTokens";
|
||||||
constexpr char semanticTokensProviderKey[] = "semanticTokensProvider";
|
constexpr char semanticTokensProviderKey[] = "semanticTokensProvider";
|
||||||
constexpr char serverInfoKey[] = "serverInfo";
|
constexpr char serverInfoKey[] = "serverInfo";
|
||||||
@@ -220,7 +217,6 @@ constexpr char titleKey[] = "title";
|
|||||||
constexpr char tokenKey[] = "token";
|
constexpr char tokenKey[] = "token";
|
||||||
constexpr char tokenModifiersKey[] = "tokenModifiers";
|
constexpr char tokenModifiersKey[] = "tokenModifiers";
|
||||||
constexpr char tokenTypesKey[] = "tokenTypes";
|
constexpr char tokenTypesKey[] = "tokenTypes";
|
||||||
constexpr char tokensKey[] = "tokens";
|
|
||||||
constexpr char traceKey[] = "trace";
|
constexpr char traceKey[] = "trace";
|
||||||
constexpr char triggerCharacterKey[] = "triggerCharacter";
|
constexpr char triggerCharacterKey[] = "triggerCharacter";
|
||||||
constexpr char triggerCharactersKey[] = "triggerCharacters";
|
constexpr char triggerCharactersKey[] = "triggerCharacters";
|
||||||
|
@@ -48,7 +48,6 @@ constexpr const char DocumentRangeFormattingRequest::methodName[];
|
|||||||
constexpr const char DocumentOnTypeFormattingRequest::methodName[];
|
constexpr const char DocumentOnTypeFormattingRequest::methodName[];
|
||||||
constexpr const char RenameRequest::methodName[];
|
constexpr const char RenameRequest::methodName[];
|
||||||
constexpr const char SignatureHelpRequest::methodName[];
|
constexpr const char SignatureHelpRequest::methodName[];
|
||||||
constexpr const char SemanticHighlightNotification::methodName[];
|
|
||||||
constexpr const char PrepareRenameRequest::methodName[];
|
constexpr const char PrepareRenameRequest::methodName[];
|
||||||
|
|
||||||
HoverContent LanguageServerProtocol::Hover::content() const
|
HoverContent LanguageServerProtocol::Hover::content() const
|
||||||
@@ -369,63 +368,6 @@ CodeActionResult::CodeActionResult(const QJsonValue &val)
|
|||||||
emplace<std::nullptr_t>(nullptr);
|
emplace<std::nullptr_t>(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::optional<QList<SemanticHighlightToken>> SemanticHighlightingInformation::tokens() const
|
|
||||||
{
|
|
||||||
QList<SemanticHighlightToken> resultTokens;
|
|
||||||
|
|
||||||
const QByteArray tokensByteArray = QByteArray::fromBase64(
|
|
||||||
typedValue<QString>(tokensKey).toLocal8Bit());
|
|
||||||
constexpr int tokensByteSize = 8;
|
|
||||||
int index = 0;
|
|
||||||
while (index + tokensByteSize <= tokensByteArray.size()) {
|
|
||||||
resultTokens << SemanticHighlightToken(tokensByteArray.mid(index, tokensByteSize));
|
|
||||||
index += tokensByteSize;
|
|
||||||
}
|
|
||||||
return Utils::make_optional(resultTokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SemanticHighlightingInformation::setTokens(const QList<SemanticHighlightToken> &tokens)
|
|
||||||
{
|
|
||||||
QByteArray byteArray;
|
|
||||||
byteArray.reserve(8 * tokens.size());
|
|
||||||
for (const SemanticHighlightToken &token : tokens)
|
|
||||||
token.appendToByteArray(byteArray);
|
|
||||||
insert(tokensKey, QString::fromLocal8Bit(byteArray.toBase64()));
|
|
||||||
}
|
|
||||||
|
|
||||||
SemanticHighlightToken::SemanticHighlightToken(const QByteArray &token)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(token.size() == 8, return );
|
|
||||||
character = ( quint32(token.at(0)) << 24
|
|
||||||
| quint32(token.at(1)) << 16
|
|
||||||
| quint32(token.at(2)) << 8
|
|
||||||
| quint32(token.at(3)));
|
|
||||||
|
|
||||||
length = quint16(token.at(4) << 8 | token.at(5));
|
|
||||||
|
|
||||||
scope = quint16(token.at(6) << 8 | token.at(7));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SemanticHighlightToken::appendToByteArray(QByteArray &byteArray) const
|
|
||||||
{
|
|
||||||
byteArray.append(char((character & 0xff000000) >> 24));
|
|
||||||
byteArray.append(char((character & 0x00ff0000) >> 16));
|
|
||||||
byteArray.append(char((character & 0x0000ff00) >> 8));
|
|
||||||
byteArray.append(char((character & 0x000000ff)));
|
|
||||||
byteArray.append(char((length & 0xff00) >> 8));
|
|
||||||
byteArray.append(char((length & 0x00ff)));
|
|
||||||
byteArray.append(char((scope & 0xff00) >> 8));
|
|
||||||
byteArray.append(char((scope & 0x00ff)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils::variant<VersionedTextDocumentIdentifier, TextDocumentIdentifier>
|
|
||||||
SemanticHighlightingParams::textDocument() const
|
|
||||||
{
|
|
||||||
VersionedTextDocumentIdentifier textDocument = fromJsonValue<VersionedTextDocumentIdentifier>(
|
|
||||||
value(textDocumentKey));
|
|
||||||
return textDocument.isValid() ? textDocument : TextDocumentIdentifier(textDocument);
|
|
||||||
}
|
|
||||||
|
|
||||||
PrepareRenameResult::PrepareRenameResult()
|
PrepareRenameResult::PrepareRenameResult()
|
||||||
: Utils::variant<PlaceHolderResult, Range, std::nullptr_t>(nullptr)
|
: Utils::variant<PlaceHolderResult, Range, std::nullptr_t>(nullptr)
|
||||||
{}
|
{}
|
||||||
@@ -457,10 +399,6 @@ PrepareRenameResult::PrepareRenameResult(const QJsonValue &val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SemanticHighlightNotification::SemanticHighlightNotification(const SemanticHighlightingParams ¶ms)
|
|
||||||
: Notification(methodName, params)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Utils::optional<QJsonValue> CodeLens::data() const
|
Utils::optional<QJsonValue> CodeLens::data() const
|
||||||
{
|
{
|
||||||
return contains(dataKey) ? Utils::make_optional(value(dataKey)) : Utils::nullopt;
|
return contains(dataKey) ? Utils::make_optional(value(dataKey)) : Utils::nullopt;
|
||||||
|
@@ -846,61 +846,4 @@ public:
|
|||||||
constexpr static const char methodName[] = "textDocument/rename";
|
constexpr static const char methodName[] = "textDocument/rename";
|
||||||
};
|
};
|
||||||
|
|
||||||
class LANGUAGESERVERPROTOCOL_EXPORT SemanticHighlightToken
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Just accepts token with 8 bytes
|
|
||||||
explicit SemanticHighlightToken(const QByteArray &token);
|
|
||||||
SemanticHighlightToken() = default;
|
|
||||||
|
|
||||||
void appendToByteArray(QByteArray &byteArray) const;
|
|
||||||
|
|
||||||
quint32 character = 0;
|
|
||||||
quint16 length = 0;
|
|
||||||
quint16 scope = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LANGUAGESERVERPROTOCOL_EXPORT SemanticHighlightingInformation : public JsonObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using JsonObject::JsonObject;
|
|
||||||
|
|
||||||
int line() const { return typedValue<int>(lineKey); }
|
|
||||||
void setLine(int line) { insert(lineKey, line); }
|
|
||||||
|
|
||||||
Utils::optional<QList<SemanticHighlightToken>> tokens() const;
|
|
||||||
void setTokens(const QList<SemanticHighlightToken> &tokens);
|
|
||||||
void clearTokens() { remove(tokensKey); }
|
|
||||||
|
|
||||||
bool isValid() const override { return contains(lineKey); }
|
|
||||||
};
|
|
||||||
|
|
||||||
class LANGUAGESERVERPROTOCOL_EXPORT SemanticHighlightingParams : public JsonObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using JsonObject::JsonObject;
|
|
||||||
|
|
||||||
Utils::variant<VersionedTextDocumentIdentifier, TextDocumentIdentifier> textDocument() const;
|
|
||||||
void setTextDocument(const TextDocumentIdentifier &textDocument)
|
|
||||||
{ insert(textDocumentKey, textDocument); }
|
|
||||||
void setTextDocument(const VersionedTextDocumentIdentifier &textDocument)
|
|
||||||
{ insert(textDocumentKey, textDocument); }
|
|
||||||
|
|
||||||
QList<SemanticHighlightingInformation> lines() const
|
|
||||||
{ return array<SemanticHighlightingInformation>(linesKey); }
|
|
||||||
void setLines(const QList<SemanticHighlightingInformation> &lines)
|
|
||||||
{ insertArray(linesKey, lines); }
|
|
||||||
|
|
||||||
bool isValid() const override { return contains(textDocumentKey) && contains(linesKey); }
|
|
||||||
};
|
|
||||||
|
|
||||||
class LANGUAGESERVERPROTOCOL_EXPORT SemanticHighlightNotification
|
|
||||||
: public Notification<SemanticHighlightingParams>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit SemanticHighlightNotification(const SemanticHighlightingParams ¶ms);
|
|
||||||
using Notification::Notification;
|
|
||||||
constexpr static const char methodName[] = "textDocument/semanticHighlighting";
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace LanguageClient
|
} // namespace LanguageClient
|
||||||
|
@@ -306,50 +306,6 @@ bool TextDocumentRegistrationOptions::filterApplies(const Utils::FilePath &fileN
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::optional<QList<QList<QString>>> ServerCapabilities::SemanticHighlightingServerCapabilities::scopes() const
|
|
||||||
{
|
|
||||||
QList<QList<QString>> scopes;
|
|
||||||
if (!contains(scopesKey))
|
|
||||||
return Utils::nullopt;
|
|
||||||
for (const QJsonValue jsonScopeValue : value(scopesKey).toArray()) {
|
|
||||||
if (!jsonScopeValue.isArray())
|
|
||||||
return {};
|
|
||||||
QList<QString> scope;
|
|
||||||
for (const QJsonValue value : jsonScopeValue.toArray()) {
|
|
||||||
if (!value.isString())
|
|
||||||
return {};
|
|
||||||
scope.append(value.toString());
|
|
||||||
}
|
|
||||||
scopes.append(scope);
|
|
||||||
}
|
|
||||||
return Utils::make_optional(scopes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerCapabilities::SemanticHighlightingServerCapabilities::setScopes(
|
|
||||||
const QList<QList<QString>> &scopes)
|
|
||||||
{
|
|
||||||
QJsonArray jsonScopes;
|
|
||||||
for (const QList<QString> &scope : scopes) {
|
|
||||||
QJsonArray jsonScope;
|
|
||||||
for (const QString &value : scope)
|
|
||||||
jsonScope.append(value);
|
|
||||||
jsonScopes.append(jsonScope);
|
|
||||||
}
|
|
||||||
insert(scopesKey, jsonScopes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ServerCapabilities::SemanticHighlightingServerCapabilities::isValid() const
|
|
||||||
{
|
|
||||||
return contains(scopesKey) && value(scopesKey).isArray()
|
|
||||||
&& Utils::allOf(value(scopesKey).toArray(), [](const QJsonValue &array) {
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
return array.isArray() && Utils::allOf(array.toArray(), &QJsonValue::isString);
|
|
||||||
#else
|
|
||||||
return array.isArray() && Utils::allOf(array.toArray(), &QJsonValueRef::isString);
|
|
||||||
#endif
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ServerCapabilities::ExecuteCommandOptions::isValid() const
|
bool ServerCapabilities::ExecuteCommandOptions::isValid() const
|
||||||
{
|
{
|
||||||
return WorkDoneProgressOptions::isValid() && contains(commandsKey);
|
return WorkDoneProgressOptions::isValid() && contains(commandsKey);
|
||||||
|
@@ -263,17 +263,6 @@ public:
|
|||||||
void clearId() { remove(idKey); }
|
void clearId() { remove(idKey); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class LANGUAGESERVERPROTOCOL_EXPORT SemanticHighlightingServerCapabilities : public JsonObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using JsonObject::JsonObject;
|
|
||||||
|
|
||||||
Utils::optional<QList<QList<QString>>> scopes() const;
|
|
||||||
void setScopes(const QList<QList<QString>> &scopes);
|
|
||||||
|
|
||||||
bool isValid() const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Defines how text documents are synced. Is either a detailed structure defining each
|
// Defines how text documents are synced. Is either a detailed structure defining each
|
||||||
// notification or for backwards compatibility the TextDocumentSyncKind number.
|
// notification or for backwards compatibility the TextDocumentSyncKind number.
|
||||||
using TextDocumentSync = Utils::variant<TextDocumentSyncOptions, int>;
|
using TextDocumentSync = Utils::variant<TextDocumentSyncOptions, int>;
|
||||||
@@ -463,12 +452,6 @@ public:
|
|||||||
Utils::optional<JsonObject> experimental() const { return optionalValue<JsonObject>(experimentalKey); }
|
Utils::optional<JsonObject> experimental() const { return optionalValue<JsonObject>(experimentalKey); }
|
||||||
void setExperimental(const JsonObject &experimental) { insert(experimentalKey, experimental); }
|
void setExperimental(const JsonObject &experimental) { insert(experimentalKey, experimental); }
|
||||||
void clearExperimental() { remove(experimentalKey); }
|
void clearExperimental() { remove(experimentalKey); }
|
||||||
|
|
||||||
Utils::optional<SemanticHighlightingServerCapabilities> semanticHighlighting() const
|
|
||||||
{ return optionalValue<SemanticHighlightingServerCapabilities>(semanticHighlightingKey); }
|
|
||||||
void setSemanticHighlighting(const SemanticHighlightingServerCapabilities &semanticHighlighting)
|
|
||||||
{ insert(semanticHighlightingKey, semanticHighlighting); }
|
|
||||||
void clearSemanticHighlighting() { remove(semanticHighlightingKey); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace LanguageClient
|
} // namespace LanguageClient
|
||||||
|
@@ -102,10 +102,6 @@ Client::Client(BaseClientInterface *clientInterface)
|
|||||||
connect(clientInterface, &BaseClientInterface::messageReceived, this, &Client::handleMessage);
|
connect(clientInterface, &BaseClientInterface::messageReceived, this, &Client::handleMessage);
|
||||||
connect(clientInterface, &BaseClientInterface::error, this, &Client::setError);
|
connect(clientInterface, &BaseClientInterface::error, this, &Client::setError);
|
||||||
connect(clientInterface, &BaseClientInterface::finished, this, &Client::finished);
|
connect(clientInterface, &BaseClientInterface::finished, this, &Client::finished);
|
||||||
connect(TextEditor::TextEditorSettings::instance(),
|
|
||||||
&TextEditor::TextEditorSettings::fontSettingsChanged,
|
|
||||||
this,
|
|
||||||
&Client::rehighlight);
|
|
||||||
|
|
||||||
m_tokenSupport.setTokenTypesMap(SemanticTokens::defaultTokenTypesMap());
|
m_tokenSupport.setTokenTypesMap(SemanticTokens::defaultTokenTypesMap());
|
||||||
m_tokenSupport.setTokenModifiersMap(SemanticTokens::defaultTokenModifiersMap());
|
m_tokenSupport.setTokenModifiersMap(SemanticTokens::defaultTokenModifiersMap());
|
||||||
@@ -142,13 +138,6 @@ Client::~Client()
|
|||||||
widget->removeHoverHandler(&m_hoverHandler);
|
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))
|
for (IAssistProcessor *processor : qAsConst(m_runningAssistProcessors))
|
||||||
processor->setAsyncProposalAvailable(nullptr);
|
processor->setAsyncProposalAvailable(nullptr);
|
||||||
qDeleteAll(m_documentHighlightsTimer);
|
qDeleteAll(m_documentHighlightsTimer);
|
||||||
@@ -199,10 +188,6 @@ static ClientCapabilities generateClientCapabilities()
|
|||||||
symbolCapabilities.setHierarchicalDocumentSymbolSupport(true);
|
symbolCapabilities.setHierarchicalDocumentSymbolSupport(true);
|
||||||
documentCapabilities.setDocumentSymbol(symbolCapabilities);
|
documentCapabilities.setDocumentSymbol(symbolCapabilities);
|
||||||
|
|
||||||
TextDocumentClientCapabilities::SemanticHighlightingCapabilities semanticHighlight;
|
|
||||||
semanticHighlight.setSemanticHighlighting(true);
|
|
||||||
documentCapabilities.setSemanticHighlightingCapabilities(semanticHighlight);
|
|
||||||
|
|
||||||
TextDocumentClientCapabilities::CompletionCapabilities completionCapabilities;
|
TextDocumentClientCapabilities::CompletionCapabilities completionCapabilities;
|
||||||
completionCapabilities.setDynamicRegistration(true);
|
completionCapabilities.setDynamicRegistration(true);
|
||||||
TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemKindCapabilities
|
TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemKindCapabilities
|
||||||
@@ -449,7 +434,6 @@ void Client::closeDocument(TextEditor::TextDocument *document)
|
|||||||
{
|
{
|
||||||
deactivateDocument(document);
|
deactivateDocument(document);
|
||||||
const DocumentUri &uri = DocumentUri::fromFilePath(document->filePath());
|
const DocumentUri &uri = DocumentUri::fromFilePath(document->filePath());
|
||||||
m_highlights[uri].clear();
|
|
||||||
m_postponedDocuments.remove(document);
|
m_postponedDocuments.remove(document);
|
||||||
if (m_openedDocument.remove(document) != 0) {
|
if (m_openedDocument.remove(document) != 0) {
|
||||||
handleDocumentClosed(document);
|
handleDocumentClosed(document);
|
||||||
@@ -580,7 +564,6 @@ void Client::activateDocument(TextEditor::TextDocument *document)
|
|||||||
const FilePath &filePath = document->filePath();
|
const FilePath &filePath = document->filePath();
|
||||||
auto uri = DocumentUri::fromFilePath(filePath);
|
auto uri = DocumentUri::fromFilePath(filePath);
|
||||||
m_diagnosticManager.showDiagnostics(uri, m_documentVersions.value(filePath));
|
m_diagnosticManager.showDiagnostics(uri, m_documentVersions.value(filePath));
|
||||||
SemanticHighligtingSupport::applyHighlight(document, m_highlights.value(uri), capabilities());
|
|
||||||
m_tokenSupport.updateSemanticTokens(document);
|
m_tokenSupport.updateSemanticTokens(document);
|
||||||
// only replace the assist provider if the language server support it
|
// only replace the assist provider if the language server support it
|
||||||
updateCompletionProvider(document);
|
updateCompletionProvider(document);
|
||||||
@@ -607,10 +590,7 @@ void Client::deactivateDocument(TextEditor::TextDocument *document)
|
|||||||
m_diagnosticManager.hideDiagnostics(document);
|
m_diagnosticManager.hideDiagnostics(document);
|
||||||
resetAssistProviders(document);
|
resetAssistProviders(document);
|
||||||
document->setFormatter(nullptr);
|
document->setFormatter(nullptr);
|
||||||
if (m_serverCapabilities.semanticHighlighting().has_value()) {
|
m_tokenSupport.clearHighlight(document);
|
||||||
if (TextEditor::SyntaxHighlighter *highlighter = document->syntaxHighlighter())
|
|
||||||
highlighter->clearAllExtraFormats();
|
|
||||||
}
|
|
||||||
for (Core::IEditor *editor : Core::DocumentModel::editorsForDocument(document)) {
|
for (Core::IEditor *editor : Core::DocumentModel::editorsForDocument(document)) {
|
||||||
if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor)) {
|
if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor)) {
|
||||||
TextEditor::TextEditorWidget *widget = textEditor->editorWidget();
|
TextEditor::TextEditorWidget *widget = textEditor->editorWidget();
|
||||||
@@ -1249,7 +1229,6 @@ void Client::sendPostponedDocumentUpdates(Schedule semanticTokensSchedule)
|
|||||||
TextEditor::TextDocument * const document = elem.first;
|
TextEditor::TextDocument * const document = elem.first;
|
||||||
const FilePath &filePath = document->filePath();
|
const FilePath &filePath = document->filePath();
|
||||||
const auto uri = DocumentUri::fromFilePath(filePath);
|
const auto uri = DocumentUri::fromFilePath(filePath);
|
||||||
m_highlights[uri].clear();
|
|
||||||
VersionedTextDocumentIdentifier docId(uri);
|
VersionedTextDocumentIdentifier docId(uri);
|
||||||
docId.setVersion(m_documentVersions[filePath]);
|
docId.setVersion(m_documentVersions[filePath]);
|
||||||
DidChangeTextDocumentParams params;
|
DidChangeTextDocumentParams params;
|
||||||
@@ -1327,12 +1306,6 @@ void Client::handleMethod(const QString &method, const MessageId &id, const ICon
|
|||||||
log(params);
|
log(params);
|
||||||
else
|
else
|
||||||
log(invalidParamsErrorMessage(params));
|
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) {
|
} else if (method == ShowMessageNotification::methodName) {
|
||||||
auto params = dynamic_cast<const ShowMessageNotification *>(content)->params().value_or(ShowMessageParams());
|
auto params = dynamic_cast<const ShowMessageNotification *>(content)->params().value_or(ShowMessageParams());
|
||||||
if (params.isValid())
|
if (params.isValid())
|
||||||
@@ -1457,48 +1430,6 @@ void Client::handleDiagnostics(const PublishDiagnosticsParams ¶ms)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::handleSemanticHighlight(const SemanticHighlightingParams ¶ms)
|
|
||||||
{
|
|
||||||
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
|
bool Client::documentUpdatePostponed(const Utils::FilePath &fileName) const
|
||||||
{
|
{
|
||||||
return Utils::contains(m_documentsToUpdate, [fileName](const auto &elem) {
|
return Utils::contains(m_documentsToUpdate, [fileName](const auto &elem) {
|
||||||
|
@@ -226,8 +226,6 @@ private:
|
|||||||
void handleMethod(const QString &method, const LanguageServerProtocol::MessageId &id,
|
void handleMethod(const QString &method, const LanguageServerProtocol::MessageId &id,
|
||||||
const LanguageServerProtocol::IContent *content);
|
const LanguageServerProtocol::IContent *content);
|
||||||
|
|
||||||
void handleSemanticHighlight(const LanguageServerProtocol::SemanticHighlightingParams ¶ms);
|
|
||||||
|
|
||||||
void initializeCallback(const LanguageServerProtocol::InitializeRequest::Response &initResponse);
|
void initializeCallback(const LanguageServerProtocol::InitializeRequest::Response &initResponse);
|
||||||
void shutDownCallback(const LanguageServerProtocol::ShutdownRequest::Response &shutdownResponse);
|
void shutDownCallback(const LanguageServerProtocol::ShutdownRequest::Response &shutdownResponse);
|
||||||
bool sendWorkspceFolderChanges() const;
|
bool sendWorkspceFolderChanges() const;
|
||||||
@@ -247,7 +245,6 @@ private:
|
|||||||
void requestDocumentHighlights(TextEditor::TextEditorWidget *widget);
|
void requestDocumentHighlights(TextEditor::TextEditorWidget *widget);
|
||||||
LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(TextEditor::TextDocument *document) const;
|
LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(TextEditor::TextDocument *document) const;
|
||||||
void handleSemanticTokens(const LanguageServerProtocol::SemanticTokens &tokens);
|
void handleSemanticTokens(const LanguageServerProtocol::SemanticTokens &tokens);
|
||||||
void rehighlight();
|
|
||||||
|
|
||||||
virtual void handleDocumentClosed(TextEditor::TextDocument *) {}
|
virtual void handleDocumentClosed(TextEditor::TextDocument *) {}
|
||||||
virtual void handleDocumentOpened(TextEditor::TextDocument *) {}
|
virtual void handleDocumentOpened(TextEditor::TextDocument *) {}
|
||||||
|
@@ -63,7 +63,6 @@ LanguageClientManager::LanguageClientManager(QObject *parent)
|
|||||||
using namespace Core;
|
using namespace Core;
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
JsonRpcMessageHandler::registerMessageProvider<PublishDiagnosticsNotification>();
|
JsonRpcMessageHandler::registerMessageProvider<PublishDiagnosticsNotification>();
|
||||||
JsonRpcMessageHandler::registerMessageProvider<SemanticHighlightNotification>();
|
|
||||||
JsonRpcMessageHandler::registerMessageProvider<ApplyWorkspaceEditRequest>();
|
JsonRpcMessageHandler::registerMessageProvider<ApplyWorkspaceEditRequest>();
|
||||||
JsonRpcMessageHandler::registerMessageProvider<LogMessageNotification>();
|
JsonRpcMessageHandler::registerMessageProvider<LogMessageNotification>();
|
||||||
JsonRpcMessageHandler::registerMessageProvider<ShowMessageRequest>();
|
JsonRpcMessageHandler::registerMessageProvider<ShowMessageRequest>();
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
#include "languageclientmanager.h"
|
#include "languageclientmanager.h"
|
||||||
|
|
||||||
#include <texteditor/fontsettings.h>
|
#include <texteditor/fontsettings.h>
|
||||||
|
#include <texteditor/syntaxhighlighter.h>
|
||||||
#include <texteditor/texteditor.h>
|
#include <texteditor/texteditor.h>
|
||||||
#include <texteditor/texteditorsettings.h>
|
#include <texteditor/texteditorsettings.h>
|
||||||
#include <utils/mimetypes/mimedatabase.h>
|
#include <utils/mimetypes/mimedatabase.h>
|
||||||
@@ -42,138 +43,6 @@ namespace LanguageClient {
|
|||||||
|
|
||||||
static Q_LOGGING_CATEGORY(LOGLSPHIGHLIGHT, "qtc.languageclient.highlight", QtWarningMsg);
|
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;
|
constexpr int tokenTypeBitOffset = 16;
|
||||||
|
|
||||||
SemanticTokenSupport::SemanticTokenSupport(Client *client)
|
SemanticTokenSupport::SemanticTokenSupport(Client *client)
|
||||||
@@ -258,6 +127,14 @@ void SemanticTokenSupport::updateSemanticTokens(TextDocument *textDocument)
|
|||||||
reloadSemanticTokens(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()
|
void SemanticTokenSupport::rehighlight()
|
||||||
{
|
{
|
||||||
for (const Utils::FilePath &filePath : m_tokens.keys())
|
for (const Utils::FilePath &filePath : m_tokens.keys())
|
||||||
|
@@ -58,17 +58,6 @@ inline bool operator==(const ExpandedSemanticToken &t1, const ExpandedSemanticTo
|
|||||||
using SemanticTokensHandler = std::function<void(TextEditor::TextDocument *,
|
using SemanticTokensHandler = std::function<void(TextEditor::TextDocument *,
|
||||||
const QList<ExpandedSemanticToken> &, int, bool)>;
|
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
|
class SemanticTokenSupport : public QObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -77,6 +66,7 @@ public:
|
|||||||
void refresh();
|
void refresh();
|
||||||
void reloadSemanticTokens(TextEditor::TextDocument *doc);
|
void reloadSemanticTokens(TextEditor::TextDocument *doc);
|
||||||
void updateSemanticTokens(TextEditor::TextDocument *doc);
|
void updateSemanticTokens(TextEditor::TextDocument *doc);
|
||||||
|
void clearHighlight(TextEditor::TextDocument *doc);
|
||||||
void rehighlight();
|
void rehighlight();
|
||||||
void setLegend(const LanguageServerProtocol::SemanticTokensLegend &legend);
|
void setLegend(const LanguageServerProtocol::SemanticTokensLegend &legend);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user