1 /*
2  *Copyright (C) 2018 Laurent Tréguier
3  *
4  *This file is part of DLS.
5  *
6  *DLS is free software: you can redistribute it and/or modify
7  *it under the terms of the GNU General Public License as published by
8  *the Free Software Foundation, either version 3 of the License, or
9  *(at your option) any later version.
10  *
11  *DLS is distributed in the hope that it will be useful,
12  *but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *GNU General Public License for more details.
15  *
16  *You should have received a copy of the GNU General Public License
17  *along with DLS.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 module dls.protocol.definitions;
22 
23 alias DocumentUri = string;
24 
25 class Position
26 {
27     size_t line;
28     size_t character;
29 
30     @safe this(size_t line = size_t.init, size_t character = size_t.init) pure nothrow
31     {
32         this.line = line;
33         this.character = character;
34     }
35 }
36 
37 class Range
38 {
39     Position start;
40     Position end;
41 
42     @safe this(Position start = new Position(), Position end = new Position()) pure nothrow
43     {
44         this.start = start;
45         this.end = end;
46     }
47 }
48 
49 class Location
50 {
51     DocumentUri uri;
52     Range range;
53 
54     @safe this(DocumentUri uri = DocumentUri.init, Range range = new Range()) pure nothrow
55     {
56         this.uri = uri;
57         this.range = range;
58     }
59 }
60 
61 class LocationLink
62 {
63     import dls.util.nullable : Nullable;
64 
65     Nullable!Range originSelectionRange;
66     DocumentUri targetUri;
67     Range targetRange;
68     Nullable!Range targetSelectionRange;
69 
70     @safe this(Nullable!Range originSelectionRange = Nullable!Range.init, DocumentUri targetUri = DocumentUri.init,
71             Range targetRange = new Range(),
72             Nullable!Range targetSelectionRange = Nullable!Range.init) pure nothrow
73     {
74         this.originSelectionRange = originSelectionRange;
75         this.targetUri = targetUri;
76         this.targetRange = targetRange;
77         this.targetSelectionRange = targetSelectionRange;
78     }
79 }
80 
81 class Diagnostic
82 {
83     import std.json : JSONValue;
84     import dls.util.nullable: Nullable;
85 
86     Range range;
87     string message;
88     Nullable!DiagnosticSeverity severity;
89     Nullable!JSONValue code;
90     Nullable!string source;
91     Nullable!(DiagnosticRelatedInformation[]) relatedInformation;
92 
93     @safe this(Range range = new Range(), string message = string.init,
94             Nullable!DiagnosticSeverity severity = Nullable!DiagnosticSeverity.init,
95             Nullable!JSONValue code = Nullable!JSONValue.init,
96             Nullable!string source = Nullable!string.init,
97             Nullable!(DiagnosticRelatedInformation[]) relatedInformation = Nullable!(
98                 DiagnosticRelatedInformation[]).init) pure nothrow
99     {
100         this.range = range;
101         this.message = message;
102         this.severity = severity;
103         this.code = code;
104         this.source = source;
105         this.relatedInformation = relatedInformation;
106     }
107 }
108 
109 enum DiagnosticSeverity : uint
110 {
111     error = 1,
112     warning = 2,
113     information = 3,
114     hint = 4
115 }
116 
117 class DiagnosticRelatedInformation
118 {
119     Location location;
120     string message;
121 
122     @safe this(Location location = new Location(), string message = string.init) pure nothrow
123     {
124         this.location = location;
125         this.message = message;
126     }
127 }
128 
129 class Command
130 {
131     import std.json : JSONValue;
132     import dls.util.nullable: Nullable;
133 
134     string title;
135     string command;
136     Nullable!(JSONValue[]) arguments;
137 
138     @safe this(string title = string.init, string command = string.init,
139             Nullable!(JSONValue[]) arguments = Nullable!(JSONValue[]).init) pure nothrow
140     {
141         this.title = title;
142         this.command = command;
143         this.arguments = arguments;
144     }
145 }
146 
147 class TextEdit
148 {
149     Range range;
150     string newText;
151 
152     @safe this(Range range = new Range(), string newText = string.init) pure nothrow
153     {
154         this.range = range;
155         this.newText = newText;
156     }
157 }
158 
159 class TextDocumentEdit
160 {
161     VersionedTextDocumentIdentifier textDocument;
162     TextEdit[] edits;
163 
164     @safe this(VersionedTextDocumentIdentifier textDocument = new VersionedTextDocumentIdentifier(),
165             TextEdit[] edits = TextEdit[].init) pure nothrow
166     {
167         this.textDocument = textDocument;
168         this.edits = edits;
169     }
170 }
171 
172 class CreateFileOptions
173 {
174     import dls.util.nullable: Nullable;
175 
176     Nullable!bool overwrite;
177     Nullable!bool ignoreIfExists;
178 
179     @safe this(Nullable!bool overwrite = Nullable!bool.init,
180             Nullable!bool ignoreIfExists = Nullable!bool.init) pure nothrow
181     {
182         this.overwrite = overwrite;
183         this.ignoreIfExists = ignoreIfExists;
184     }
185 }
186 
187 class CreateFile
188 {
189     import dls.protocol.interfaces : ResourceOperationKind;
190     import dls.util.nullable: Nullable;
191 
192     immutable ResourceOperationKind kind = ResourceOperationKind.create;
193     DocumentUri uri;
194     Nullable!CreateFileOptions options;
195 
196     @safe this(DocumentUri uri = DocumentUri.init,
197             Nullable!CreateFileOptions options = Nullable!CreateFileOptions.init) pure nothrow
198     {
199         this.uri = uri;
200         this.options = options;
201     }
202 }
203 
204 class RenameFileOptions
205 {
206     import dls.util.nullable: Nullable;
207 
208     Nullable!bool overwrite;
209     Nullable!bool ignoreIfExists;
210 
211     @safe this(Nullable!bool overwrite = Nullable!bool.init,
212             Nullable!bool ignoreIfExists = Nullable!bool.init) pure nothrow
213     {
214         this.overwrite = overwrite;
215         this.ignoreIfExists = ignoreIfExists;
216     }
217 }
218 
219 class RenameFile
220 {
221     import dls.protocol.interfaces : ResourceOperationKind;
222     import dls.util.nullable: Nullable;
223 
224     immutable ResourceOperationKind kind = ResourceOperationKind.rename;
225     DocumentUri oldUri;
226     DocumentUri newUri;
227     Nullable!RenameFileOptions options;
228 
229     @safe this(DocumentUri oldUri = DocumentUri.init, DocumentUri newUri = DocumentUri.init,
230             Nullable!RenameFileOptions options = Nullable!RenameFileOptions.init) pure nothrow
231     {
232         this.oldUri = oldUri;
233         this.newUri = newUri;
234         this.options = options;
235     }
236 }
237 
238 class DeleteFileOptions
239 {
240     import dls.util.nullable: Nullable;
241 
242     Nullable!bool recursive;
243     Nullable!bool ignoreIfExists;
244 
245     @safe this(Nullable!bool recursive = Nullable!bool.init,
246             Nullable!bool ignoreIfExists = Nullable!bool.init) pure nothrow
247     {
248         this.recursive = recursive;
249         this.ignoreIfExists = ignoreIfExists;
250     }
251 }
252 
253 class DeleteFile
254 {
255     import dls.protocol.interfaces : ResourceOperationKind;
256     import dls.util.nullable: Nullable;
257 
258     immutable ResourceOperationKind kind = ResourceOperationKind.delete_;
259     DocumentUri uri;
260     Nullable!DeleteFileOptions options;
261 
262     @safe this(DocumentUri uri = DocumentUri.init,
263             Nullable!DeleteFileOptions options = Nullable!DeleteFileOptions.init) pure nothrow
264     {
265         this.uri = uri;
266         this.options = options;
267     }
268 }
269 
270 class WorkspaceEdit
271 {
272     import dls.util.nullable: Nullable;
273 
274     Nullable!(TextEdit[][string]) changes;
275     Nullable!(TextDocumentEdit[]) documentChanges; // (TextDocumentEdit | CreateFile | RenameFile | DeleteFile)[]
276 
277     @safe this(Nullable!(TextEdit[][string]) changes = Nullable!(TextEdit[][string])
278             .init, Nullable!(TextDocumentEdit[]) documentChanges = Nullable!(
279                 TextDocumentEdit[]).init) pure nothrow
280     {
281         this.changes = changes;
282         this.documentChanges = documentChanges;
283     }
284 }
285 
286 class TextDocumentIdentifier
287 {
288     DocumentUri uri;
289 
290     @safe this(DocumentUri uri = DocumentUri.init) pure nothrow
291     {
292         this.uri = uri;
293     }
294 }
295 
296 class TextDocumentItem : TextDocumentIdentifier
297 {
298     string languageId;
299     long version_;
300     string text;
301 
302     @safe this(DocumentUri uri = DocumentUri.init, string languageId = string.init,
303             long version_ = long.init, string text = string.init) pure nothrow
304     {
305         super(uri);
306         this.languageId = languageId;
307         this.version_ = version_;
308         this.text = text;
309     }
310 }
311 
312 class VersionedTextDocumentIdentifier : TextDocumentIdentifier
313 {
314     import std.json : JSONValue;
315 
316     JSONValue version_;
317 
318     @safe this(DocumentUri uri = DocumentUri.init, JSONValue version_ = JSONValue.init) pure nothrow
319     {
320         super(uri);
321         this.version_ = version_;
322     }
323 }
324 
325 class TextDocumentPositionParams
326 {
327     TextDocumentIdentifier textDocument;
328     Position position;
329 
330     @safe this(TextDocumentIdentifier textDocument = new TextDocumentIdentifier(),
331             Position position = new Position()) pure nothrow
332     {
333         this.textDocument = textDocument;
334         this.position = position;
335     }
336 }
337 
338 class DocumentFilter
339 {
340     import dls.util.nullable: Nullable;
341 
342     Nullable!string languageId;
343     Nullable!string scheme;
344     Nullable!string pattern;
345 
346     @safe this(Nullable!string languageId = Nullable!string.init,
347             Nullable!string scheme = Nullable!string.init,
348             Nullable!string pattern = Nullable!string.init) pure nothrow
349     {
350         this.languageId = languageId;
351         this.scheme = scheme;
352         this.pattern = pattern;
353     }
354 }
355 
356 alias DocumentSelector = DocumentFilter[];
357 
358 enum MarkupKind : string
359 {
360     plaintext = "plaintext",
361     markdown = "markdown"
362 }
363 
364 class MarkupContent
365 {
366     MarkupKind kind;
367     string value;
368 
369     @safe this(MarkupKind kind = MarkupKind.init, string value = string.init) pure nothrow
370     {
371         this.kind = kind;
372         this.value = value;
373     }
374 }