outlines, made JSON stdout memory dynamic
This commit is contained in:
parent
6fafceeb51
commit
2b153e046c
@ -1,6 +1,7 @@
|
||||
const std = @import("std");
|
||||
const AnalysisContext = @import("document_store.zig").AnalysisContext;
|
||||
const ast = std.zig.ast;
|
||||
const types = @import("types.zig");
|
||||
|
||||
/// REALLY BAD CODE, PLEASE DON'T USE THIS!!!!!!! (only for testing)
|
||||
pub fn getFunctionByName(tree: *ast.Tree, name: []const u8) ?*ast.Node.FnProto {
|
||||
@ -907,7 +908,6 @@ pub fn getImportStr(tree: *ast.Tree, source_index: usize) ?[]const u8 {
|
||||
return null;
|
||||
}
|
||||
|
||||
const types = @import("types.zig");
|
||||
pub const SourceRange = std.zig.Token.Loc;
|
||||
|
||||
pub const PositionContext = union(enum) {
|
||||
@ -1040,3 +1040,91 @@ pub fn documentPositionContext(allocator: *std.mem.Allocator, document: types.Te
|
||||
break :block .empty;
|
||||
};
|
||||
}
|
||||
|
||||
fn addOutlineNodes(allocator: *std.mem.Allocator, children: *std.ArrayList(types.DocumentSymbol), tree: *ast.Tree, child: *ast.Node) anyerror!void {
|
||||
switch (child.id) {
|
||||
.StringLiteral, .IntegerLiteral, .BuiltinCall, .Call, .Identifier, .InfixOp,
|
||||
.PrefixOp, .SuffixOp, .ControlFlowExpression, .ArrayInitializerDot, .SwitchElse,
|
||||
.SwitchCase, .For, .EnumLiteral, .PointerIndexPayload , .StructInitializerDot,
|
||||
.PointerPayload, .While, .Switch, .Else, .BoolLiteral, .NullLiteral, .Defer,
|
||||
.StructInitializer, .FieldInitializer, .If, .FnProto => return,
|
||||
|
||||
.ContainerDecl => {
|
||||
const decl = child.cast(ast.Node.ContainerDecl).?;
|
||||
|
||||
for (decl.fieldsAndDecls()) |cchild|
|
||||
try addOutlineNodes(allocator, children, tree, cchild);
|
||||
// _ = try children.append(try getDocumentSymbolsInternal(allocator, tree, cchild));
|
||||
return;
|
||||
},
|
||||
.Block => {
|
||||
// const block = child.cast(ast.Node.Block).?;
|
||||
|
||||
// for (block.statements()) |cchild|
|
||||
// try addOutlineNodes(allocator, children, tree, cchild);
|
||||
// _ = try children.append(try getDocumentSymbolsInternal(allocator, tree, cchild));
|
||||
return;
|
||||
},
|
||||
else => {}
|
||||
}
|
||||
std.debug.warn("{}\n", .{child.id});
|
||||
_ = try children.append(try getDocumentSymbolsInternal(allocator, tree, child));
|
||||
}
|
||||
|
||||
fn getDocumentSymbolsInternal(allocator: *std.mem.Allocator, tree: *ast.Tree, node: *ast.Node) anyerror!types.DocumentSymbol {
|
||||
// const symbols = std.ArrayList(types.DocumentSymbol).init(allocator);
|
||||
|
||||
const start_loc = tree.tokenLocation(0, node.firstToken());
|
||||
const end_loc = tree.tokenLocation(0, node.lastToken());
|
||||
const range = types.Range{
|
||||
.start = .{
|
||||
.line = @intCast(i64, start_loc.line),
|
||||
.character = @intCast(i64, start_loc.column),
|
||||
},
|
||||
.end = .{
|
||||
.line = @intCast(i64, end_loc.line),
|
||||
.character = @intCast(i64, end_loc.column),
|
||||
}
|
||||
};
|
||||
|
||||
if (getDeclName(tree, node) == null) {
|
||||
std.debug.warn("NULL NAME: {}\n", .{node.id});
|
||||
}
|
||||
|
||||
// TODO: Get my lazy bum to fix detail newlines
|
||||
return types.DocumentSymbol{
|
||||
.name = getDeclName(tree, node) orelse "no_name",
|
||||
// .detail = (try getDocComments(allocator, tree, node)) orelse "",
|
||||
.detail = "",
|
||||
.kind = switch (node.id) {
|
||||
.FnProto => .Function,
|
||||
.VarDecl => .Variable,
|
||||
.ContainerField => .Field,
|
||||
else => .Variable
|
||||
},
|
||||
.range = range,
|
||||
.selectionRange = range,
|
||||
.children = ch: {
|
||||
var children = std.ArrayList(types.DocumentSymbol).init(allocator);
|
||||
|
||||
var index: usize = 0;
|
||||
while (node.iterate(index)) |child| : (index += 1) {
|
||||
try addOutlineNodes(allocator, &children, tree, child);
|
||||
}
|
||||
|
||||
break :ch children.items;
|
||||
},
|
||||
};
|
||||
|
||||
// return symbols.items;
|
||||
}
|
||||
|
||||
pub fn getDocumentSymbols(allocator: *std.mem.Allocator, tree: *ast.Tree) ![]types.DocumentSymbol {
|
||||
var symbols = std.ArrayList(types.DocumentSymbol).init(allocator);
|
||||
|
||||
for (tree.root_node.decls()) |node| {
|
||||
_ = try symbols.append(try getDocumentSymbolsInternal(allocator, tree, node));
|
||||
}
|
||||
|
||||
return symbols.items;
|
||||
}
|
||||
|
37
src/main.zig
37
src/main.zig
@ -19,7 +19,7 @@ var document_store: DocumentStore = undefined;
|
||||
var workspace_folder_configs: std.StringHashMap(?Config) = undefined;
|
||||
|
||||
const initialize_response =
|
||||
\\,"result":{"capabilities":{"signatureHelpProvider":{"triggerCharacters":["(",","]},"textDocumentSync":1,"completionProvider":{"resolveProvider":false,"triggerCharacters":[".",":","@"]},"documentHighlightProvider":false,"hoverProvider":true,"codeActionProvider":false,"declarationProvider":true,"definitionProvider":true,"typeDefinitionProvider":true,"implementationProvider":false,"referencesProvider":false,"documentSymbolProvider":false,"colorProvider":false,"documentFormattingProvider":false,"documentRangeFormattingProvider":false,"foldingRangeProvider":false,"selectionRangeProvider":false,"workspaceSymbolProvider":false,"workspace":{"workspaceFolders":{"supported":true,"changeNotifications":true}}}}}
|
||||
\\,"result":{"capabilities":{"signatureHelpProvider":{"triggerCharacters":["(",","]},"textDocumentSync":1,"completionProvider":{"resolveProvider":false,"triggerCharacters":[".",":","@"]},"documentHighlightProvider":false,"hoverProvider":true,"codeActionProvider":false,"declarationProvider":true,"definitionProvider":true,"typeDefinitionProvider":true,"implementationProvider":false,"referencesProvider":false,"documentSymbolProvider":true,"colorProvider":false,"documentFormattingProvider":false,"documentRangeFormattingProvider":false,"foldingRangeProvider":false,"selectionRangeProvider":false,"workspaceSymbolProvider":false,"workspace":{"workspaceFolders":{"supported":true,"changeNotifications":true}}}}}
|
||||
;
|
||||
|
||||
const not_implemented_response =
|
||||
@ -44,14 +44,15 @@ const no_completions_response =
|
||||
|
||||
/// Sends a request or response
|
||||
fn send(reqOrRes: var) !void {
|
||||
// The most memory we'll probably need
|
||||
var mem_buffer: [1024 * 128]u8 = undefined;
|
||||
var fbs = std.io.fixedBufferStream(&mem_buffer);
|
||||
try std.json.stringify(reqOrRes, std.json.StringifyOptions{}, fbs.outStream());
|
||||
var arena = std.heap.ArenaAllocator.init(allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
var arr = std.ArrayList(u8).init(&arena.allocator);
|
||||
try std.json.stringify(reqOrRes, std.json.StringifyOptions{}, arr.outStream());
|
||||
|
||||
const stdout_stream = stdout.outStream();
|
||||
try stdout_stream.print("Content-Length: {}\r\n\r\n", .{fbs.pos});
|
||||
try stdout_stream.writeAll(fbs.getWritten());
|
||||
try stdout_stream.print("Content-Length: {}\r\n\r\n", .{arr.items.len});
|
||||
try stdout_stream.writeAll(arr.items);
|
||||
try stdout.flush();
|
||||
}
|
||||
|
||||
@ -526,6 +527,18 @@ fn completeFieldAccess(id: i64, handle: *DocumentStore.Handle, position: types.P
|
||||
});
|
||||
}
|
||||
|
||||
fn documentSymbol(id: i64, handle: *DocumentStore.Handle) !void {
|
||||
var arena = std.heap.ArenaAllocator.init(allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
try send(types.Response{
|
||||
.id = .{ .Integer = id },
|
||||
.result = .{
|
||||
.DocumentSymbols = try analysis.getDocumentSymbols(&arena.allocator, handle.tree)
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Compute builtin completions at comptime.
|
||||
const builtin_completions = block: {
|
||||
@setEvalBranchQuota(3_500);
|
||||
@ -834,6 +847,16 @@ fn processJsonRpc(parser: *std.json.Parser, json: []const u8, config: Config) !v
|
||||
} else {
|
||||
try respondGeneric(id, null_result_response);
|
||||
}
|
||||
} else if (std.mem.eql(u8, method, "textDocument/documentSymbol")) {
|
||||
const document = params.getValue("textDocument").?.Object;
|
||||
const uri = document.getValue("uri").?.String;
|
||||
|
||||
const handle = document_store.getHandle(uri) orelse {
|
||||
std.debug.warn("Trying to got to definition in non existent document {}", .{uri});
|
||||
return try respondGeneric(id, null_result_response);
|
||||
};
|
||||
|
||||
try documentSymbol(id, handle);
|
||||
} else if (root.Object.getValue("id")) |_| {
|
||||
std.debug.warn("Method with return value not implemented: {}", .{method});
|
||||
try respondGeneric(id, not_implemented_response);
|
||||
|
@ -62,6 +62,7 @@ pub const ResponseParams = union(enum) {
|
||||
CompletionList: CompletionList,
|
||||
Location: Location,
|
||||
Hover: Hover,
|
||||
DocumentSymbols: []DocumentSymbol
|
||||
};
|
||||
|
||||
/// JSONRPC error
|
||||
@ -292,3 +293,50 @@ pub const CompletionItem = struct {
|
||||
documentation: ?MarkupContent = null
|
||||
// filterText: String = .NotDefined,
|
||||
};
|
||||
|
||||
const SymbolKind = enum {
|
||||
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: SymbolKind,
|
||||
options: json.StringifyOptions,
|
||||
out_stream: var,
|
||||
) !void {
|
||||
try json.stringify(@enumToInt(value), options, out_stream);
|
||||
}
|
||||
};
|
||||
|
||||
pub const DocumentSymbol = struct {
|
||||
name: []const u8,
|
||||
detail: ?[]const u8 = null,
|
||||
kind: SymbolKind,
|
||||
deprecated: bool = false,
|
||||
range: Range,
|
||||
selectionRange: Range,
|
||||
children: []DocumentSymbol = &[_]DocumentSymbol{}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user