Added references.zig, use it from rename.zig
This commit is contained in:
parent
cbfb316763
commit
0f7a384b39
@ -89,7 +89,7 @@ var client_capabilities = ClientCapabilities{};
|
|||||||
var offset_encoding = offsets.Encoding.utf16;
|
var offset_encoding = offsets.Encoding.utf16;
|
||||||
|
|
||||||
const initialize_capabilities =
|
const initialize_capabilities =
|
||||||
\\"capabilities": {"signatureHelpProvider": {"triggerCharacters": ["(",","]},"textDocumentSync": 1,"renameProvider":true,"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": true,"documentRangeFormattingProvider": false,"foldingRangeProvider": false,"selectionRangeProvider": false,"workspaceSymbolProvider": false,"rangeProvider": false,"documentProvider": true,"workspace": {"workspaceFolders": {"supported": true,"changeNotifications": true}},"semanticTokensProvider": {"documentProvider": true,"legend": {"tokenTypes": ["namespace","type","struct","enum","union","parameter","variable","tagField","field","errorTag","function","keyword","comment","string","number","operator","builtin","label"],"tokenModifiers": ["definition","async","documentation", "generic"]}}}}}
|
\\"capabilities": {"signatureHelpProvider": {"triggerCharacters": ["(",","]},"textDocumentSync": 1,"renameProvider":true,"completionProvider": {"resolveProvider": false,"triggerCharacters": [".",":","@"]},"documentHighlightProvider": false,"hoverProvider": true,"codeActionProvider": false,"declarationProvider": true,"definitionProvider": true,"typeDefinitionProvider": true,"implementationProvider": false,"referencesProvider": true,"documentSymbolProvider": true,"colorProvider": false,"documentFormattingProvider": true,"documentRangeFormattingProvider": false,"foldingRangeProvider": false,"selectionRangeProvider": false,"workspaceSymbolProvider": false,"rangeProvider": false,"documentProvider": true,"workspace": {"workspaceFolders": {"supported": true,"changeNotifications": true}},"semanticTokensProvider": {"documentProvider": true,"legend": {"tokenTypes": ["namespace","type","struct","enum","union","parameter","variable","tagField","field","errorTag","function","keyword","comment","string","number","operator","builtin","label"],"tokenModifiers": ["definition","async","documentation", "generic"]}}}}}
|
||||||
;
|
;
|
||||||
|
|
||||||
const initialize_response = ",\"result\": {" ++ initialize_capabilities;
|
const initialize_response = ",\"result\": {" ++ initialize_capabilities;
|
||||||
|
410
src/references.zig
Normal file
410
src/references.zig
Normal file
@ -0,0 +1,410 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const DocumentStore = @import("document_store.zig");
|
||||||
|
const analysis = @import("analysis.zig");
|
||||||
|
const types = @import("types.zig");
|
||||||
|
const offsets = @import("offsets.zig");
|
||||||
|
|
||||||
|
const ast = std.zig.ast;
|
||||||
|
|
||||||
|
fn tokenReference(
|
||||||
|
handle: *DocumentStore.Handle,
|
||||||
|
tok: ast.TokenIndex,
|
||||||
|
encoding: offsets.Encoding,
|
||||||
|
context: var,
|
||||||
|
comptime handler: var,
|
||||||
|
) !void {
|
||||||
|
const loc = offsets.tokenRelativeLocation(handle.tree, 0, tok, encoding) catch return;
|
||||||
|
try handler(context, types.Location{
|
||||||
|
.uri = handle.uri(),
|
||||||
|
.range = .{
|
||||||
|
.start = .{
|
||||||
|
.line = @intCast(types.Integer, loc.line),
|
||||||
|
.character = @intCast(types.Integer, loc.column),
|
||||||
|
},
|
||||||
|
.end = .{
|
||||||
|
.line = @intCast(types.Integer, loc.line),
|
||||||
|
.character = @intCast(types.Integer, loc.column + offsets.tokenLength(handle.tree, tok, encoding)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn labelReferences(
|
||||||
|
arena: *std.heap.ArenaAllocator,
|
||||||
|
decl: analysis.DeclWithHandle,
|
||||||
|
encoding: offsets.Encoding,
|
||||||
|
include_decl: bool,
|
||||||
|
context: var,
|
||||||
|
comptime handler: var,
|
||||||
|
) !void {
|
||||||
|
std.debug.assert(decl.decl.* == .label_decl);
|
||||||
|
const handle = decl.handle;
|
||||||
|
|
||||||
|
// Find while / for / block from label -> iterate over children nodes, find break and continues, change their labels if they match.
|
||||||
|
// This case can be implemented just by scanning tokens.
|
||||||
|
const first_tok = decl.decl.label_decl.firstToken();
|
||||||
|
const last_tok = decl.decl.label_decl.lastToken();
|
||||||
|
|
||||||
|
if (include_decl) {
|
||||||
|
// The first token is always going to be the label
|
||||||
|
try tokenReference(handle, first_tok, encoding, context, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
var curr_tok = first_tok + 1;
|
||||||
|
while (curr_tok < last_tok - 2) : (curr_tok += 1) {
|
||||||
|
const curr_id = handle.tree.token_ids[curr_tok];
|
||||||
|
if ((curr_id == .Keyword_break or curr_id == .Keyword_continue) and handle.tree.token_ids[curr_tok + 1] == .Colon and
|
||||||
|
handle.tree.token_ids[curr_tok + 2] == .Identifier)
|
||||||
|
{
|
||||||
|
if (std.mem.eql(u8, handle.tree.tokenSlice(curr_tok + 2), handle.tree.tokenSlice(first_tok))) {
|
||||||
|
try tokenReference(handle, first_tok, encoding, context, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn symbolReferencesInternal(
|
||||||
|
arena: *std.heap.ArenaAllocator,
|
||||||
|
store: *DocumentStore,
|
||||||
|
node_handle: analysis.NodeWithHandle,
|
||||||
|
decl: analysis.DeclWithHandle,
|
||||||
|
encoding: offsets.Encoding,
|
||||||
|
context: var,
|
||||||
|
comptime handler: var,
|
||||||
|
) error{OutOfMemory}!void {
|
||||||
|
const node = node_handle.node;
|
||||||
|
const handle = node_handle.handle;
|
||||||
|
|
||||||
|
switch (node.id) {
|
||||||
|
.ContainerDecl, .Root, .Block => {
|
||||||
|
var idx: usize = 0;
|
||||||
|
while (node.iterate(idx)) |child| : (idx += 1) {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = child, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.VarDecl => {
|
||||||
|
const var_decl = node.cast(ast.Node.VarDecl).?;
|
||||||
|
if (var_decl.type_node) |type_node| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = type_node, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
if (var_decl.init_node) |init_node| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = init_node, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.Use => {
|
||||||
|
const use = node.cast(ast.Node.Use).?;
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = use.expr, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
},
|
||||||
|
.ContainerField => {
|
||||||
|
const field = node.cast(ast.Node.ContainerField).?;
|
||||||
|
if (field.type_expr) |type_node| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = type_node, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
if (field.value_expr) |init_node| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = init_node, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.Identifier => {
|
||||||
|
if (try analysis.lookupSymbolGlobal(store, arena, handle, handle.tree.getNodeSource(node), handle.tree.token_locs[node.firstToken()].start)) |child| {
|
||||||
|
if (std.meta.eql(decl, child)) {
|
||||||
|
try tokenReference(handle, node.firstToken(), encoding, context, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.FnProto => {
|
||||||
|
const fn_proto = node.cast(ast.Node.FnProto).?;
|
||||||
|
for (fn_proto.paramsConst()) |param| {
|
||||||
|
switch (param.param_type) {
|
||||||
|
.type_expr => |type_node| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = type_node, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (fn_proto.return_type) {
|
||||||
|
.Explicit, .InferErrorSet => |type_node| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = type_node, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
if (fn_proto.align_expr) |align_expr| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = align_expr, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
if (fn_proto.section_expr) |section_expr| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = section_expr, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
if (fn_proto.callconv_expr) |callconv_expr| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = callconv_expr, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
if (fn_proto.body_node) |body| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = body, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.AnyFrameType => {
|
||||||
|
const anyframe_type = node.cast(ast.Node.AnyFrameType).?;
|
||||||
|
if (anyframe_type.result) |result| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = result.return_type, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.Defer => {
|
||||||
|
const defer_node = node.cast(ast.Node.Defer).?;
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = defer_node.expr, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
},
|
||||||
|
.Comptime => {
|
||||||
|
const comptime_node = node.cast(ast.Node.Comptime).?;
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = comptime_node.expr, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
},
|
||||||
|
.Nosuspend => {
|
||||||
|
const nosuspend_node = node.cast(ast.Node.Nosuspend).?;
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = nosuspend_node.expr, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
},
|
||||||
|
.Switch => {
|
||||||
|
// TODO When renaming a union(enum) field, also rename switch items that refer to it.
|
||||||
|
const switch_node = node.cast(ast.Node.Switch).?;
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = switch_node.expr, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
for (switch_node.casesConst()) |case| {
|
||||||
|
if (case.*.cast(ast.Node.SwitchCase)) |case_node| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = case_node.expr, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.While => {
|
||||||
|
const while_node = node.cast(ast.Node.While).?;
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = while_node.condition, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
if (while_node.continue_expr) |cont_expr| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = cont_expr, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = while_node.body, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
if (while_node.@"else") |else_node| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = else_node.body, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.For => {
|
||||||
|
const for_node = node.cast(ast.Node.For).?;
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = for_node.array_expr, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = for_node.body, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
if (for_node.@"else") |else_node| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = else_node.body, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.If => {
|
||||||
|
const if_node = node.cast(ast.Node.If).?;
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = if_node.condition, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = if_node.body, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
if (if_node.@"else") |else_node| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = else_node.body, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.InfixOp => {
|
||||||
|
const infix_op = node.cast(ast.Node.InfixOp).?;
|
||||||
|
switch (infix_op.op) {
|
||||||
|
.Period => {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = infix_op.lhs, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
|
||||||
|
const rhs_str = analysis.nodeToString(handle.tree, infix_op.rhs) orelse return;
|
||||||
|
var bound_type_params = analysis.BoundTypeParams.init(&arena.allocator);
|
||||||
|
const left_type = try analysis.resolveFieldAccessLhsType(
|
||||||
|
store,
|
||||||
|
arena,
|
||||||
|
(try analysis.resolveTypeOfNodeInternal(store, arena, .{
|
||||||
|
.node = infix_op.lhs,
|
||||||
|
.handle = handle,
|
||||||
|
}, &bound_type_params)) orelse return,
|
||||||
|
&bound_type_params,
|
||||||
|
);
|
||||||
|
|
||||||
|
const left_type_node = switch (left_type.type.data) {
|
||||||
|
.other => |n| n,
|
||||||
|
else => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (try analysis.lookupSymbolContainer(
|
||||||
|
store,
|
||||||
|
arena,
|
||||||
|
.{ .node = left_type_node, .handle = left_type.handle },
|
||||||
|
rhs_str,
|
||||||
|
!left_type.type.is_type_val,
|
||||||
|
)) |child| {
|
||||||
|
if (std.meta.eql(child, decl)) {
|
||||||
|
try tokenReference(handle, infix_op.rhs.firstToken(), encoding, context, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = infix_op.lhs, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = infix_op.rhs, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.PrefixOp => {
|
||||||
|
const prefix_op = node.cast(ast.Node.PrefixOp).?;
|
||||||
|
switch (prefix_op.op) {
|
||||||
|
.ArrayType => |info| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = info.len_expr, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
if (info.sentinel) |sentinel| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = sentinel, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.PtrType, .SliceType => |info| {
|
||||||
|
if (info.align_info) |align_info| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = align_info.node, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
if (align_info.bit_range) |range| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = range.start, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = range.end, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (info.sentinel) |sentinel| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = sentinel, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = prefix_op.rhs, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
},
|
||||||
|
.FieldInitializer => {
|
||||||
|
// TODO Rename field initializer names when needed
|
||||||
|
const field_init = node.cast(ast.Node.FieldInitializer).?;
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = field_init.expr, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
},
|
||||||
|
.ArrayInitializer => {
|
||||||
|
const array_init = node.cast(ast.Node.ArrayInitializer).?;
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = array_init.lhs, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
for (array_init.listConst()) |child| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = child, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.ArrayInitializerDot => {
|
||||||
|
const array_init = node.cast(ast.Node.ArrayInitializerDot).?;
|
||||||
|
for (array_init.listConst()) |child| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = child, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.StructInitializer => {
|
||||||
|
// TODO Rename field initializer names when needed
|
||||||
|
const struct_init = node.cast(ast.Node.StructInitializer).?;
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = struct_init.lhs, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
for (struct_init.listConst()) |child| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = child, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.StructInitializerDot => {
|
||||||
|
const struct_init = node.cast(ast.Node.StructInitializerDot).?;
|
||||||
|
for (struct_init.listConst()) |child| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = child, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.Call => {
|
||||||
|
const call = node.cast(ast.Node.Call).?;
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = call.lhs, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
for (call.paramsConst()) |param| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = param, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.SuffixOp => {
|
||||||
|
const suffix_op = node.cast(ast.Node.SuffixOp).?;
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = suffix_op.lhs, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
switch (suffix_op.op) {
|
||||||
|
.ArrayAccess => |acc| try symbolReferencesInternal(arena, store, .{ .node = acc, .handle = handle }, decl, encoding, context, handler),
|
||||||
|
.Slice => |sl| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = sl.start, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
if (sl.end) |end| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = end, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
if (sl.sentinel) |sentinel| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = sentinel, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.GroupedExpression => {
|
||||||
|
const grouped = node.cast(ast.Node.GroupedExpression).?;
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = grouped.expr, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
},
|
||||||
|
.ControlFlowExpression => {
|
||||||
|
const cfe = node.cast(ast.Node.ControlFlowExpression).?;
|
||||||
|
if (cfe.rhs) |rhs| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = rhs, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.Suspend => {
|
||||||
|
const suspend_node = node.cast(ast.Node.Suspend).?;
|
||||||
|
if (suspend_node.body) |body| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = body, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.BuiltinCall => {
|
||||||
|
const builtin_call = node.cast(ast.Node.BuiltinCall).?;
|
||||||
|
for (builtin_call.paramsConst()) |param| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = param, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// TODO Inline asm expr
|
||||||
|
.TestDecl => {
|
||||||
|
const test_decl = node.cast(ast.Node.TestDecl).?;
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = test_decl.body_node, .handle = handle }, decl, encoding, context, handler);
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn symbolReferences(
|
||||||
|
arena: *std.heap.ArenaAllocator,
|
||||||
|
store: *DocumentStore,
|
||||||
|
decl_handle: analysis.DeclWithHandle,
|
||||||
|
encoding: offsets.Encoding,
|
||||||
|
include_decl: bool,
|
||||||
|
context: var,
|
||||||
|
comptime handler: var,
|
||||||
|
) !void {
|
||||||
|
std.debug.assert(decl_handle.decl.* != .label_decl);
|
||||||
|
const curr_handle = decl_handle.handle;
|
||||||
|
|
||||||
|
switch (decl_handle.decl.*) {
|
||||||
|
.ast_node => |decl_node| {
|
||||||
|
var handles = std.ArrayList(*DocumentStore.Handle).init(&arena.allocator);
|
||||||
|
var handle_it = store.handles.iterator();
|
||||||
|
while (handle_it.next()) |entry| {
|
||||||
|
try handles.append(entry.value);
|
||||||
|
}
|
||||||
|
for (handles.items) |handle| {
|
||||||
|
if (include_decl and handle == curr_handle) {
|
||||||
|
try tokenReference(curr_handle, decl_handle.nameToken(), encoding, context, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = &handle.tree.root_node.base, .handle = handle }, decl_handle, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.param_decl => |param| {
|
||||||
|
// Rename the param tok.
|
||||||
|
if (include_decl) {
|
||||||
|
try tokenReference(curr_handle, decl_handle.nameToken(), encoding, context, handler);
|
||||||
|
}
|
||||||
|
const fn_node = loop: for (curr_handle.document_scope.scopes) |scope| {
|
||||||
|
switch (scope.data) {
|
||||||
|
.function => |proto| {
|
||||||
|
const fn_proto = proto.cast(std.zig.ast.Node.FnProto).?;
|
||||||
|
for (fn_proto.paramsConst()) |*candidate| {
|
||||||
|
if (candidate == param)
|
||||||
|
break :loop fn_proto;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std.log.warn(.references, "Could not find param decl's function", .{});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if (fn_node.body_node) |body| {
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = body, .handle = curr_handle }, decl_handle, encoding, context, handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.pointer_payload, .array_payload, .switch_payload => {
|
||||||
|
if (include_decl) {
|
||||||
|
try tokenReference(curr_handle, decl_handle.nameToken(), encoding, context, handler);
|
||||||
|
}
|
||||||
|
try symbolReferencesInternal(arena, store, .{ .node = &curr_handle.tree.root_node.base, .handle = curr_handle }, decl_handle, encoding, context, handler);
|
||||||
|
},
|
||||||
|
.label_decl => unreachable,
|
||||||
|
}
|
||||||
|
}
|
415
src/rename.zig
415
src/rename.zig
@ -1,340 +1,30 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const DocumentStore = @import("document_store.zig");
|
const DocumentStore = @import("document_store.zig");
|
||||||
const analysis = @import("analysis.zig");
|
const analysis = @import("analysis.zig");
|
||||||
|
const references = @import("references.zig");
|
||||||
const types = @import("types.zig");
|
const types = @import("types.zig");
|
||||||
const offsets = @import("offsets.zig");
|
const offsets = @import("offsets.zig");
|
||||||
|
|
||||||
const ast = std.zig.ast;
|
const ast = std.zig.ast;
|
||||||
|
|
||||||
fn renameToken(handle: *DocumentStore.Handle, tok: ast.TokenIndex, new_name: []const u8, edits: *std.ArrayList(types.TextEdit), encoding: offsets.Encoding) !void {
|
// TODO Use an map to array lists and collect at the end instead?
|
||||||
const loc = offsets.tokenRelativeLocation(handle.tree, 0, tok, encoding) catch return;
|
const RefHandlerContext = struct {
|
||||||
(try edits.addOne()).* = .{
|
edits: *std.StringHashMap([]types.TextEdit),
|
||||||
.range = .{
|
allocator: *std.mem.Allocator,
|
||||||
.start = .{
|
|
||||||
.line = @intCast(types.Integer, loc.line),
|
|
||||||
.character = @intCast(types.Integer, loc.column),
|
|
||||||
},
|
|
||||||
.end = .{
|
|
||||||
.line = @intCast(types.Integer, loc.line),
|
|
||||||
.character = @intCast(types.Integer, loc.column + offsets.tokenLength(handle.tree, tok, encoding)),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.newText = new_name,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn renameLabel(arena: *std.heap.ArenaAllocator, decl: analysis.DeclWithHandle, new_name: []const u8, edits: *std.StringHashMap([]types.TextEdit), encoding: offsets.Encoding) !void {
|
|
||||||
std.debug.assert(decl.decl.* == .label_decl);
|
|
||||||
const handle = decl.handle;
|
|
||||||
|
|
||||||
var text_edits = std.ArrayList(types.TextEdit).init(&arena.allocator);
|
|
||||||
|
|
||||||
// Find while / for / block from label -> iterate over children nodes, find break and continues, change their labels if they match.
|
|
||||||
// This case can be implemented just by scanning tokens.
|
|
||||||
const first_tok = decl.decl.label_decl.firstToken();
|
|
||||||
const last_tok = decl.decl.label_decl.lastToken();
|
|
||||||
|
|
||||||
// The first token is always going to be the label
|
|
||||||
try renameToken(handle, first_tok, new_name, &text_edits, encoding);
|
|
||||||
|
|
||||||
var curr_tok = first_tok + 1;
|
|
||||||
while (curr_tok < last_tok - 2) : (curr_tok += 1) {
|
|
||||||
const curr_id = handle.tree.token_ids[curr_tok];
|
|
||||||
if ((curr_id == .Keyword_break or curr_id == .Keyword_continue) and handle.tree.token_ids[curr_tok + 1] == .Colon and
|
|
||||||
handle.tree.token_ids[curr_tok + 2] == .Identifier)
|
|
||||||
{
|
|
||||||
if (std.mem.eql(u8, handle.tree.tokenSlice(curr_tok + 2), handle.tree.tokenSlice(first_tok))) {
|
|
||||||
try renameToken(handle, curr_tok + 2, new_name, &text_edits, encoding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try edits.putNoClobber(handle.uri(), text_edits.items);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn renameSymbolInternal(
|
|
||||||
arena: *std.heap.ArenaAllocator,
|
|
||||||
store: *DocumentStore,
|
|
||||||
node_handle: analysis.NodeWithHandle,
|
|
||||||
decl: analysis.DeclWithHandle,
|
|
||||||
new_name: []const u8,
|
new_name: []const u8,
|
||||||
edits: *std.ArrayList(types.TextEdit),
|
};
|
||||||
encoding: offsets.Encoding,
|
|
||||||
) error{OutOfMemory}!void {
|
|
||||||
const node = node_handle.node;
|
|
||||||
const handle = node_handle.handle;
|
|
||||||
|
|
||||||
switch (node.id) {
|
fn refHandler(context: RefHandlerContext, loc: types.Location) !void {
|
||||||
.ContainerDecl, .Root, .Block => {
|
var text_edits = if (context.edits.getValue(loc.uri)) |slice|
|
||||||
var idx: usize = 0;
|
std.ArrayList(types.TextEdit).fromOwnedSlice(context.allocator, slice)
|
||||||
while (node.iterate(idx)) |child| : (idx += 1) {
|
else
|
||||||
try renameSymbolInternal(arena, store, .{ .node = child, .handle = handle }, decl, new_name, edits, encoding);
|
std.ArrayList(types.TextEdit).init(context.allocator);
|
||||||
}
|
|
||||||
},
|
|
||||||
.VarDecl => {
|
|
||||||
const var_decl = node.cast(ast.Node.VarDecl).?;
|
|
||||||
if (var_decl.type_node) |type_node| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = type_node, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
if (var_decl.init_node) |init_node| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = init_node, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.Use => {
|
|
||||||
const use = node.cast(ast.Node.Use).?;
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = use.expr, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
},
|
|
||||||
.ContainerField => {
|
|
||||||
const field = node.cast(ast.Node.ContainerField).?;
|
|
||||||
if (field.type_expr) |type_node| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = type_node, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
if (field.value_expr) |init_node| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = init_node, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.Identifier => {
|
|
||||||
if (try analysis.lookupSymbolGlobal(store, arena, handle, handle.tree.getNodeSource(node), handle.tree.token_locs[node.firstToken()].start)) |child| {
|
|
||||||
if (std.meta.eql(decl, child)) {
|
|
||||||
try renameToken(handle, node.firstToken(), new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.FnProto => {
|
|
||||||
const fn_proto = node.cast(ast.Node.FnProto).?;
|
|
||||||
for (fn_proto.paramsConst()) |param| {
|
|
||||||
switch (param.param_type) {
|
|
||||||
.type_expr => |type_node| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = type_node, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (fn_proto.return_type) {
|
|
||||||
.Explicit, .InferErrorSet => |type_node| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = type_node, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
if (fn_proto.align_expr) |align_expr| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = align_expr, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
if (fn_proto.section_expr) |section_expr| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = section_expr, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
if (fn_proto.callconv_expr) |callconv_expr| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = callconv_expr, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
if (fn_proto.body_node) |body| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = body, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.AnyFrameType => {
|
|
||||||
const anyframe_type = node.cast(ast.Node.AnyFrameType).?;
|
|
||||||
if (anyframe_type.result) |result| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = result.return_type, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.Defer => {
|
|
||||||
const defer_node = node.cast(ast.Node.Defer).?;
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = defer_node.expr, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
},
|
|
||||||
.Comptime => {
|
|
||||||
const comptime_node = node.cast(ast.Node.Comptime).?;
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = comptime_node.expr, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
},
|
|
||||||
.Nosuspend => {
|
|
||||||
const nosuspend_node = node.cast(ast.Node.Nosuspend).?;
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = nosuspend_node.expr, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
},
|
|
||||||
.Switch => {
|
|
||||||
// TODO When renaming a union(enum) field, also rename switch items that refer to it.
|
|
||||||
const switch_node = node.cast(ast.Node.Switch).?;
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = switch_node.expr, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
for (switch_node.casesConst()) |case| {
|
|
||||||
if (case.*.cast(ast.Node.SwitchCase)) |case_node| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = case_node.expr, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.While => {
|
|
||||||
const while_node = node.cast(ast.Node.While).?;
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = while_node.condition, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
if (while_node.continue_expr) |cont_expr| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = cont_expr, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = while_node.body, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
if (while_node.@"else") |else_node| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = else_node.body, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.For => {
|
|
||||||
const for_node = node.cast(ast.Node.For).?;
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = for_node.array_expr, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = for_node.body, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
if (for_node.@"else") |else_node| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = else_node.body, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.If => {
|
|
||||||
const if_node = node.cast(ast.Node.If).?;
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = if_node.condition, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = if_node.body, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
if (if_node.@"else") |else_node| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = else_node.body, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.InfixOp => {
|
|
||||||
const infix_op = node.cast(ast.Node.InfixOp).?;
|
|
||||||
switch (infix_op.op) {
|
|
||||||
.Period => {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = infix_op.lhs, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
|
|
||||||
const rhs_str = analysis.nodeToString(handle.tree, infix_op.rhs) orelse return;
|
(try text_edits.addOne()).* = .{
|
||||||
var bound_type_params = analysis.BoundTypeParams.init(&arena.allocator);
|
.range = loc.range,
|
||||||
const left_type = try analysis.resolveFieldAccessLhsType(
|
.newText = context.new_name,
|
||||||
store,
|
};
|
||||||
arena,
|
_ = try context.edits.put(loc.uri, text_edits.toOwnedSlice());
|
||||||
(try analysis.resolveTypeOfNodeInternal(store, arena, .{
|
|
||||||
.node = infix_op.lhs,
|
|
||||||
.handle = handle,
|
|
||||||
}, &bound_type_params)) orelse return,
|
|
||||||
&bound_type_params,
|
|
||||||
);
|
|
||||||
|
|
||||||
const left_type_node = switch (left_type.type.data) {
|
|
||||||
.other => |n| n,
|
|
||||||
else => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (try analysis.lookupSymbolContainer(
|
|
||||||
store,
|
|
||||||
arena,
|
|
||||||
.{ .node = left_type_node, .handle = left_type.handle },
|
|
||||||
rhs_str,
|
|
||||||
!left_type.type.is_type_val,
|
|
||||||
)) |child| {
|
|
||||||
if (std.meta.eql(child, decl)) {
|
|
||||||
try renameToken(handle, infix_op.rhs.firstToken(), new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = infix_op.lhs, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = infix_op.rhs, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.PrefixOp => {
|
|
||||||
const prefix_op = node.cast(ast.Node.PrefixOp).?;
|
|
||||||
switch (prefix_op.op) {
|
|
||||||
.ArrayType => |info| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = info.len_expr, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
if (info.sentinel) |sentinel| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = sentinel, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.PtrType, .SliceType => |info| {
|
|
||||||
if (info.align_info) |align_info| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = align_info.node, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
if (align_info.bit_range) |range| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = range.start, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = range.end, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (info.sentinel) |sentinel| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = sentinel, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = prefix_op.rhs, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
},
|
|
||||||
.FieldInitializer => {
|
|
||||||
// TODO Rename field initializer names when needed
|
|
||||||
const field_init = node.cast(ast.Node.FieldInitializer).?;
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = field_init.expr, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
},
|
|
||||||
.ArrayInitializer => {
|
|
||||||
const array_init = node.cast(ast.Node.ArrayInitializer).?;
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = array_init.lhs, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
for (array_init.listConst()) |child| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = child, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.ArrayInitializerDot => {
|
|
||||||
const array_init = node.cast(ast.Node.ArrayInitializerDot).?;
|
|
||||||
for (array_init.listConst()) |child| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = child, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.StructInitializer => {
|
|
||||||
// TODO Rename field initializer names when needed
|
|
||||||
const struct_init = node.cast(ast.Node.StructInitializer).?;
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = struct_init.lhs, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
for (struct_init.listConst()) |child| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = child, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.StructInitializerDot => {
|
|
||||||
const struct_init = node.cast(ast.Node.StructInitializerDot).?;
|
|
||||||
for (struct_init.listConst()) |child| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = child, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.Call => {
|
|
||||||
const call = node.cast(ast.Node.Call).?;
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = call.lhs, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
for (call.paramsConst()) |param| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = param, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.SuffixOp => {
|
|
||||||
const suffix_op = node.cast(ast.Node.SuffixOp).?;
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = suffix_op.lhs, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
switch (suffix_op.op) {
|
|
||||||
.ArrayAccess => |acc| try renameSymbolInternal(arena, store, .{ .node = acc, .handle = handle }, decl, new_name, edits, encoding),
|
|
||||||
.Slice => |sl| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = sl.start, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
if (sl.end) |end| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = end, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
if (sl.sentinel) |sentinel| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = sentinel, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.GroupedExpression => {
|
|
||||||
const grouped = node.cast(ast.Node.GroupedExpression).?;
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = grouped.expr, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
},
|
|
||||||
.ControlFlowExpression => {
|
|
||||||
const cfe = node.cast(ast.Node.ControlFlowExpression).?;
|
|
||||||
if (cfe.rhs) |rhs| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = rhs, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.Suspend => {
|
|
||||||
const suspend_node = node.cast(ast.Node.Suspend).?;
|
|
||||||
if (suspend_node.body) |body| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = body, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.BuiltinCall => {
|
|
||||||
const builtin_call = node.cast(ast.Node.BuiltinCall).?;
|
|
||||||
for (builtin_call.paramsConst()) |param| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = param, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// TODO Inline asm expr
|
|
||||||
.TestDecl => {
|
|
||||||
const test_decl = node.cast(ast.Node.TestDecl).?;
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = test_decl.body_node, .handle = handle }, decl, new_name, edits, encoding);
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn renameSymbol(
|
pub fn renameSymbol(
|
||||||
@ -346,57 +36,24 @@ pub fn renameSymbol(
|
|||||||
encoding: offsets.Encoding,
|
encoding: offsets.Encoding,
|
||||||
) !void {
|
) !void {
|
||||||
std.debug.assert(decl_handle.decl.* != .label_decl);
|
std.debug.assert(decl_handle.decl.* != .label_decl);
|
||||||
const curr_handle = decl_handle.handle;
|
try references.symbolReferences(arena, store, decl_handle, encoding, true, RefHandlerContext{
|
||||||
|
.edits = edits,
|
||||||
switch (decl_handle.decl.*) {
|
.allocator = &arena.allocator,
|
||||||
.ast_node => |decl_node| {
|
.new_name = new_name,
|
||||||
var handles = std.ArrayList(*DocumentStore.Handle).init(&arena.allocator);
|
}, refHandler);
|
||||||
var handle_it = store.handles.iterator();
|
}
|
||||||
while (handle_it.next()) |entry| {
|
|
||||||
try handles.append(entry.value);
|
pub fn renameLabel(
|
||||||
}
|
arena: *std.heap.ArenaAllocator,
|
||||||
for (handles.items) |handle| {
|
decl_handle: analysis.DeclWithHandle,
|
||||||
var text_edits = std.ArrayList(types.TextEdit).init(&arena.allocator);
|
new_name: []const u8,
|
||||||
if (handle == curr_handle) {
|
edits: *std.StringHashMap([]types.TextEdit),
|
||||||
try renameToken(curr_handle, decl_handle.nameToken(), new_name, &text_edits, encoding);
|
encoding: offsets.Encoding,
|
||||||
}
|
) !void {
|
||||||
|
std.debug.assert(decl_handle.decl.* == .label_decl);
|
||||||
try renameSymbolInternal(arena, store, .{ .node = &handle.tree.root_node.base, .handle = handle }, decl_handle, new_name, &text_edits, encoding);
|
try references.labelReferences(arena, decl_handle, encoding, true, RefHandlerContext{
|
||||||
if (text_edits.items.len > 0) {
|
.edits = edits,
|
||||||
try edits.putNoClobber(handle.uri(), text_edits.items);
|
.allocator = &arena.allocator,
|
||||||
}
|
.new_name = new_name,
|
||||||
}
|
}, refHandler);
|
||||||
},
|
|
||||||
.param_decl => |param| {
|
|
||||||
var curr_doc_text_edits = std.ArrayList(types.TextEdit).init(&arena.allocator);
|
|
||||||
// Rename the param tok.
|
|
||||||
try renameToken(curr_handle, decl_handle.nameToken(), new_name, &curr_doc_text_edits, encoding);
|
|
||||||
const fn_node = loop: for (curr_handle.document_scope.scopes) |scope| {
|
|
||||||
switch (scope.data) {
|
|
||||||
.function => |proto| {
|
|
||||||
const fn_proto = proto.cast(std.zig.ast.Node.FnProto).?;
|
|
||||||
for (fn_proto.paramsConst()) |*candidate| {
|
|
||||||
if (candidate == param)
|
|
||||||
break :loop fn_proto;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std.log.warn(.rename, "Could not find param decl's function", .{});
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if (fn_node.body_node) |body| {
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = body, .handle = curr_handle }, decl_handle, new_name, &curr_doc_text_edits, encoding);
|
|
||||||
}
|
|
||||||
try edits.putNoClobber(curr_handle.uri(), curr_doc_text_edits.items);
|
|
||||||
},
|
|
||||||
.pointer_payload, .array_payload, .switch_payload => {
|
|
||||||
var curr_doc_text_edits = std.ArrayList(types.TextEdit).init(&arena.allocator);
|
|
||||||
try renameToken(curr_handle, decl_handle.nameToken(), new_name, &curr_doc_text_edits, encoding);
|
|
||||||
try renameSymbolInternal(arena, store, .{ .node = &curr_handle.tree.root_node.base, .handle = curr_handle }, decl_handle, new_name, &curr_doc_text_edits, encoding);
|
|
||||||
try edits.putNoClobber(curr_handle.uri(), curr_doc_text_edits.items);
|
|
||||||
},
|
|
||||||
.label_decl => unreachable,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -208,3 +208,11 @@ pub const Rename = struct {
|
|||||||
newName: types.String,
|
newName: types.String,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Reference = struct {
|
||||||
|
params: struct {
|
||||||
|
textDocument: TextDocumentIdentifier,
|
||||||
|
position: types.Position,
|
||||||
|
includeDeclaration: bool,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user