Optimize document symbols
This commit is contained in:
parent
3659a5c1a9
commit
b61785eb3e
@ -2,6 +2,7 @@ const std = @import("std");
|
|||||||
const DocumentStore = @import("document_store.zig");
|
const DocumentStore = @import("document_store.zig");
|
||||||
const ast = std.zig.ast;
|
const ast = std.zig.ast;
|
||||||
const types = @import("types.zig");
|
const types = @import("types.zig");
|
||||||
|
const offsets = @import("offsets.zig");
|
||||||
|
|
||||||
/// Get a declaration's doc comment node
|
/// Get a declaration's doc comment node
|
||||||
fn getDocCommentNode(tree: *ast.Tree, node: *ast.Node) ?*ast.Node.DocComment {
|
fn getDocCommentNode(tree: *ast.Tree, node: *ast.Node) ?*ast.Node.DocComment {
|
||||||
@ -153,7 +154,6 @@ pub fn isTypeFunction(tree: *ast.Tree, func: *ast.Node.FnProto) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TODO
|
|
||||||
pub fn isGenericFunction(tree: *ast.Tree, func: *ast.Node.FnProto) bool {
|
pub fn isGenericFunction(tree: *ast.Tree, func: *ast.Node.FnProto) bool {
|
||||||
for (func.paramsConst()) |param| {
|
for (func.paramsConst()) |param| {
|
||||||
if (param.param_type == .var_type or param.comptime_token != null) {
|
if (param.param_type == .var_type or param.comptime_token != null) {
|
||||||
@ -1346,7 +1346,7 @@ pub fn documentPositionContext(arena: *std.heap.ArenaAllocator, document: types.
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn addOutlineNodes(allocator: *std.mem.Allocator, children: *std.ArrayList(types.DocumentSymbol), tree: *ast.Tree, child: *ast.Node) anyerror!void {
|
fn addOutlineNodes(allocator: *std.mem.Allocator, tree: *ast.Tree, child: *ast.Node, context: *GetDocumentSymbolsContext) anyerror!void {
|
||||||
switch (child.id) {
|
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, .MultilineStringLiteral, .UndefinedLiteral, .VarType, .Block, .ErrorSetDecl => return,
|
.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, .MultilineStringLiteral, .UndefinedLiteral, .VarType, .Block, .ErrorSetDecl => return,
|
||||||
|
|
||||||
@ -1354,18 +1354,36 @@ fn addOutlineNodes(allocator: *std.mem.Allocator, children: *std.ArrayList(types
|
|||||||
const decl = child.cast(ast.Node.ContainerDecl).?;
|
const decl = child.cast(ast.Node.ContainerDecl).?;
|
||||||
|
|
||||||
for (decl.fieldsAndDecls()) |cchild|
|
for (decl.fieldsAndDecls()) |cchild|
|
||||||
try addOutlineNodes(allocator, children, tree, cchild);
|
try addOutlineNodes(allocator, tree, cchild, context);
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
_ = try children.append(try getDocumentSymbolsInternal(allocator, tree, child));
|
try getDocumentSymbolsInternal(allocator, tree, child, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getDocumentSymbolsInternal(allocator: *std.mem.Allocator, tree: *ast.Tree, node: *ast.Node) anyerror!types.DocumentSymbol {
|
const GetDocumentSymbolsContext = struct {
|
||||||
// const symbols = std.ArrayList(types.DocumentSymbol).init(allocator);
|
prev_loc: offsets.TokenLocation = .{
|
||||||
const start_loc = tree.tokenLocation(0, node.firstToken());
|
.line = 0,
|
||||||
const end_loc = tree.tokenLocation(0, node.lastToken());
|
.column = 0,
|
||||||
|
.offset = 0,
|
||||||
|
},
|
||||||
|
symbols: *std.ArrayList(types.DocumentSymbol),
|
||||||
|
encoding: offsets.Encoding,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn getDocumentSymbolsInternal(allocator: *std.mem.Allocator, tree: *ast.Tree, node: *ast.Node, context: *GetDocumentSymbolsContext) anyerror!void {
|
||||||
|
const name = if (getDeclName(tree, node)) |name|
|
||||||
|
name
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (name.len == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const start_loc = context.prev_loc.add(try offsets.tokenRelativeLocation(tree, context.prev_loc.offset, node.firstToken(), context.encoding));
|
||||||
|
const end_loc = start_loc.add(try offsets.tokenRelativeLocation(tree, start_loc.offset, node.lastToken(), context.encoding));
|
||||||
|
context.prev_loc = end_loc;
|
||||||
const range = types.Range{
|
const range = types.Range{
|
||||||
.start = .{
|
.start = .{
|
||||||
.line = @intCast(i64, start_loc.line),
|
.line = @intCast(i64, start_loc.line),
|
||||||
@ -1377,23 +1395,8 @@ fn getDocumentSymbolsInternal(allocator: *std.mem.Allocator, tree: *ast.Tree, no
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (getDeclName(tree, node) == null) {
|
(try context.symbols.addOne()).* = .{
|
||||||
std.log.debug(.analysis, "NULL NAME: {}\n", .{node.id});
|
.name = name,
|
||||||
}
|
|
||||||
|
|
||||||
const maybe_name = if (getDeclName(tree, node)) |name|
|
|
||||||
name
|
|
||||||
else
|
|
||||||
"";
|
|
||||||
|
|
||||||
// TODO: Get my lazy bum to fix detail newlines
|
|
||||||
return types.DocumentSymbol{
|
|
||||||
.name = if (maybe_name.len == 0) switch (node.id) {
|
|
||||||
.TestDecl => "Nameless Test",
|
|
||||||
else => "no_name",
|
|
||||||
} else maybe_name,
|
|
||||||
// .detail = (try getDocComments(allocator, tree, node)) orelse "",
|
|
||||||
.detail = "",
|
|
||||||
.kind = switch (node.id) {
|
.kind = switch (node.id) {
|
||||||
.FnProto => .Function,
|
.FnProto => .Function,
|
||||||
.VarDecl => .Variable,
|
.VarDecl => .Variable,
|
||||||
@ -1402,26 +1405,36 @@ fn getDocumentSymbolsInternal(allocator: *std.mem.Allocator, tree: *ast.Tree, no
|
|||||||
},
|
},
|
||||||
.range = range,
|
.range = range,
|
||||||
.selectionRange = range,
|
.selectionRange = range,
|
||||||
|
.detail = "",
|
||||||
.children = ch: {
|
.children = ch: {
|
||||||
var children = std.ArrayList(types.DocumentSymbol).init(allocator);
|
var children = std.ArrayList(types.DocumentSymbol).init(allocator);
|
||||||
|
|
||||||
|
var child_context = GetDocumentSymbolsContext{
|
||||||
|
.prev_loc = start_loc,
|
||||||
|
.symbols = &children,
|
||||||
|
.encoding = context.encoding,
|
||||||
|
};
|
||||||
|
|
||||||
var index: usize = 0;
|
var index: usize = 0;
|
||||||
while (node.iterate(index)) |child| : (index += 1) {
|
while (node.iterate(index)) |child| : (index += 1) {
|
||||||
try addOutlineNodes(allocator, &children, tree, child);
|
try addOutlineNodes(allocator, tree, child, &child_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
break :ch children.items;
|
break :ch children.items;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// return symbols.items;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getDocumentSymbols(allocator: *std.mem.Allocator, tree: *ast.Tree) ![]types.DocumentSymbol {
|
pub fn getDocumentSymbols(allocator: *std.mem.Allocator, tree: *ast.Tree, encoding: offsets.Encoding) ![]types.DocumentSymbol {
|
||||||
var symbols = std.ArrayList(types.DocumentSymbol).init(allocator);
|
var symbols = try std.ArrayList(types.DocumentSymbol).initCapacity(allocator, tree.root_node.decls_len);
|
||||||
|
|
||||||
|
var context = GetDocumentSymbolsContext {
|
||||||
|
.symbols = &symbols,
|
||||||
|
.encoding = encoding,
|
||||||
|
};
|
||||||
|
|
||||||
for (tree.root_node.decls()) |node| {
|
for (tree.root_node.decls()) |node| {
|
||||||
_ = try symbols.append(try getDocumentSymbolsInternal(allocator, tree, node));
|
try getDocumentSymbolsInternal(allocator, tree, node, &context);
|
||||||
}
|
}
|
||||||
|
|
||||||
return symbols.items;
|
return symbols.items;
|
||||||
@ -1462,9 +1475,9 @@ pub const DeclWithHandle = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn location(self: DeclWithHandle) ast.Tree.Location {
|
pub fn location(self: DeclWithHandle, encoding: offsets.Encoding) !offsets.TokenLocation {
|
||||||
const tree = self.handle.tree;
|
const tree = self.handle.tree;
|
||||||
return tree.tokenLocation(0, self.nameToken());
|
return try offsets.tokenRelativeLocation(tree, 0, self.nameToken(), encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn isPublic(self: DeclWithHandle) bool {
|
fn isPublic(self: DeclWithHandle) bool {
|
||||||
|
@ -99,7 +99,7 @@ pub fn init(base_allocator: *std.mem.Allocator, max_bytes: usize) DebugAllocator
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: DebugAllocator) void {
|
pub fn deinit(self: *DebugAllocator) void {
|
||||||
self.allocation_strack_addresses.deinit();
|
self.allocation_strack_addresses.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
src/main.zig
19
src/main.zig
@ -483,15 +483,15 @@ fn gotoDefinitionSymbol(id: types.RequestId, arena: *std.heap.ArenaAllocator, de
|
|||||||
if (resolve_alias) {
|
if (resolve_alias) {
|
||||||
if (try analysis.resolveVarDeclAlias(&document_store, arena, .{ .node = node, .handle = handle })) |result| {
|
if (try analysis.resolveVarDeclAlias(&document_store, arena, .{ .node = node, .handle = handle })) |result| {
|
||||||
handle = result.handle;
|
handle = result.handle;
|
||||||
break :block result.location();
|
break :block result.location(offset_encoding) catch return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const name_token = analysis.getDeclNameToken(handle.tree, node) orelse
|
const name_token = analysis.getDeclNameToken(handle.tree, node) orelse
|
||||||
return try respondGeneric(id, null_result_response);
|
return try respondGeneric(id, null_result_response);
|
||||||
break :block handle.tree.tokenLocation(0, name_token);
|
break :block offsets.tokenRelativeLocation(handle.tree, 0, name_token, offset_encoding) catch return;
|
||||||
},
|
},
|
||||||
else => decl_handle.location(),
|
else => decl_handle.location(offset_encoding) catch return,
|
||||||
};
|
};
|
||||||
|
|
||||||
try send(arena, types.Response{
|
try send(arena, types.Response{
|
||||||
@ -499,7 +499,16 @@ fn gotoDefinitionSymbol(id: types.RequestId, arena: *std.heap.ArenaAllocator, de
|
|||||||
.result = .{
|
.result = .{
|
||||||
.Location = .{
|
.Location = .{
|
||||||
.uri = handle.document.uri,
|
.uri = handle.document.uri,
|
||||||
.range = astLocationToRange(location),
|
.range = .{
|
||||||
|
.start = .{
|
||||||
|
.line = @intCast(i64, location.line),
|
||||||
|
.character = @intCast(i64, location.column),
|
||||||
|
},
|
||||||
|
.end = .{
|
||||||
|
.line = @intCast(i64, location.line),
|
||||||
|
.character = @intCast(i64, location.column),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -907,7 +916,7 @@ fn completeFieldAccess(
|
|||||||
fn documentSymbol(arena: *std.heap.ArenaAllocator, id: types.RequestId, handle: *DocumentStore.Handle) !void {
|
fn documentSymbol(arena: *std.heap.ArenaAllocator, id: types.RequestId, handle: *DocumentStore.Handle) !void {
|
||||||
try send(arena, types.Response{
|
try send(arena, types.Response{
|
||||||
.id = id,
|
.id = id,
|
||||||
.result = .{ .DocumentSymbols = try analysis.getDocumentSymbols(&arena.allocator, handle.tree) },
|
.result = .{ .DocumentSymbols = try analysis.getDocumentSymbols(&arena.allocator, handle.tree, offset_encoding) },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +56,18 @@ pub fn documentPosition(doc: types.TextDocument, position: types.Position, encod
|
|||||||
pub const TokenLocation = struct {
|
pub const TokenLocation = struct {
|
||||||
line: usize,
|
line: usize,
|
||||||
column: usize,
|
column: usize,
|
||||||
|
offset: usize,
|
||||||
|
|
||||||
|
pub fn add(lhs: TokenLocation, rhs: TokenLocation) TokenLocation {
|
||||||
|
return .{
|
||||||
|
.line = lhs.line + rhs.line,
|
||||||
|
.column = if (rhs.line == 0)
|
||||||
|
lhs.column + rhs.column
|
||||||
|
else
|
||||||
|
rhs.column,
|
||||||
|
.offset = rhs.offset,
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn tokenRelativeLocation(tree: *std.zig.ast.Tree, start_index: usize, token: std.zig.ast.TokenIndex, encoding: Encoding) !TokenLocation {
|
pub fn tokenRelativeLocation(tree: *std.zig.ast.Tree, start_index: usize, token: std.zig.ast.TokenIndex, encoding: Encoding) !TokenLocation {
|
||||||
@ -64,6 +76,7 @@ pub fn tokenRelativeLocation(tree: *std.zig.ast.Tree, start_index: usize, token:
|
|||||||
var loc = TokenLocation{
|
var loc = TokenLocation{
|
||||||
.line = 0,
|
.line = 0,
|
||||||
.column = 0,
|
.column = 0,
|
||||||
|
.offset = 0,
|
||||||
};
|
};
|
||||||
const token_start = token_loc.start;
|
const token_start = token_loc.start;
|
||||||
const source = tree.source[start_index..];
|
const source = tree.source[start_index..];
|
||||||
@ -90,6 +103,7 @@ pub fn tokenRelativeLocation(tree: *std.zig.ast.Tree, start_index: usize, token:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
loc.offset = i + start_index;
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,7 +317,7 @@ pub const DocumentSymbol = struct {
|
|||||||
deprecated: bool = false,
|
deprecated: bool = false,
|
||||||
range: Range,
|
range: Range,
|
||||||
selectionRange: Range,
|
selectionRange: Range,
|
||||||
children: []DocumentSymbol = &[_]DocumentSymbol{},
|
children: []const DocumentSymbol = &[_]DocumentSymbol{},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ShowMessageParams = struct {
|
pub const ShowMessageParams = struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user