Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Code actions with autofix #673

Merged
merged 8 commits into from
Sep 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ The following options are currently available.
| --- | --- | --- | --- |
| `enable_snippets` | `bool` | `false` | Enables snippet completions when the client also supports them. |
| `enable_ast_check_diagnostics` | `bool` | `true`| Whether to enable ast-check diagnostics |
| `enable_autofix` | `bool` | `false`| Whether to automatically fix errors on save. Currently supports adding and removing discards. |
| `enable_import_embedfile_argument_completions` | `bool` | `false` | Whether to enable import/embedFile argument completions |
| `zig_lib_path` | `?[]const u8` | `null` | zig library path, e.g. `/path/to/zig/lib/zig`, used to analyze std library imports. |
| `zig_exe_path` | `?[]const u8` | `null` | zig executable path, e.g. `/path/to/zig/zig`, used to run the custom build runner. If `null`, zig is looked up in `PATH`. Will be used to infer the zig standard library path if none is provided. |
Expand Down
5 changes: 5 additions & 0 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
"type": "boolean",
"default": "true"
},
"enable_autofix": {
"description": "Whether to automatically fix errors on save. Currently supports adding and removing discards.",
"type": "boolean",
"default": "false"
},
"enable_import_embedfile_argument_completions": {
"description": "Whether to enable import/embedFile argument completions",
"type": "boolean",
Expand Down
4 changes: 4 additions & 0 deletions src/Config.zig
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ enable_snippets: bool = false,
/// Whether to enable ast-check diagnostics
enable_ast_check_diagnostics: bool = true,

/// Whether to automatically fix errors on save.
/// Currently supports adding and removing discards.
enable_autofix: bool = false,

/// Whether to enable import/embedFile argument completions (NOTE: these are triggered manually as updating the autotrigger characters may cause issues)
enable_import_embedfile_argument_completions: bool = false,

Expand Down
308 changes: 199 additions & 109 deletions src/Server.zig

Large diffs are not rendered by default.

12 changes: 8 additions & 4 deletions src/analysis.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1844,7 +1844,10 @@ pub const Declaration = union(enum) {
/// Index of the ast node
ast_node: Ast.Node.Index,
/// Function parameter
param_decl: Ast.full.FnProto.Param,
param_payload: struct {
param: Ast.full.FnProto.Param,
func: Ast.Node.Index,
},
pointer_payload: struct {
name: Ast.TokenIndex,
condition: Ast.Node.Index,
Expand All @@ -1870,7 +1873,7 @@ pub const DeclWithHandle = struct {
const tree = self.handle.tree;
return switch (self.decl.*) {
.ast_node => |n| getDeclNameToken(tree, n).?,
.param_decl => |p| p.name_token.?,
.param_payload => |pp| pp.param.name_token.?,
.pointer_payload => |pp| pp.name,
.array_payload => |ap| ap.identifier,
.array_index => |ai| ai,
Expand All @@ -1897,7 +1900,8 @@ pub const DeclWithHandle = struct {
.{ .node = node, .handle = self.handle },
bound_type_params,
),
.param_decl => |param_decl| {
.param_payload => |pay| {
const param_decl = pay.param;
if (isMetaType(self.handle.tree, param_decl.type_expr)) {
var bound_param_it = bound_type_params.iterator();
while (bound_param_it.next()) |entry| {
Expand Down Expand Up @@ -2555,7 +2559,7 @@ fn makeScopeInternal(allocator: std.mem.Allocator, context: ScopeContext, node_i
if (try scopes.items[scope_idx].decls.fetchPut(
allocator,
tree.tokenSlice(name_token),
.{ .param_decl = param },
.{ .param_payload = .{ .param = param, .func = node_idx } },
)) |existing| {
_ = existing;
// TODO record a redefinition error
Expand Down
11 changes: 11 additions & 0 deletions src/ast.zig
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,17 @@ pub fn lastToken(tree: Ast, node: Ast.Node.Index) Ast.TokenIndex {
};
}

pub fn paramFirstToken(tree: Ast, param: Ast.full.FnProto.Param) Ast.TokenIndex {
return param.first_doc_comment orelse
param.comptime_noalias orelse
param.name_token orelse
tree.firstToken(param.type_expr);
}

pub fn paramLastToken(tree: Ast, param: Ast.full.FnProto.Param) Ast.TokenIndex {
return param.anytype_ellipsis3 orelse tree.lastToken(param.type_expr);
}

pub fn containerField(tree: Ast, node: Ast.Node.Index) ?Ast.full.ContainerField {
return switch (tree.nodes.items(.tag)[node]) {
.container_field => tree.containerField(node),
Expand Down
Loading