diff --git a/src/analysis.zig b/src/analysis.zig index e5264e6..3c5ec53 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -181,25 +181,6 @@ fn getDeclName(tree: *ast.Tree, node: *ast.Node) ?[]const u8 { }; } -/// Gets the child of node -pub fn getChild(tree: *ast.Tree, node: *ast.Node, name: []const u8) ?*ast.Node { - var child_idx: usize = 0; - while (node.iterate(child_idx)) |child| : (child_idx += 1) { - const child_name = getDeclName(tree, child) orelse continue; - if (std.mem.eql(u8, child_name, name)) return child; - } - return null; -} - -/// Gets the child of slice -pub fn getChildOfSlice(tree: *ast.Tree, nodes: []*ast.Node, name: []const u8) ?*ast.Node { - for (nodes) |child| { - const child_name = getDeclName(tree, child) orelse continue; - if (std.mem.eql(u8, child_name, name)) return child; - } - return null; -} - fn findReturnStatementInternal( tree: *ast.Tree, fn_decl: *ast.Node.FnProto, @@ -378,22 +359,7 @@ pub fn resolveTypeOfNode(store: *DocumentStore, arena: *std.heap.ArenaAllocator, const decl = (try resolveTypeOfNode(store, arena, .{ .node = call.lhs, .handle = handle })) orelse return null; if (decl.node.cast(ast.Node.FnProto)) |fn_decl| { - // @TODO use BoundTypeParams: ParamDecl -> NodeWithHandle or something - // Add type param values to the scope nodes - // const param_len = std.math.min(call.params_len, fn_decl.params_len); - // for (fn_decl.paramsConst()) |decl_param, param_idx| { - // if (param_idx >= param_len) break; - // if (decl_param.name_token == null) continue; - // const type_param = switch (decl_param.param_type) { - // .type_expr => |type_node| if (type_node.cast(ast.Node.Identifier)) |ident| - // std.mem.eql(u8, analysis_ctx.tree().tokenSlice(ident.token), "type") - // else - // false, - // else => false, - // }; - // if (!type_param) continue; - // const call_param_type = (try resolveTypeOfNode(store, arena, .{ .node = call.paramsConst()[param_idx], .handle = handle })) orelse continue; - // } + // TODO Use some type of ParamDecl -> NodeWithHandle map while resolving, and associate type params here. return try resolveReturnType(store, arena, fn_decl, decl.handle); } return decl; @@ -726,57 +692,6 @@ pub fn nodeToString(tree: *ast.Tree, node: *ast.Node) ?[]const u8 { return null; } -fn makeAccessNode(allocator: *std.mem.Allocator, expr: *ast.Node) !*ast.Node { - const suffix_op_node = try allocator.create(ast.Node.SuffixOp); - suffix_op_node.* = .{ - .op = .{ .ArrayAccess = expr }, - .lhs = expr, - .rtoken = expr.lastToken(), - }; - return &suffix_op_node.base; -} - -fn makeUnwrapNode(allocator: *std.mem.Allocator, expr: *ast.Node) !*ast.Node { - const suffix_op_node = try allocator.create(ast.Node.SuffixOp); - suffix_op_node.* = .{ - .op = .UnwrapOptional, - .lhs = expr, - .rtoken = expr.lastToken(), - }; - return &suffix_op_node.base; -} - -fn makeVarDeclNode( - allocator: *std.mem.Allocator, - doc: ?*ast.Node.DocComment, - comptime_token: ?ast.TokenIndex, - name_token: ast.TokenIndex, - type_expr: ?*ast.Node, - init_expr: ?*ast.Node, -) !*ast.Node { - // TODO: This will not be needed anymore when we use out own decl type instead of directly - // repurposing ast nodes. - const var_decl_node = try allocator.create(ast.Node.VarDecl); - var_decl_node.* = .{ - .doc_comments = doc, - .comptime_token = comptime_token, - .visib_token = null, - .thread_local_token = null, - .name_token = name_token, - .eq_token = null, - .mut_token = name_token, - .extern_export_token = null, - .lib_name = null, - .type_node = type_expr, - .align_node = null, - .section_node = null, - .init_node = init_expr, - .semicolon_token = name_token, - }; - - return &var_decl_node.base; -} - fn nodeContainsSourceIndex(tree: *ast.Tree, node: *ast.Node, source_index: usize) bool { const first_token = tree.token_locs[node.firstToken()]; const last_token = tree.token_locs[node.lastToken()]; @@ -1265,7 +1180,8 @@ fn nodeSourceRange(tree: *ast.Tree, node: *ast.Node) SourceRange { // TODO Make enum and error stores per-document // CLear the doc ones before calling this and // rebuild them here. - +// TODO Possibly collect all imports to diff them on changes +// as well fn makeScopeInternal( allocator: *std.mem.Allocator, scopes: *std.ArrayList(Scope), diff --git a/src/main.zig b/src/main.zig index 8a84917..a9786df 100644 --- a/src/main.zig +++ b/src/main.zig @@ -204,7 +204,6 @@ fn containerToCompletion( config: Config, ) !void { // @TODO Something like iterateSymbolsGlobal but for container to support uses. - const container = container_handle.node; const handle = container_handle.handle; @@ -272,20 +271,36 @@ fn nodeToCompletion( const use_snippets = config.enable_snippets and client_capabilities.supports_snippets; const insert_text = if (use_snippets) blk: { - // @TODO Rebuild this. - const skip_self_param = false; - // const skip_self_param = if (func.params_len > 0) param_check: { - // break :param_check switch (func.paramsConst()[0].param_type) { - // .type_expr => |type_node| if (analysis_ctx.in_container == analysis.resolveTypeOfNode(&child_analysis_ctx, type_node)) - // true - // else if (type_node.cast(std.zig.ast.Node.PrefixOp)) |prefix_op| - // prefix_op.op == .PtrType and analysis_ctx.in_container == analysis.resolveTypeOfNode(&child_analysis_ctx, prefix_op.rhs) - // else - // false, - // else => false, - // }; - // } else - // false; + const skip_self_param = if (func.params_len > 0) param_check: { + const in_container = analysis.innermostContainer(handle, handle.tree.token_locs[func.firstToken()].start); + switch (func.paramsConst()[0].param_type) { + .type_expr => |type_node| { + if (try analysis.resolveTypeOfNode(&document_store, arena, .{ + .node = type_node, + .handle = handle, + })) |resolved_type| { + if (in_container.node == resolved_type.node) + break :param_check true; + } + + if (type_node.cast(std.zig.ast.Node.PrefixOp)) |prefix_op| { + if (prefix_op.op == .PtrType) { + if (try analysis.resolveTypeOfNode(&document_store, arena, .{ + .node = prefix_op.rhs, + .handle = handle, + })) |resolved_prefix_op| { + if (in_container.node == resolved_prefix_op.node) + break :param_check true; + } + } + } + + break :param_check false; + }, + else => break :param_check false, + } + } else + false; break :blk try analysis.getFunctionSnippet(&arena.allocator, handle.tree, func, skip_self_param); } else