Optimize document symbols

This commit is contained in:
Alexandros Naskos 2020-07-07 11:57:02 +03:00
parent 3659a5c1a9
commit b61785eb3e
5 changed files with 76 additions and 40 deletions

View File

@ -2,6 +2,7 @@ const std = @import("std");
const DocumentStore = @import("document_store.zig");
const ast = std.zig.ast;
const types = @import("types.zig");
const offsets = @import("offsets.zig");
/// Get a declaration's doc comment node
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 {
for (func.paramsConst()) |param| {
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) {
.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).?;
for (decl.fieldsAndDecls()) |cchild|
try addOutlineNodes(allocator, children, tree, cchild);
try addOutlineNodes(allocator, tree, cchild, context);
return;
},
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 symbols = std.ArrayList(types.DocumentSymbol).init(allocator);
const start_loc = tree.tokenLocation(0, node.firstToken());
const end_loc = tree.tokenLocation(0, node.lastToken());
const GetDocumentSymbolsContext = struct {
prev_loc: offsets.TokenLocation = .{
.line = 0,
.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{
.start = .{
.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) {
std.log.debug(.analysis, "NULL NAME: {}\n", .{node.id});
}
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 = "",
(try context.symbols.addOne()).* = .{
.name = name,
.kind = switch (node.id) {
.FnProto => .Function,
.VarDecl => .Variable,
@ -1402,26 +1405,36 @@ fn getDocumentSymbolsInternal(allocator: *std.mem.Allocator, tree: *ast.Tree, no
},
.range = range,
.selectionRange = range,
.detail = "",
.children = ch: {
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;
while (node.iterate(index)) |child| : (index += 1) {
try addOutlineNodes(allocator, &children, tree, child);
try addOutlineNodes(allocator, tree, child, &child_context);
}
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);
pub fn getDocumentSymbols(allocator: *std.mem.Allocator, tree: *ast.Tree, encoding: offsets.Encoding) ![]types.DocumentSymbol {
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| {
_ = try symbols.append(try getDocumentSymbolsInternal(allocator, tree, node));
try getDocumentSymbolsInternal(allocator, tree, node, &context);
}
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;
return tree.tokenLocation(0, self.nameToken());
return try offsets.tokenRelativeLocation(tree, 0, self.nameToken(), encoding);
}
fn isPublic(self: DeclWithHandle) bool {

View File

@ -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();
}

View File

@ -483,15 +483,15 @@ fn gotoDefinitionSymbol(id: types.RequestId, arena: *std.heap.ArenaAllocator, de
if (resolve_alias) {
if (try analysis.resolveVarDeclAlias(&document_store, arena, .{ .node = node, .handle = handle })) |result| {
handle = result.handle;
break :block result.location();
break :block result.location(offset_encoding) catch return;
}
}
const name_token = analysis.getDeclNameToken(handle.tree, node) orelse
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{
@ -499,7 +499,16 @@ fn gotoDefinitionSymbol(id: types.RequestId, arena: *std.heap.ArenaAllocator, de
.result = .{
.Location = .{
.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 {
try send(arena, types.Response{
.id = id,
.result = .{ .DocumentSymbols = try analysis.getDocumentSymbols(&arena.allocator, handle.tree) },
.result = .{ .DocumentSymbols = try analysis.getDocumentSymbols(&arena.allocator, handle.tree, offset_encoding) },
});
}

View File

@ -56,6 +56,18 @@ pub fn documentPosition(doc: types.TextDocument, position: types.Position, encod
pub const TokenLocation = struct {
line: 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 {
@ -64,6 +76,7 @@ pub fn tokenRelativeLocation(tree: *std.zig.ast.Tree, start_index: usize, token:
var loc = TokenLocation{
.line = 0,
.column = 0,
.offset = 0,
};
const token_start = token_loc.start;
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;
}

View File

@ -317,7 +317,7 @@ pub const DocumentSymbol = struct {
deprecated: bool = false,
range: Range,
selectionRange: Range,
children: []DocumentSymbol = &[_]DocumentSymbol{},
children: []const DocumentSymbol = &[_]DocumentSymbol{},
};
pub const ShowMessageParams = struct {