Commit 034defad authored by Simon Zünd's avatar Simon Zünd Committed by Commit Bot

[torque-ls] Add boilerplate for DocumentSymbol requests and responses

DocumentSymbol responses provide all symbols (macros, classes, etc.)
in a given document. The LSP standard evolved over time and supports
two different kind of responses here:
  - A simpler one, that is a plain list of all the symbols
  - A more detailed one, allowing a hierarchy of symbols. For example
    a class symbol has a list of field/method symbols attached. This
    is used by editors to build hierarchical outline views.

For now, the simpler response is chosen as its also used for
workspace wide symbol searches.

This CL adds the necessary boilerplate so the actual implementation CL
is easier to review.

R=tebbi@chromium.org

Bug: v8:8880
Change-Id: I6c86fc839b1f4e0309f6403a5f9afd5c162c0e89
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1598757
Auto-Submit: Simon Zünd <szuend@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61294}
parent 0f706761
......@@ -198,6 +198,7 @@ void HandleInitializeRequest(InitializeRequest request, MessageWriter writer) {
response.set_id(request.id());
response.result().capabilities().textDocumentSync();
response.result().capabilities().set_definitionProvider(true);
response.result().capabilities().set_documentSymbolProvider(true);
// TODO(szuend): Register for document synchronisation here,
// so we work with the content that the client
......@@ -291,6 +292,20 @@ void HandleChangeWatchedFilesNotification(
RecompileTorqueWithDiagnostics(writer);
}
void HandleDocumentSymbolRequest(DocumentSymbolRequest request,
MessageWriter writer) {
DocumentSymbolResponse response;
response.set_id(request.id());
// TODO(szuend): Convert declarables and other symbols into SymbolInformation
// objects here.
// Trigger empty array creation in case no symbols were found.
USE(response.result_size());
writer(response.GetJsonValue());
}
} // namespace
void HandleMessage(JsonValue& raw_message, MessageWriter writer) {
......@@ -319,6 +334,9 @@ void HandleMessage(JsonValue& raw_message, MessageWriter writer) {
} else if (method == "workspace/didChangeWatchedFiles") {
HandleChangeWatchedFilesNotification(
DidChangeWatchedFilesNotification(request.GetJsonValue()), writer);
} else if (method == "textDocument/documentSymbol") {
HandleDocumentSymbolRequest(DocumentSymbolRequest(request.GetJsonValue()),
writer);
} else {
Logger::Log("[error] Message of type ", method, " is not handled!\n\n");
}
......
......@@ -190,6 +190,7 @@ class ServerCapabilities : public NestedJsonAccessor {
JSON_OBJECT_ACCESSORS(TextDocumentSyncOptions, textDocumentSync)
JSON_BOOL_ACCESSORS(definitionProvider)
JSON_BOOL_ACCESSORS(documentSymbolProvider)
};
class InitializeResult : public NestedJsonAccessor {
......@@ -279,6 +280,37 @@ class PublishDiagnosticsParams : public NestedJsonAccessor {
JSON_ARRAY_OBJECT_ACCESSORS(Diagnostic, diagnostics)
};
enum SymbolKind {
kFile = 1,
kNamespace = 3,
kClass = 5,
kMethod = 6,
kProperty = 7,
kField = 8,
kConstructor = 9,
kFunction = 12,
kVariable = 13,
kConstant = 14,
kStruct = 23,
};
class DocumentSymbolParams : public NestedJsonAccessor {
public:
using NestedJsonAccessor::NestedJsonAccessor;
JSON_OBJECT_ACCESSORS(TextDocumentIdentifier, textDocument)
};
class SymbolInformation : public NestedJsonAccessor {
public:
using NestedJsonAccessor::NestedJsonAccessor;
JSON_STRING_ACCESSORS(name)
JSON_INT_ACCESSORS(kind)
JSON_OBJECT_ACCESSORS(Location, location)
JSON_STRING_ACCESSORS(containerName)
};
template <class T>
class Request : public Message {
public:
......@@ -295,6 +327,7 @@ using TorqueFileListNotification = Request<FileListParams>;
using GotoDefinitionRequest = Request<TextDocumentPositionParams>;
using DidChangeWatchedFilesNotification = Request<DidChangeWatchedFilesParams>;
using PublishDiagnosticsNotification = Request<PublishDiagnosticsParams>;
using DocumentSymbolRequest = Request<DocumentSymbolParams>;
template <class T>
class Response : public Message {
......@@ -309,6 +342,19 @@ class Response : public Message {
using InitializeResponse = Response<InitializeResult>;
using GotoDefinitionResponse = Response<Location>;
// Same as "Response" but the result is T[] instead of T.
template <class T>
class ResponseArrayResult : public Message {
public:
explicit ResponseArrayResult(JsonValue& value) : Message(value) {}
ResponseArrayResult() : Message() {}
JSON_INT_ACCESSORS(id)
JSON_OBJECT_ACCESSORS(ResponseError, error)
JSON_ARRAY_OBJECT_ACCESSORS(T, result)
};
using DocumentSymbolResponse = ResponseArrayResult<SymbolInformation>;
} // namespace ls
} // namespace torque
} // namespace internal
......
......@@ -26,7 +26,8 @@ TEST(LanguageServerMessage, InitializeRequest) {
// Check that the response id matches up with the request id, and that
// the language server signals its support for definitions.
EXPECT_EQ(response.id(), 5);
EXPECT_EQ(response.result().capabilities().definitionProvider(), true);
EXPECT_TRUE(response.result().capabilities().definitionProvider());
EXPECT_TRUE(response.result().capabilities().documentSymbolProvider());
});
}
......@@ -179,6 +180,20 @@ TEST(LanguageServerMessage, CleanCompileSendsNoDiagnostics) {
});
}
TEST(LanguageServerMessage, NoSymbolsSendsEmptyResponse) {
LanguageServerData::Scope server_data_scope;
DocumentSymbolRequest request;
request.set_id(42);
request.set_method("textDocument/documentSymbol");
HandleMessage(request.GetJsonValue(), [](JsonValue& raw_response) {
DocumentSymbolResponse response(raw_response);
EXPECT_EQ(response.id(), 42);
EXPECT_EQ(response.result_size(), static_cast<size_t>(0));
});
}
} // namespace ls
} // namespace torque
} // namespace internal
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment