Skip to content

Commit ca3af4b

Browse files
committed
LSP: Implement semantic tokens
1 parent f629f9e commit ca3af4b

File tree

10 files changed

+698
-0
lines changed

10 files changed

+698
-0
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Language Features:
44

55

66
Compiler Features:
7+
* LSP: Add rudimentary support for semantic highlighting.
78

89

910
Bugfixes:

libsolidity/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ set(sources
163163
lsp/HandlerBase.h
164164
lsp/LanguageServer.cpp
165165
lsp/LanguageServer.h
166+
lsp/SemanticTokensBuilder.cpp
167+
lsp/SemanticTokensBuilder.h
166168
lsp/Transport.cpp
167169
lsp/Transport.h
168170
lsp/Utils.cpp

libsolidity/lsp/LanguageServer.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
// LSP feature implementations
2828
#include <libsolidity/lsp/GotoDefinition.h>
29+
#include <libsolidity/lsp/SemanticTokensBuilder.h>
2930

3031
#include <liblangutil/SourceReferenceExtractor.h>
3132
#include <liblangutil/CharStream.h>
@@ -64,6 +65,49 @@ int toDiagnosticSeverity(Error::Type _errorType)
6465
return -1;
6566
}
6667

68+
Json::Value semanticTokensLegend()
69+
{
70+
Json::Value legend = Json::objectValue;
71+
72+
// NOTE! The (alphabetical) order and items must match exactly the items of
73+
// their respective enum class members.
74+
75+
Json::Value tokenTypes = Json::arrayValue;
76+
tokenTypes.append("class");
77+
tokenTypes.append("comment");
78+
tokenTypes.append("enum");
79+
tokenTypes.append("enumMember");
80+
tokenTypes.append("event");
81+
tokenTypes.append("function");
82+
tokenTypes.append("interface");
83+
tokenTypes.append("keyword");
84+
tokenTypes.append("macro");
85+
tokenTypes.append("method");
86+
tokenTypes.append("modifier");
87+
tokenTypes.append("number");
88+
tokenTypes.append("operator");
89+
tokenTypes.append("parameter");
90+
tokenTypes.append("property");
91+
tokenTypes.append("string");
92+
tokenTypes.append("struct");
93+
tokenTypes.append("type");
94+
tokenTypes.append("typeParameter");
95+
tokenTypes.append("variable");
96+
legend["tokenTypes"] = tokenTypes;
97+
98+
Json::Value tokenModifiers = Json::arrayValue;
99+
tokenModifiers.append("abstract");
100+
tokenModifiers.append("declaration");
101+
tokenModifiers.append("definition");
102+
tokenModifiers.append("deprecated");
103+
tokenModifiers.append("documentation");
104+
tokenModifiers.append("modification");
105+
tokenModifiers.append("readonly");
106+
legend["tokenModifiers"] = tokenModifiers;
107+
108+
return legend;
109+
}
110+
67111
}
68112

69113
LanguageServer::LanguageServer(Transport& _transport):
@@ -81,6 +125,7 @@ LanguageServer::LanguageServer(Transport& _transport):
81125
{"textDocument/didChange", bind(&LanguageServer::handleTextDocumentDidChange, this, _2)},
82126
{"textDocument/didClose", bind(&LanguageServer::handleTextDocumentDidClose, this, _2)},
83127
{"textDocument/implementation", GotoDefinition(*this) },
128+
{"textDocument/semanticTokens/full", bind(&LanguageServer::semanticTokensFull, this, _1, _2)},
84129
{"workspace/didChangeConfiguration", bind(&LanguageServer::handleWorkspaceDidChangeConfiguration, this, _2)},
85130
},
86131
m_fileRepository("/" /* basePath */),
@@ -266,10 +311,30 @@ void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args)
266311
replyArgs["capabilities"]["implementationProvider"] = true;
267312
replyArgs["capabilities"]["textDocumentSync"]["change"] = 2; // 0=none, 1=full, 2=incremental
268313
replyArgs["capabilities"]["textDocumentSync"]["openClose"] = true;
314+
replyArgs["capabilities"]["semanticTokensProvider"]["legend"] = semanticTokensLegend();
315+
replyArgs["capabilities"]["semanticTokensProvider"]["range"] = false;
316+
replyArgs["capabilities"]["semanticTokensProvider"]["full"] = true; // XOR requests.full.delta = true
269317

270318
m_client.reply(_id, move(replyArgs));
271319
}
272320

321+
void LanguageServer::semanticTokensFull(MessageID _id, Json::Value const& _args)
322+
{
323+
auto uri = _args["textDocument"]["uri"];
324+
325+
compile();
326+
327+
auto const sourceName = m_fileRepository.uriToSourceUnitName(uri.as<string>());
328+
SourceUnit const& ast = m_compilerStack.ast(sourceName);
329+
m_compilerStack.charStream(sourceName);
330+
Json::Value data = SemanticTokensBuilder().build(ast, m_compilerStack.charStream(sourceName));
331+
332+
Json::Value reply = Json::objectValue;
333+
reply["data"] = data;
334+
335+
m_client.reply(_id, std::move(reply));
336+
}
337+
273338
void LanguageServer::handleWorkspaceDidChangeConfiguration(Json::Value const& _args)
274339
{
275340
requireServerInitialized();

libsolidity/lsp/LanguageServer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class LanguageServer
7373
void handleTextDocumentDidChange(Json::Value const& _args);
7474
void handleTextDocumentDidClose(Json::Value const& _args);
7575
void handleGotoDefinition(MessageID _id, Json::Value const& _args);
76+
void semanticTokensFull(MessageID _id, Json::Value const& _args);
7677

7778
/// Invoked when the server user-supplied configuration changes (initiated by the client).
7879
void changeConfiguration(Json::Value const&);

0 commit comments

Comments
 (0)