zls/src/types.zig
Luca Sas 2a17590bf4
Added textDocument/foldingRange (#718)
* Added textDocument/foldingRange

* Added support for code regions

* Fixed warning message in foldingRangeHandler

Co-authored-by: LucaSas <sas.luca.alex@gmail.com>
2022-10-25 10:35:16 -04:00

529 lines
14 KiB
Zig

const std = @import("std");
const string = []const u8;
// LSP types
// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/
pub const Position = struct {
line: u32,
character: u32,
};
pub const Range = struct {
start: Position,
end: Position,
};
pub const Location = struct {
uri: string,
range: Range,
};
/// Id of a request
pub const RequestId = union(enum) {
String: string,
Integer: i32,
};
/// Params of a response (result)
pub const ResponseParams = union(enum) {
SignatureHelp: SignatureHelp,
CompletionList: CompletionList,
Location: Location,
Hover: Hover,
DocumentSymbols: []DocumentSymbol,
SemanticTokensFull: SemanticTokens,
InlayHint: []InlayHint,
TextEdits: []TextEdit,
Locations: []Location,
WorkspaceEdit: WorkspaceEdit,
InitializeResult: InitializeResult,
ConfigurationParams: ConfigurationParams,
RegistrationParams: RegistrationParams,
DocumentHighlight: []DocumentHighlight,
CodeAction: []CodeAction,
ApplyEdit: ApplyWorkspaceEditParams,
FoldingRange: []FoldingRange,
};
pub const Response = struct {
jsonrpc: string = "2.0",
id: RequestId,
result: ResponseParams,
};
pub const Request = struct {
jsonrpc: string = "2.0",
id: RequestId,
method: []const u8,
params: ?ResponseParams,
};
pub const ResponseError = struct {
code: i32,
message: string,
data: std.json.Value,
};
pub const ErrorCodes = enum(i32) {
// Defined by JSON-RPC
ParseError = -32700,
InvalidRequest = -32600,
MethodNotFound = -32601,
InvalidParams = -32602,
InternalError = -32603,
// JSON-RPC reserved error codes
ServerNotInitialized = -32002,
UnknownErrorCode = -3200,
// LSP reserved error codes
RequestFailed = -32803,
ServerCancelled = -32802,
ContentModified = -32801,
RequestCancelled = -32800,
};
pub const Notification = struct {
jsonrpc: string = "2.0",
method: string,
params: NotificationParams,
};
pub const NotificationParams = union(enum) {
LogMessage: struct {
type: MessageType,
message: string,
},
PublishDiagnostics: struct {
uri: string,
diagnostics: []Diagnostic,
},
ShowMessage: struct {
type: MessageType,
message: string,
},
};
/// Type of a debug message
pub const MessageType = enum(i64) {
Error = 1,
Warning = 2,
Info = 3,
Log = 4,
pub fn jsonStringify(value: MessageType, options: std.json.StringifyOptions, out_stream: anytype) !void {
try std.json.stringify(@enumToInt(value), options, out_stream);
}
};
pub const DiagnosticSeverity = enum(i64) {
Error = 1,
Warning = 2,
Information = 3,
Hint = 4,
pub fn jsonStringify(value: DiagnosticSeverity, options: std.json.StringifyOptions, out_stream: anytype) !void {
try std.json.stringify(@enumToInt(value), options, out_stream);
}
};
pub const DiagnosticRelatedInformation = struct {
location: Location,
message: string,
};
pub const Diagnostic = struct {
range: Range,
severity: ?DiagnosticSeverity,
code: ?string,
source: ?string,
message: string,
relatedInformation: ?[]DiagnosticRelatedInformation = null,
};
pub const WorkspaceEdit = struct {
changes: std.StringHashMapUnmanaged(std.ArrayListUnmanaged(TextEdit)),
pub fn jsonStringify(self: WorkspaceEdit, options: std.json.StringifyOptions, writer: anytype) @TypeOf(writer).Error!void {
try writer.writeAll("{\"changes\": {");
var it = self.changes.iterator();
var idx: usize = 0;
while (it.next()) |entry| : (idx += 1) {
if (idx != 0) try writer.writeAll(", ");
try writer.writeByte('"');
try writer.writeAll(entry.key_ptr.*);
try writer.writeAll("\":");
try std.json.stringify(entry.value_ptr.items, options, writer);
}
try writer.writeAll("}}");
}
};
pub const TextEdit = struct {
range: Range,
newText: string,
};
pub const MarkupContent = struct {
pub const Kind = enum(u1) {
PlainText = 0,
Markdown = 1,
pub fn jsonStringify(value: Kind, options: std.json.StringifyOptions, out_stream: anytype) !void {
const str = switch (value) {
.PlainText => "plaintext",
.Markdown => "markdown",
};
try std.json.stringify(str, options, out_stream);
}
};
kind: Kind = .Markdown,
value: string,
};
pub const CompletionList = struct {
isIncomplete: bool,
items: []const CompletionItem,
};
pub const InsertTextFormat = enum(i64) {
PlainText = 1,
Snippet = 2,
pub fn jsonStringify(value: InsertTextFormat, options: std.json.StringifyOptions, out_stream: anytype) !void {
try std.json.stringify(@enumToInt(value), options, out_stream);
}
};
pub const Hover = struct {
contents: MarkupContent,
};
pub const SemanticTokens = struct {
data: []const u32,
};
pub const CompletionItem = struct {
pub const Kind = enum(i64) {
Text = 1,
Method = 2,
Function = 3,
Constructor = 4,
Field = 5,
Variable = 6,
Class = 7,
Interface = 8,
Module = 9,
Property = 10,
Unit = 11,
Value = 12,
Enum = 13,
Keyword = 14,
Snippet = 15,
Color = 16,
File = 17,
Reference = 18,
Folder = 19,
EnumMember = 20,
Constant = 21,
Struct = 22,
Event = 23,
Operator = 24,
TypeParameter = 25,
pub fn jsonStringify(value: Kind, options: std.json.StringifyOptions, out_stream: anytype) !void {
try std.json.stringify(@enumToInt(value), options, out_stream);
}
};
label: string,
labelDetails: ?CompletionItemLabelDetails = null,
kind: Kind,
detail: ?string = null,
sortText: ?string = null,
filterText: ?string = null,
insertText: ?string = null,
insertTextFormat: ?InsertTextFormat = .PlainText,
documentation: ?MarkupContent = null,
// FIXME: i commented this out, because otherwise the vscode client complains about *ranges*
// and breaks code completion entirely
// see: https://github.com/zigtools/zls-vscode/pull/33
// textEdit: ?TextEdit = null,
};
pub const CompletionItemLabelDetails = struct {
detail: ?string,
description: ?string,
sortText: ?string = null,
};
pub const DocumentSymbol = struct {
const Kind = enum(u32) {
File = 1,
Module = 2,
Namespace = 3,
Package = 4,
Class = 5,
Method = 6,
Property = 7,
Field = 8,
Constructor = 9,
Enum = 10,
Interface = 11,
Function = 12,
Variable = 13,
Constant = 14,
String = 15,
Number = 16,
Boolean = 17,
Array = 18,
Object = 19,
Key = 20,
Null = 21,
EnumMember = 22,
Struct = 23,
Event = 24,
Operator = 25,
TypeParameter = 26,
pub fn jsonStringify(value: Kind, options: std.json.StringifyOptions, out_stream: anytype) !void {
try std.json.stringify(@enumToInt(value), options, out_stream);
}
};
name: string,
detail: ?string = null,
kind: Kind,
deprecated: bool = false,
range: Range,
selectionRange: Range,
children: []const DocumentSymbol = &[_]DocumentSymbol{},
};
pub const WorkspaceFolder = struct {
uri: string,
name: string,
};
pub const SignatureInformation = struct {
pub const ParameterInformation = struct {
// TODO Can also send a pair of encoded offsets
label: string,
documentation: ?MarkupContent,
};
label: string,
documentation: ?MarkupContent,
parameters: ?[]const ParameterInformation,
activeParameter: ?u32,
};
pub const SignatureHelp = struct {
signatures: ?[]const SignatureInformation,
activeSignature: ?u32,
activeParameter: ?u32,
};
pub const InlayHint = struct {
position: Position,
label: string,
kind: InlayHintKind,
tooltip: MarkupContent,
paddingLeft: bool,
paddingRight: bool,
// appends a colon to the label and reduces the output size
pub fn jsonStringify(value: InlayHint, options: std.json.StringifyOptions, writer: anytype) @TypeOf(writer).Error!void {
try writer.writeAll("{\"position\":");
try std.json.stringify(value.position, options, writer);
try writer.writeAll(",\"label\":\"");
try writer.writeAll(value.label);
try writer.writeAll(":\",\"kind\":");
try std.json.stringify(value.kind, options, writer);
if (value.tooltip.value.len != 0) {
try writer.writeAll(",\"tooltip\":");
try std.json.stringify(value.tooltip, options, writer);
}
if (value.paddingLeft) try writer.writeAll(",\"paddingLeft\":true");
if (value.paddingRight) try writer.writeAll(",\"paddingRight\":true");
try writer.writeByte('}');
}
};
pub const InlayHintKind = enum(i64) {
Type = 1,
Parameter = 2,
pub fn jsonStringify(value: InlayHintKind, options: std.json.StringifyOptions, out_stream: anytype) !void {
try std.json.stringify(@enumToInt(value), options, out_stream);
}
};
pub const CodeActionKind = enum {
Empty,
QuickFix,
Refactor,
RefactorExtract,
RefactorInline,
RefactorRewrite,
Source,
SourceOrganizeImports,
SourceFixAll,
pub fn jsonStringify(value: CodeActionKind, options: std.json.StringifyOptions, out_stream: anytype) !void {
const name = switch (value) {
.Empty => "",
.QuickFix => "quickfix",
.Refactor => "refactor",
.RefactorExtract => "refactor.extract",
.RefactorInline => "refactor.inline",
.RefactorRewrite => "refactor.rewrite",
.Source => "source",
.SourceOrganizeImports => "source.organizeImports",
.SourceFixAll => "source.fixAll",
};
try std.json.stringify(name, options, out_stream);
}
};
pub const CodeAction = struct {
title: string,
kind: CodeActionKind,
// diagnostics: []Diagnostic,
isPreferred: bool,
edit: WorkspaceEdit,
};
pub const ApplyWorkspaceEditParams = struct {
label: string,
edit: WorkspaceEdit,
};
pub const PositionEncodingKind = enum {
utf8,
utf16,
utf32,
pub fn jsonStringify(value: PositionEncodingKind, options: std.json.StringifyOptions, out_stream: anytype) !void {
const str = switch (value) {
.utf8 => "utf-8",
.utf16 => "utf-16",
.utf32 => "utf-32",
};
try std.json.stringify(str, options, out_stream);
}
};
const TextDocumentSyncKind = enum(u32) {
None = 0,
Full = 1,
Incremental = 2,
pub fn jsonStringify(value: @This(), options: std.json.StringifyOptions, out_stream: anytype) !void {
try std.json.stringify(@enumToInt(value), options, out_stream);
}
};
// Only includes options we set in our initialize result.
const InitializeResult = struct {
capabilities: struct {
positionEncoding: PositionEncodingKind,
signatureHelpProvider: struct {
triggerCharacters: []const string,
retriggerCharacters: []const string,
},
textDocumentSync: struct {
openClose: bool,
change: TextDocumentSyncKind,
save: bool,
},
renameProvider: bool,
completionProvider: struct {
resolveProvider: bool,
triggerCharacters: []const string,
completionItem: struct { labelDetailsSupport: bool },
},
documentHighlightProvider: bool,
hoverProvider: bool,
codeActionProvider: bool,
declarationProvider: bool,
definitionProvider: bool,
typeDefinitionProvider: bool,
implementationProvider: bool,
referencesProvider: bool,
documentSymbolProvider: bool,
colorProvider: bool,
documentFormattingProvider: bool,
documentRangeFormattingProvider: bool,
foldingRangeProvider: bool,
selectionRangeProvider: bool,
workspaceSymbolProvider: bool,
rangeProvider: bool,
documentProvider: bool,
workspace: ?struct {
workspaceFolders: ?struct {
supported: bool,
changeNotifications: bool,
},
},
semanticTokensProvider: struct {
full: bool,
range: bool,
legend: struct {
tokenTypes: []const string,
tokenModifiers: []const string,
},
},
inlayHintProvider: bool,
},
serverInfo: struct {
name: string,
version: ?string = null,
},
};
pub const ConfigurationParams = struct {
items: []const ConfigurationItem,
pub const ConfigurationItem = struct {
section: ?[]const u8,
};
};
pub const RegistrationParams = struct {
registrations: []const Registration,
pub const Registration = struct {
id: string,
method: string,
// registerOptions?: LSPAny;
};
};
pub const DocumentHighlightKind = enum(u8) {
Text = 1,
Read = 2,
Write = 3,
pub fn jsonStringify(value: DocumentHighlightKind, options: std.json.StringifyOptions, out_stream: anytype) !void {
try std.json.stringify(@enumToInt(value), options, out_stream);
}
};
pub const DocumentHighlight = struct {
range: Range,
kind: ?DocumentHighlightKind,
};
pub const FoldingRange = struct {
startLine: usize,
endLine: usize,
};