Fix config source of truth problems, refactor some more
This commit is contained in:
		
							parent
							
								
									4507f4a275
								
							
						
					
					
						commit
						6f19772c17
					
				| @ -1,6 +1,6 @@ | ||||
| const std = @import("std"); | ||||
| const builtin = @import("builtin"); | ||||
| const shared = @import("./src/shared.zig"); | ||||
| const shared = @import("src/shared.zig"); | ||||
| 
 | ||||
| pub fn build(b: *std.build.Builder) !void { | ||||
|     const target = b.standardTargetOptions(.{}); | ||||
|  | ||||
							
								
								
									
										123
									
								
								src/Config.zig
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								src/Config.zig
									
									
									
									
									
								
							| @ -1,4 +1,12 @@ | ||||
| // Configuration options for zls. | ||||
| //! Configuration options for zls. | ||||
| 
 | ||||
| const Config = @This(); | ||||
| 
 | ||||
| const std = @import("std"); | ||||
| const setup = @import("setup.zig"); | ||||
| const known_folders = @import("known-folders"); | ||||
| 
 | ||||
| const logger = std.log.scoped(.config); | ||||
| 
 | ||||
| /// Whether to enable snippet completions | ||||
| enable_snippets: bool = false, | ||||
| @ -44,3 +52,116 @@ skip_std_references: bool = false, | ||||
| 
 | ||||
| /// Path to "builtin;" useful for debugging, automatically set if let null | ||||
| builtin_path: ?[]const u8 = null, | ||||
| 
 | ||||
| pub fn configChanged(config: *Config, allocator: std.mem.Allocator, builtin_creation_dir: ?[]const u8) !void { | ||||
|     // Find the zig executable in PATH | ||||
|     find_zig: { | ||||
|         if (config.zig_exe_path) |exe_path| { | ||||
|             if (std.fs.path.isAbsolute(exe_path)) not_valid: { | ||||
|                 std.fs.cwd().access(exe_path, .{}) catch break :not_valid; | ||||
|                 break :find_zig; | ||||
|             } | ||||
|             logger.debug("zig path `{s}` is not absolute, will look in path", .{exe_path}); | ||||
|             allocator.free(exe_path); | ||||
|         } | ||||
|         config.zig_exe_path = try setup.findZig(allocator); | ||||
|     } | ||||
| 
 | ||||
|     if (config.zig_exe_path) |exe_path| { | ||||
|         logger.info("Using zig executable {s}", .{exe_path}); | ||||
| 
 | ||||
|         if (config.zig_lib_path == null) find_lib_path: { | ||||
|             // Use `zig env` to find the lib path | ||||
|             const zig_env_result = try std.ChildProcess.exec(.{ | ||||
|                 .allocator = allocator, | ||||
|                 .argv = &[_][]const u8{ exe_path, "env" }, | ||||
|             }); | ||||
| 
 | ||||
|             defer { | ||||
|                 allocator.free(zig_env_result.stdout); | ||||
|                 allocator.free(zig_env_result.stderr); | ||||
|             } | ||||
| 
 | ||||
|             switch (zig_env_result.term) { | ||||
|                 .Exited => |exit_code| { | ||||
|                     if (exit_code == 0) { | ||||
|                         const Env = struct { | ||||
|                             zig_exe: []const u8, | ||||
|                             lib_dir: ?[]const u8, | ||||
|                             std_dir: []const u8, | ||||
|                             global_cache_dir: []const u8, | ||||
|                             version: []const u8, | ||||
|                         }; | ||||
| 
 | ||||
|                         var json_env = std.json.parse( | ||||
|                             Env, | ||||
|                             &std.json.TokenStream.init(zig_env_result.stdout), | ||||
|                             .{ .allocator = allocator }, | ||||
|                         ) catch { | ||||
|                             logger.err("Failed to parse zig env JSON result", .{}); | ||||
|                             break :find_lib_path; | ||||
|                         }; | ||||
|                         defer std.json.parseFree(Env, json_env, .{ .allocator = allocator }); | ||||
|                         // We know this is allocated with `allocator`, we just steal it! | ||||
|                         config.zig_lib_path = json_env.lib_dir.?; | ||||
|                         json_env.lib_dir = null; | ||||
|                         logger.info("Using zig lib path '{s}'", .{config.zig_lib_path}); | ||||
|                     } | ||||
|                 }, | ||||
|                 else => logger.err("zig env invocation failed", .{}), | ||||
|             } | ||||
|         } | ||||
|     } else { | ||||
|         logger.warn("Zig executable path not specified in zls.json and could not be found in PATH", .{}); | ||||
|     } | ||||
| 
 | ||||
|     if (config.zig_lib_path == null) { | ||||
|         logger.warn("Zig standard library path not specified in zls.json and could not be resolved from the zig executable", .{}); | ||||
|     } | ||||
| 
 | ||||
|     if (config.builtin_path == null and config.zig_exe_path != null and builtin_creation_dir != null) blk: { | ||||
|         const result = try std.ChildProcess.exec(.{ | ||||
|             .allocator = allocator, | ||||
|             .argv = &.{ | ||||
|                 config.zig_exe_path.?, | ||||
|                 "build-exe", | ||||
|                 "--show-builtin", | ||||
|             }, | ||||
|             .max_output_bytes = 1024 * 1024 * 50, | ||||
|         }); | ||||
|         defer allocator.free(result.stdout); | ||||
|         defer allocator.free(result.stderr); | ||||
| 
 | ||||
|         var d = try std.fs.cwd().openDir(builtin_creation_dir.?, .{}); | ||||
|         defer d.close(); | ||||
| 
 | ||||
|         const f = d.createFile("builtin.zig", .{}) catch |err| switch (err) { | ||||
|             error.AccessDenied => break :blk, | ||||
|             else => |e| return e, | ||||
|         }; | ||||
|         defer f.close(); | ||||
| 
 | ||||
|         try f.writer().writeAll(result.stdout); | ||||
| 
 | ||||
|         config.builtin_path = try std.fs.path.join(allocator, &.{ builtin_creation_dir.?, "builtin.zig" }); | ||||
|     } | ||||
| 
 | ||||
|     config.build_runner_path = if (config.build_runner_path) |p| | ||||
|         try allocator.dupe(u8, p) | ||||
|     else blk: { | ||||
|         var exe_dir_bytes: [std.fs.MAX_PATH_BYTES]u8 = undefined; | ||||
|         const exe_dir_path = try std.fs.selfExeDirPath(&exe_dir_bytes); | ||||
|         break :blk try std.fs.path.resolve(allocator, &[_][]const u8{ exe_dir_path, "build_runner.zig" }); | ||||
|     }; | ||||
| 
 | ||||
|     config.build_runner_cache_path = if (config.build_runner_cache_path) |p| | ||||
|         try allocator.dupe(u8, p) | ||||
|     else blk: { | ||||
|         const cache_dir_path = (try known_folders.getPath(allocator, .cache)) orelse { | ||||
|             logger.warn("Known-folders could not fetch the cache path", .{}); | ||||
|             return; | ||||
|         }; | ||||
|         defer allocator.free(cache_dir_path); | ||||
|         break :blk try std.fs.path.resolve(allocator, &[_][]const u8{ cache_dir_path, "zls" }); | ||||
|     }; | ||||
| } | ||||
|  | ||||
| @ -1,13 +1,13 @@ | ||||
| const std = @import("std"); | ||||
| const types = @import("./types.zig"); | ||||
| const URI = @import("./uri.zig"); | ||||
| const analysis = @import("./analysis.zig"); | ||||
| const offsets = @import("./offsets.zig"); | ||||
| const types = @import("types.zig"); | ||||
| const URI = @import("uri.zig"); | ||||
| const analysis = @import("analysis.zig"); | ||||
| const offsets = @import("offsets.zig"); | ||||
| const log = std.log.scoped(.doc_store); | ||||
| const Ast = std.zig.Ast; | ||||
| const BuildAssociatedConfig = @import("./BuildAssociatedConfig.zig"); | ||||
| const tracy = @import("./tracy.zig"); | ||||
| const Config = @import("./Config.zig"); | ||||
| const BuildAssociatedConfig = @import("BuildAssociatedConfig.zig"); | ||||
| const tracy = @import("tracy.zig"); | ||||
| const Config = @import("Config.zig"); | ||||
| 
 | ||||
| const DocumentStore = @This(); | ||||
| 
 | ||||
| @ -75,6 +75,12 @@ pub fn init( | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| fn updateStdUri(store: *DocumentStore) !void { | ||||
|     if (store.std_uri) |std_uri| | ||||
|         store.allocator.free(std_uri); | ||||
|     store.std_uri = try stdUriFromLibPath(store.allocator, store.config.zig_lib_path); | ||||
| } | ||||
| 
 | ||||
| fn loadBuildAssociatedConfiguration(allocator: std.mem.Allocator, build_file: *BuildFile, build_file_path: []const u8) !void { | ||||
|     const directory_path = build_file_path[0 .. build_file_path.len - "build.zig".len]; | ||||
| 
 | ||||
| @ -767,8 +773,6 @@ pub fn deinit(self: *DocumentStore) void { | ||||
|     if (self.std_uri) |std_uri| { | ||||
|         self.allocator.free(std_uri); | ||||
|     } | ||||
|     self.allocator.free(self.config.build_runner_path.?); | ||||
|     self.allocator.free(self.config.build_runner_cache_path.?); | ||||
|     self.build_files.deinit(self.allocator); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1,10 +1,10 @@ | ||||
| const std = @import("std"); | ||||
| const DocumentStore = @import("./DocumentStore.zig"); | ||||
| const DocumentStore = @import("DocumentStore.zig"); | ||||
| const Ast = std.zig.Ast; | ||||
| const types = @import("./types.zig"); | ||||
| const offsets = @import("./offsets.zig"); | ||||
| const types = @import("types.zig"); | ||||
| const offsets = @import("offsets.zig"); | ||||
| const log = std.log.scoped(.analysis); | ||||
| const ast = @import("./ast.zig"); | ||||
| const ast = @import("ast.zig"); | ||||
| 
 | ||||
| var using_trail: std.ArrayList([*]const u8) = undefined; | ||||
| var resolve_trail: std.ArrayList(NodeWithHandle) = undefined; | ||||
|  | ||||
							
								
								
									
										145
									
								
								src/main.zig
									
									
									
									
									
								
							
							
						
						
									
										145
									
								
								src/main.zig
									
									
									
									
									
								
							| @ -1,23 +1,23 @@ | ||||
| const std = @import("std"); | ||||
| const zig_builtin = @import("builtin"); | ||||
| const build_options = @import("build_options"); | ||||
| const Config = @import("./Config.zig"); | ||||
| const DocumentStore = @import("./DocumentStore.zig"); | ||||
| const readRequestHeader = @import("./header.zig").readRequestHeader; | ||||
| const requests = @import("./requests.zig"); | ||||
| const types = @import("./types.zig"); | ||||
| const analysis = @import("./analysis.zig"); | ||||
| const ast = @import("./ast.zig"); | ||||
| const references = @import("./references.zig"); | ||||
| const rename = @import("./rename.zig"); | ||||
| const offsets = @import("./offsets.zig"); | ||||
| const setup = @import("./setup.zig"); | ||||
| const semantic_tokens = @import("./semantic_tokens.zig"); | ||||
| const shared = @import("./shared.zig"); | ||||
| const Config = @import("Config.zig"); | ||||
| const DocumentStore = @import("DocumentStore.zig"); | ||||
| const readRequestHeader = @import("header.zig").readRequestHeader; | ||||
| const requests = @import("requests.zig"); | ||||
| const types = @import("types.zig"); | ||||
| const analysis = @import("analysis.zig"); | ||||
| const ast = @import("ast.zig"); | ||||
| const references = @import("references.zig"); | ||||
| const rename = @import("rename.zig"); | ||||
| const offsets = @import("offsets.zig"); | ||||
| const setup = @import("setup.zig"); | ||||
| const semantic_tokens = @import("semantic_tokens.zig"); | ||||
| const shared = @import("shared.zig"); | ||||
| const Ast = std.zig.Ast; | ||||
| const known_folders = @import("known-folders"); | ||||
| const tracy = @import("./tracy.zig"); | ||||
| const uri_utils = @import("./uri.zig"); | ||||
| const tracy = @import("tracy.zig"); | ||||
| const uri_utils = @import("uri.zig"); | ||||
| 
 | ||||
| const data = switch (build_options.data_version) { | ||||
|     .master => @import("data/master.zig"), | ||||
| @ -2191,6 +2191,8 @@ fn didChangeConfigurationHandler(arena: *std.heap.ArenaAllocator, id: types.Requ | ||||
|                 @field(config, field.name) = if (@TypeOf(value) == []const u8) try gpa_state.allocator().dupe(u8, value) else value; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         try config.configChanged(allocator, null); | ||||
|     } else if (client_capabilities.supports_configuration) | ||||
|         try requestConfiguration(arena); | ||||
| } | ||||
| @ -2281,6 +2283,8 @@ fn processJsonRpc(arena: *std.heap.ArenaAllocator, parser: *std.json.Parser, jso | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         try config.configChanged(allocator, null); | ||||
| 
 | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
| @ -2475,116 +2479,7 @@ pub fn main() anyerror!void { | ||||
|         config_path = null; | ||||
|     } | ||||
| 
 | ||||
|     // Find the zig executable in PATH | ||||
|     find_zig: { | ||||
|         if (config.zig_exe_path) |exe_path| { | ||||
|             if (std.fs.path.isAbsolute(exe_path)) not_valid: { | ||||
|                 std.fs.cwd().access(exe_path, .{}) catch break :not_valid; | ||||
|                 break :find_zig; | ||||
|             } | ||||
|             logger.debug("zig path `{s}` is not absolute, will look in path", .{exe_path}); | ||||
|             allocator.free(exe_path); | ||||
|         } | ||||
|         config.zig_exe_path = try setup.findZig(allocator); | ||||
|     } | ||||
| 
 | ||||
|     if (config.zig_exe_path) |exe_path| { | ||||
|         logger.info("Using zig executable {s}", .{exe_path}); | ||||
| 
 | ||||
|         if (config.zig_lib_path == null) find_lib_path: { | ||||
|             // Use `zig env` to find the lib path | ||||
|             const zig_env_result = try std.ChildProcess.exec(.{ | ||||
|                 .allocator = allocator, | ||||
|                 .argv = &[_][]const u8{ exe_path, "env" }, | ||||
|             }); | ||||
| 
 | ||||
|             defer { | ||||
|                 allocator.free(zig_env_result.stdout); | ||||
|                 allocator.free(zig_env_result.stderr); | ||||
|             } | ||||
| 
 | ||||
|             switch (zig_env_result.term) { | ||||
|                 .Exited => |exit_code| { | ||||
|                     if (exit_code == 0) { | ||||
|                         const Env = struct { | ||||
|                             zig_exe: []const u8, | ||||
|                             lib_dir: ?[]const u8, | ||||
|                             std_dir: []const u8, | ||||
|                             global_cache_dir: []const u8, | ||||
|                             version: []const u8, | ||||
|                         }; | ||||
| 
 | ||||
|                         var json_env = std.json.parse( | ||||
|                             Env, | ||||
|                             &std.json.TokenStream.init(zig_env_result.stdout), | ||||
|                             .{ .allocator = allocator }, | ||||
|                         ) catch { | ||||
|                             logger.err("Failed to parse zig env JSON result", .{}); | ||||
|                             break :find_lib_path; | ||||
|                         }; | ||||
|                         defer std.json.parseFree(Env, json_env, .{ .allocator = allocator }); | ||||
|                         // We know this is allocated with `allocator`, we just steal it! | ||||
|                         config.zig_lib_path = json_env.lib_dir.?; | ||||
|                         json_env.lib_dir = null; | ||||
|                         logger.info("Using zig lib path '{s}'", .{config.zig_lib_path}); | ||||
|                     } | ||||
|                 }, | ||||
|                 else => logger.err("zig env invocation failed", .{}), | ||||
|             } | ||||
|         } | ||||
|     } else { | ||||
|         logger.warn("Zig executable path not specified in zls.json and could not be found in PATH", .{}); | ||||
|     } | ||||
| 
 | ||||
|     if (config.zig_lib_path == null) { | ||||
|         logger.warn("Zig standard library path not specified in zls.json and could not be resolved from the zig executable", .{}); | ||||
|     } | ||||
| 
 | ||||
|     if (config.builtin_path == null and config.zig_exe_path != null and config_path != null) blk: { | ||||
|         const result = try std.ChildProcess.exec(.{ | ||||
|             .allocator = allocator, | ||||
|             .argv = &.{ | ||||
|                 config.zig_exe_path.?, | ||||
|                 "build-exe", | ||||
|                 "--show-builtin", | ||||
|             }, | ||||
|             .max_output_bytes = 1024 * 1024 * 50, | ||||
|         }); | ||||
|         defer allocator.free(result.stdout); | ||||
|         defer allocator.free(result.stderr); | ||||
| 
 | ||||
|         var d = try std.fs.cwd().openDir(config_path.?, .{}); | ||||
|         defer d.close(); | ||||
| 
 | ||||
|         const f = d.createFile("builtin.zig", .{}) catch |err| switch (err) { | ||||
|             error.AccessDenied => break :blk, | ||||
|             else => |e| return e, | ||||
|         }; | ||||
|         defer f.close(); | ||||
| 
 | ||||
|         try f.writer().writeAll(result.stdout); | ||||
| 
 | ||||
|         config.builtin_path = try std.fs.path.join(allocator, &.{ config_path.?, "builtin.zig" }); | ||||
|     } | ||||
| 
 | ||||
|     config.build_runner_path = if (config.build_runner_path) |p| | ||||
|         try allocator.dupe(u8, p) | ||||
|     else blk: { | ||||
|         var exe_dir_bytes: [std.fs.MAX_PATH_BYTES]u8 = undefined; | ||||
|         const exe_dir_path = try std.fs.selfExeDirPath(&exe_dir_bytes); | ||||
|         break :blk try std.fs.path.resolve(allocator, &[_][]const u8{ exe_dir_path, "build_runner.zig" }); | ||||
|     }; | ||||
| 
 | ||||
|     config.build_runner_cache_path = if (config.build_runner_cache_path) |p| | ||||
|         try allocator.dupe(u8, p) | ||||
|     else blk: { | ||||
|         const cache_dir_path = (try known_folders.getPath(allocator, .cache)) orelse { | ||||
|             logger.warn("Known-folders could not fetch the cache path", .{}); | ||||
|             return; | ||||
|         }; | ||||
|         defer allocator.free(cache_dir_path); | ||||
|         break :blk try std.fs.path.resolve(allocator, &[_][]const u8{ cache_dir_path, "zls" }); | ||||
|     }; | ||||
|     try config.configChanged(allocator, config_path); | ||||
| 
 | ||||
|     document_store = try DocumentStore.init( | ||||
|         allocator, | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| const std = @import("std"); | ||||
| const types = @import("./types.zig"); | ||||
| const types = @import("types.zig"); | ||||
| const Ast = std.zig.Ast; | ||||
| 
 | ||||
| pub const Encoding = enum { | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| const std = @import("std"); | ||||
| const Ast = std.zig.Ast; | ||||
| const DocumentStore = @import("./DocumentStore.zig"); | ||||
| const analysis = @import("./analysis.zig"); | ||||
| const types = @import("./types.zig"); | ||||
| const offsets = @import("./offsets.zig"); | ||||
| const DocumentStore = @import("DocumentStore.zig"); | ||||
| const analysis = @import("analysis.zig"); | ||||
| const types = @import("types.zig"); | ||||
| const offsets = @import("offsets.zig"); | ||||
| const log = std.log.scoped(.references); | ||||
| const ast = @import("./ast.zig"); | ||||
| const ast = @import("ast.zig"); | ||||
| 
 | ||||
| fn tokenReference(handle: *DocumentStore.Handle, tok: Ast.TokenIndex, encoding: offsets.Encoding, context: anytype, comptime handler: anytype) !void { | ||||
|     const loc = offsets.tokenRelativeLocation(handle.tree, 0, handle.tree.tokens.items(.start)[tok], encoding) catch return; | ||||
|  | ||||
| @ -1,9 +1,9 @@ | ||||
| const std = @import("std"); | ||||
| const DocumentStore = @import("./DocumentStore.zig"); | ||||
| const analysis = @import("./analysis.zig"); | ||||
| const references = @import("./references.zig"); | ||||
| const types = @import("./types.zig"); | ||||
| const offsets = @import("./offsets.zig"); | ||||
| const DocumentStore = @import("DocumentStore.zig"); | ||||
| const analysis = @import("analysis.zig"); | ||||
| const references = @import("references.zig"); | ||||
| const types = @import("types.zig"); | ||||
| const offsets = @import("offsets.zig"); | ||||
| 
 | ||||
| // TODO Use a map to array lists and collect at the end instead? | ||||
| const RefHandlerContext = struct { | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| //! We only define what we actually use. | ||||
| 
 | ||||
| const std = @import("std"); | ||||
| const types = @import("./types.zig"); | ||||
| const types = @import("types.zig"); | ||||
| 
 | ||||
| /// Only check for the field's existence. | ||||
| const Exists = struct { | ||||
|  | ||||
| @ -1,10 +1,10 @@ | ||||
| const std = @import("std"); | ||||
| const offsets = @import("./offsets.zig"); | ||||
| const DocumentStore = @import("./DocumentStore.zig"); | ||||
| const analysis = @import("./analysis.zig"); | ||||
| const offsets = @import("offsets.zig"); | ||||
| const DocumentStore = @import("DocumentStore.zig"); | ||||
| const analysis = @import("analysis.zig"); | ||||
| const Ast = std.zig.Ast; | ||||
| const log = std.log.scoped(.semantic_tokens); | ||||
| const ast = @import("./ast.zig"); | ||||
| const ast = @import("ast.zig"); | ||||
| 
 | ||||
| pub const TokenType = enum(u32) { | ||||
|     type, | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| const std = @import("std"); | ||||
| const analysis = @import("./analysis.zig"); | ||||
| const offsets = @import("./offsets.zig"); | ||||
| const DocumentStore = @import("./DocumentStore.zig"); | ||||
| const types = @import("./types.zig"); | ||||
| const analysis = @import("analysis.zig"); | ||||
| const offsets = @import("offsets.zig"); | ||||
| const DocumentStore = @import("DocumentStore.zig"); | ||||
| const types = @import("types.zig"); | ||||
| const Ast = std.zig.Ast; | ||||
| const Token = std.zig.Token; | ||||
| const identifierFromPosition = @import("./main.zig").identifierFromPosition; | ||||
| const ast = @import("./ast.zig"); | ||||
| const identifierFromPosition = @import("main.zig").identifierFromPosition; | ||||
| const ast = @import("ast.zig"); | ||||
| 
 | ||||
| fn fnProtoToSignatureInfo(document_store: *DocumentStore, arena: *std.heap.ArenaAllocator, commas: u32, skip_self_param: bool, handle: *DocumentStore.Handle, fn_node: Ast.Node.Index, proto: Ast.full.FnProto) !types.SignatureInformation { | ||||
|     const ParameterInformation = types.SignatureInformation.ParameterInformation; | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| const std = @import("std"); | ||||
| const analysis = @import("./analysis.zig"); | ||||
| const types = @import("./types.zig"); | ||||
| const offsets = @import("./offsets.zig"); | ||||
| const URI = @import("./uri.zig"); | ||||
| const analysis = @import("analysis.zig"); | ||||
| const types = @import("types.zig"); | ||||
| const offsets = @import("offsets.zig"); | ||||
| const URI = @import("uri.zig"); | ||||
| 
 | ||||
| const allocator = std.testing.allocator; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user