diff --git a/README.md b/README.md index 1e1d72a..49f31a7 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ [![CI](https://github.com/zigtools/zls/workflows/CI/badge.svg)](https://github.com/zigtools/zls/actions) ![Zig Tools](./.github/assets/zigtools.svg) +**Need support? Wanna help out? Join our [Discord server](https://discord.gg/5m5U3qpUhk)!** + Zig Language Server, or `zls`, is a language server for Zig. The Zig wiki states that "The Zig community is decentralized" and "There is no concept of 'official' or 'unofficial'", so instead of calling `zls` unofficial, and I'm going to call it a cool option, one of [many](https://github.com/search?q=zig+language+server). diff --git a/src/DocumentStore.zig b/src/DocumentStore.zig index eef7316..deb4a65 100644 --- a/src/DocumentStore.zig +++ b/src/DocumentStore.zig @@ -7,6 +7,7 @@ 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 DocumentStore = @This(); @@ -46,38 +47,32 @@ pub const Handle = struct { } }; +pub const UriToHandleMap = std.StringHashMapUnmanaged(*Handle); +pub const BuildFileList = std.ArrayListUnmanaged(*BuildFile); + allocator: std.mem.Allocator, -handles: std.StringHashMap(*Handle), -zig_exe_path: ?[]const u8, -build_files: std.ArrayListUnmanaged(*BuildFile), -build_runner_path: []const u8, -build_runner_cache_path: []const u8, +handles: UriToHandleMap = .{}, +build_files: BuildFileList = .{}, + +config: *const Config, std_uri: ?[]const u8, -zig_cache_root: []const u8, -zig_global_cache_root: []const u8, -builtin_path: ?[]const u8, +// TODO make this configurable +// We can't figure it out ourselves since we don't know what arguments +// the user will use to run "zig build" +zig_cache_root: []const u8 = "zig-cache", +// Since we don't compile anything and no packages should put their +// files there this path can be ignored +zig_global_cache_root: []const u8 = "ZLS_DONT_CARE", pub fn init( - self: *DocumentStore, allocator: std.mem.Allocator, - zig_exe_path: ?[]const u8, - build_runner_path: []const u8, - build_runner_cache_path: []const u8, - zig_lib_path: ?[]const u8, - zig_cache_root: []const u8, - zig_global_cache_root: []const u8, - builtin_path: ?[]const u8, -) !void { - self.allocator = allocator; - self.handles = std.StringHashMap(*Handle).init(allocator); - self.zig_exe_path = zig_exe_path; - self.build_files = .{}; - self.build_runner_path = build_runner_path; - self.build_runner_cache_path = build_runner_cache_path; - self.std_uri = try stdUriFromLibPath(allocator, zig_lib_path); - self.zig_cache_root = zig_cache_root; - self.zig_global_cache_root = zig_global_cache_root; - self.builtin_path = builtin_path; + config: *const Config, +) !DocumentStore { + return DocumentStore{ + .allocator = allocator, + .config = config, + .std_uri = try stdUriFromLibPath(allocator, config.zig_lib_path), + }; } fn loadBuildAssociatedConfiguration(allocator: std.mem.Allocator, build_file: *BuildFile, build_file_path: []const u8) !void { @@ -233,7 +228,7 @@ fn newDocument(self: *DocumentStore, uri: []const u8, text: [:0]u8) anyerror!*Ha // TODO: Better logic for detecting std or subdirectories? const in_std = std.mem.indexOf(u8, uri, "/std/") != null; - if (self.zig_exe_path != null and std.mem.endsWith(u8, uri, "/build.zig") and !in_std) { + if (self.config.zig_exe_path != null and std.mem.endsWith(u8, uri, "/build.zig") and !in_std) { log.debug("Document is a build file, extracting packages...", .{}); // This is a build file. var build_file = try self.allocator.create(BuildFile); @@ -252,8 +247,8 @@ fn newDocument(self: *DocumentStore, uri: []const u8, text: [:0]u8) anyerror!*Ha log.debug("Failed to load config associated with build file {s} (error: {})", .{ build_file.uri, err }); }; if (build_file.builtin_uri == null) { - if (self.builtin_path != null) { - build_file.builtin_uri = try URI.fromPath(self.allocator, self.builtin_path.?); + if (self.config.builtin_path != null) { + build_file.builtin_uri = try URI.fromPath(self.allocator, self.config.builtin_path.?); log.info("builtin config not found, falling back to default: {s}", .{build_file.builtin_uri}); } } @@ -263,9 +258,9 @@ fn newDocument(self: *DocumentStore, uri: []const u8, text: [:0]u8) anyerror!*Ha loadPackages(.{ .build_file = build_file, .allocator = self.allocator, - .build_runner_path = self.build_runner_path, - .build_runner_cache_path = self.build_runner_cache_path, - .zig_exe_path = self.zig_exe_path.?, + .build_runner_path = self.config.build_runner_path.?, + .build_runner_cache_path = self.config.build_runner_cache_path.?, + .zig_exe_path = self.config.zig_exe_path.?, .build_file_path = build_file_path, .cache_root = self.zig_cache_root, .global_cache_root = self.zig_global_cache_root, @@ -275,7 +270,7 @@ fn newDocument(self: *DocumentStore, uri: []const u8, text: [:0]u8) anyerror!*Ha try self.build_files.append(self.allocator, build_file); handle.is_build_file = build_file; - } else if (self.zig_exe_path != null and !in_std) { + } else if (self.config.zig_exe_path != null and !in_std) { // Look into build files and keep the one that lives closest to the document in the directory structure var candidate: ?*BuildFile = null; { @@ -368,7 +363,7 @@ fn newDocument(self: *DocumentStore, uri: []const u8, text: [:0]u8) anyerror!*Ha self.allocator.free(handle.import_uris); } - try self.handles.putNoClobber(uri, handle); + try self.handles.putNoClobber(self.allocator, uri, handle); return handle; } @@ -533,9 +528,9 @@ pub fn applySave(self: *DocumentStore, handle: *Handle) !void { loadPackages(.{ .build_file = build_file, .allocator = self.allocator, - .build_runner_path = self.build_runner_path, - .build_runner_cache_path = self.build_runner_cache_path, - .zig_exe_path = self.zig_exe_path.?, + .build_runner_path = self.config.build_runner_path.?, + .build_runner_cache_path = self.config.build_runner_cache_path.?, + .zig_exe_path = self.config.zig_exe_path.?, .cache_root = self.zig_cache_root, .global_cache_root = self.zig_global_cache_root, }) catch |err| { @@ -623,8 +618,8 @@ pub fn uriFromImportStr(self: *DocumentStore, allocator: std.mem.Allocator, hand return try allocator.dupe(u8, builtin_uri); } } - if (self.builtin_path) |_| { - return try URI.fromPath(allocator, self.builtin_path.?); + if (self.config.builtin_path) |_| { + return try URI.fromPath(allocator, self.config.builtin_path.?); } return null; } else if (!std.mem.endsWith(u8, import_str, ".zig")) { @@ -759,7 +754,7 @@ pub fn deinit(self: *DocumentStore) void { self.allocator.destroy(entry.value_ptr.*); } - self.handles.deinit(); + self.handles.deinit(self.allocator); for (self.build_files.items) |build_file| { for (build_file.packages.items) |pkg| { self.allocator.free(pkg.name); @@ -772,8 +767,8 @@ pub fn deinit(self: *DocumentStore) void { if (self.std_uri) |std_uri| { self.allocator.free(std_uri); } - self.allocator.free(self.build_runner_path); - self.allocator.free(self.build_runner_cache_path); + self.allocator.free(self.config.build_runner_path.?); + self.allocator.free(self.config.build_runner_cache_path.?); self.build_files.deinit(self.allocator); } diff --git a/src/main.zig b/src/main.zig index 92b0ebc..5fc8acc 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2567,7 +2567,7 @@ pub fn main() anyerror!void { config.builtin_path = try std.fs.path.join(allocator, &.{ config_path.?, "builtin.zig" }); } - const build_runner_path = if (config.build_runner_path) |p| + 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; @@ -2575,7 +2575,7 @@ pub fn main() anyerror!void { break :blk try std.fs.path.resolve(allocator, &[_][]const u8{ exe_dir_path, "build_runner.zig" }); }; - const build_runner_cache_path = if (config.build_runner_cache_path) |p| + 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 { @@ -2586,20 +2586,9 @@ pub fn main() anyerror!void { break :blk try std.fs.path.resolve(allocator, &[_][]const u8{ cache_dir_path, "zls" }); }; - try document_store.init( + document_store = try DocumentStore.init( allocator, - config.zig_exe_path, - build_runner_path, - build_runner_cache_path, - config.zig_lib_path, - // TODO make this configurable - // We can't figure it out ourselves since we don't know what arguments - // the user will use to run "zig build" - "zig-cache", - // Since we don't compile anything and no packages should put their - // files there this path can be ignored - "ZLS_DONT_CARE", - config.builtin_path, + &config, ); defer document_store.deinit();