Line data Source code
1 : // Copyright 2019 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_TORQUE_LS_MESSAGE_H_
6 : #define V8_TORQUE_LS_MESSAGE_H_
7 :
8 : #include "src/base/logging.h"
9 : #include "src/torque/ls/json.h"
10 : #include "src/torque/ls/message-macros.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 : namespace torque {
15 : namespace ls {
16 :
17 : // Base class for Messages and Objects that are backed by either a
18 : // JsonValue or a reference to a JsonObject.
19 : // Helper methods are used by macros to implement typed accessors.
20 84 : class BaseJsonAccessor {
21 : public:
22 : template <class T>
23 : T GetObject(const std::string& property) {
24 57 : return T(GetObjectProperty(property));
25 : }
26 :
27 3 : bool HasProperty(const std::string& property) const {
28 6 : return object().count(property) > 0;
29 : }
30 :
31 2 : void SetNull(const std::string& property) {
32 2 : object()[property] = JsonValue::JsonNull();
33 2 : }
34 :
35 3 : bool IsNull(const std::string& property) const {
36 6 : return HasProperty(property) &&
37 6 : object().at(property).tag == JsonValue::IS_NULL;
38 : }
39 :
40 : protected:
41 : virtual const JsonObject& object() const = 0;
42 : virtual JsonObject& object() = 0;
43 :
44 57 : JsonObject& GetObjectProperty(const std::string& property) {
45 114 : if (!object()[property].IsObject()) {
46 36 : object()[property] = JsonValue::From(JsonObject{});
47 : }
48 57 : return object()[property].ToObject();
49 : }
50 :
51 6 : JsonArray& GetArrayProperty(const std::string& property) {
52 12 : if (!object()[property].IsArray()) {
53 2 : object()[property] = JsonValue::From(JsonArray{});
54 : }
55 6 : return object()[property].ToArray();
56 : }
57 :
58 2 : JsonObject& AddObjectElementToArrayProperty(const std::string& property) {
59 2 : JsonArray& array = GetArrayProperty(property);
60 6 : array.push_back(JsonValue::From(JsonObject{}));
61 :
62 2 : return array.back().ToObject();
63 : }
64 : };
65 :
66 : // Base class for Requests, Responses and Notifications.
67 : // In contrast to "BaseObject", a Message owns the backing JsonValue of the
68 : // whole object tree; i.e. value_ serves as root.
69 25 : class Message : public BaseJsonAccessor {
70 : public:
71 20 : Message() {
72 20 : value_ = JsonValue::From(JsonObject{});
73 20 : set_jsonrpc("2.0");
74 10 : }
75 28 : explicit Message(JsonValue& value) : value_(std::move(value)) {
76 14 : CHECK(value_.tag == JsonValue::OBJECT);
77 14 : }
78 :
79 : JsonValue& GetJsonValue() { return value_; }
80 :
81 30 : JSON_STRING_ACCESSORS(jsonrpc)
82 :
83 : protected:
84 30 : const JsonObject& object() const { return value_.ToObject(); }
85 82 : JsonObject& object() { return value_.ToObject(); }
86 :
87 : private:
88 : JsonValue value_;
89 : };
90 :
91 : // Base class for complex type that might be part of a Message.
92 : // Instead of creating theses directly, use the accessors on the
93 : // root Message or a parent object.
94 : class NestedJsonAccessor : public BaseJsonAccessor {
95 : public:
96 60 : explicit NestedJsonAccessor(JsonObject& object) : object_(object) {}
97 :
98 14 : const JsonObject& object() const { return object_; }
99 108 : JsonObject& object() { return object_; }
100 :
101 : private:
102 : JsonObject& object_;
103 : };
104 :
105 : class ResponseError : public NestedJsonAccessor {
106 : public:
107 : using NestedJsonAccessor::NestedJsonAccessor;
108 :
109 : JSON_INT_ACCESSORS(code)
110 : JSON_STRING_ACCESSORS(message)
111 : };
112 :
113 : class InitializeParams : public NestedJsonAccessor {
114 : public:
115 1 : using NestedJsonAccessor::NestedJsonAccessor;
116 :
117 : JSON_INT_ACCESSORS(processId)
118 : JSON_STRING_ACCESSORS(rootPath)
119 : JSON_STRING_ACCESSORS(rootUri)
120 : JSON_STRING_ACCESSORS(trace)
121 : };
122 :
123 : class FileListParams : public NestedJsonAccessor {
124 : public:
125 0 : using NestedJsonAccessor::NestedJsonAccessor;
126 :
127 : // TODO(szuend): Implement read accessor for string
128 : // arrays. "files" is managed directly.
129 : };
130 :
131 : class FileSystemWatcher : public NestedJsonAccessor {
132 : public:
133 1 : using NestedJsonAccessor::NestedJsonAccessor;
134 :
135 2 : JSON_STRING_ACCESSORS(globPattern)
136 3 : JSON_INT_ACCESSORS(kind)
137 :
138 : enum WatchKind {
139 : kCreate = 1,
140 : kChange = 2,
141 : kDelete = 4,
142 :
143 : kAll = kCreate | kChange | kDelete,
144 : };
145 : };
146 :
147 : class DidChangeWatchedFilesRegistrationOptions : public NestedJsonAccessor {
148 : public:
149 2 : using NestedJsonAccessor::NestedJsonAccessor;
150 :
151 5 : JSON_ARRAY_OBJECT_ACCESSORS(FileSystemWatcher, watchers)
152 : };
153 :
154 : class FileEvent : public NestedJsonAccessor {
155 : public:
156 : using NestedJsonAccessor::NestedJsonAccessor;
157 :
158 : JSON_STRING_ACCESSORS(uri)
159 : JSON_INT_ACCESSORS(type)
160 : };
161 :
162 : class DidChangeWatchedFilesParams : public NestedJsonAccessor {
163 : public:
164 : using NestedJsonAccessor::NestedJsonAccessor;
165 :
166 : JSON_ARRAY_OBJECT_ACCESSORS(FileEvent, changes)
167 : };
168 :
169 : class SaveOptions : public NestedJsonAccessor {
170 : public:
171 : using NestedJsonAccessor::NestedJsonAccessor;
172 :
173 : JSON_BOOL_ACCESSORS(includeText)
174 : };
175 :
176 : class TextDocumentSyncOptions : public NestedJsonAccessor {
177 : public:
178 1 : using NestedJsonAccessor::NestedJsonAccessor;
179 :
180 : JSON_BOOL_ACCESSORS(openClose)
181 : JSON_INT_ACCESSORS(change)
182 : JSON_BOOL_ACCESSORS(willSave)
183 : JSON_BOOL_ACCESSORS(willSaveWaitUntil)
184 : JSON_OBJECT_ACCESSORS(SaveOptions, save)
185 : };
186 :
187 : class ServerCapabilities : public NestedJsonAccessor {
188 : public:
189 3 : using NestedJsonAccessor::NestedJsonAccessor;
190 :
191 2 : JSON_OBJECT_ACCESSORS(TextDocumentSyncOptions, textDocumentSync)
192 5 : JSON_BOOL_ACCESSORS(definitionProvider)
193 : };
194 :
195 : class InitializeResult : public NestedJsonAccessor {
196 : public:
197 3 : using NestedJsonAccessor::NestedJsonAccessor;
198 :
199 6 : JSON_OBJECT_ACCESSORS(ServerCapabilities, capabilities)
200 : };
201 :
202 : class Registration : public NestedJsonAccessor {
203 : public:
204 2 : using NestedJsonAccessor::NestedJsonAccessor;
205 :
206 2 : JSON_STRING_ACCESSORS(id)
207 4 : JSON_STRING_ACCESSORS(method)
208 4 : JSON_DYNAMIC_OBJECT_ACCESSORS(registerOptions)
209 : };
210 :
211 : class RegistrationParams : public NestedJsonAccessor {
212 : public:
213 3 : using NestedJsonAccessor::NestedJsonAccessor;
214 :
215 10 : JSON_ARRAY_OBJECT_ACCESSORS(Registration, registrations)
216 : };
217 :
218 : class JsonPosition : public NestedJsonAccessor {
219 : public:
220 16 : using NestedJsonAccessor::NestedJsonAccessor;
221 :
222 24 : JSON_INT_ACCESSORS(line)
223 24 : JSON_INT_ACCESSORS(character)
224 : };
225 :
226 : class Range : public NestedJsonAccessor {
227 : public:
228 5 : using NestedJsonAccessor::NestedJsonAccessor;
229 :
230 8 : JSON_OBJECT_ACCESSORS(JsonPosition, start)
231 8 : JSON_OBJECT_ACCESSORS(JsonPosition, end)
232 : };
233 :
234 : class Location : public NestedJsonAccessor {
235 : public:
236 3 : using NestedJsonAccessor::NestedJsonAccessor;
237 :
238 4 : JSON_STRING_ACCESSORS(uri)
239 10 : JSON_OBJECT_ACCESSORS(Range, range)
240 : };
241 :
242 : class TextDocumentIdentifier : public NestedJsonAccessor {
243 : public:
244 6 : using NestedJsonAccessor::NestedJsonAccessor;
245 :
246 15 : JSON_STRING_ACCESSORS(uri)
247 : };
248 :
249 : class TextDocumentPositionParams : public NestedJsonAccessor {
250 : public:
251 14 : using NestedJsonAccessor::NestedJsonAccessor;
252 :
253 12 : JSON_OBJECT_ACCESSORS(TextDocumentIdentifier, textDocument)
254 16 : JSON_OBJECT_ACCESSORS(JsonPosition, position)
255 : };
256 :
257 : template <class T>
258 32 : class Request : public Message {
259 : public:
260 10 : explicit Request(JsonValue& value) : Message(value) {}
261 6 : Request() : Message() {}
262 :
263 27 : JSON_INT_ACCESSORS(id)
264 44 : JSON_STRING_ACCESSORS(method)
265 36 : JSON_OBJECT_ACCESSORS(T, params)
266 : };
267 : using InitializeRequest = Request<InitializeParams>;
268 : using RegistrationRequest = Request<RegistrationParams>;
269 : using TorqueFileListNotification = Request<FileListParams>;
270 : using GotoDefinitionRequest = Request<TextDocumentPositionParams>;
271 : using DidChangeWatchedFilesNotification = Request<DidChangeWatchedFilesParams>;
272 :
273 : template <class T>
274 15 : class Response : public Message {
275 : public:
276 4 : explicit Response(JsonValue& value) : Message(value) {}
277 4 : Response() : Message() {}
278 :
279 24 : JSON_INT_ACCESSORS(id)
280 : JSON_OBJECT_ACCESSORS(ResponseError, error)
281 12 : JSON_OBJECT_ACCESSORS(T, result)
282 : };
283 : using InitializeResponse = Response<InitializeResult>;
284 : using GotoDefinitionResponse = Response<Location>;
285 :
286 : } // namespace ls
287 : } // namespace torque
288 : } // namespace internal
289 : } // namespace v8
290 :
291 : #endif // V8_TORQUE_LS_MESSAGE_H_
|