diff --git a/build.zig b/build.zig index fc7db75..fd47281 100644 --- a/build.zig +++ b/build.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const builtin = std.builtin; +const builtin = @import("builtin"); const shared = @import("./src/shared.zig"); pub fn build(b: *std.build.Builder) !void { diff --git a/src/Config.zig b/src/Config.zig index 7616cdb..4d6083c 100644 --- a/src/Config.zig +++ b/src/Config.zig @@ -35,3 +35,5 @@ max_detail_length: usize = 1024 * 1024, /// Skips references to std. This will improve lookup speeds. /// Going to definition however will continue to work skip_std_references: bool = false, + +builtin_path: ?[]const u8 = null, diff --git a/src/DocumentStore.zig b/src/DocumentStore.zig index 04addc3..e8448d2 100644 --- a/src/DocumentStore.zig +++ b/src/DocumentStore.zig @@ -54,6 +54,7 @@ build_runner_cache_path: []const u8, std_uri: ?[]const u8, zig_cache_root: []const u8, zig_global_cache_root: []const u8, +builtin_path: ?[]const u8, pub fn init( self: *DocumentStore, @@ -64,6 +65,7 @@ pub fn init( 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); @@ -74,6 +76,7 @@ pub fn init( 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; } fn loadBuildAssociatedConfiguration(allocator: std.mem.Allocator, build_file: *BuildFile, build_file_path: []const u8) !void { @@ -239,6 +242,12 @@ fn newDocument(self: *DocumentStore, uri: []const u8, text: [:0]u8) anyerror!*Ha loadBuildAssociatedConfiguration(self.allocator, build_file, build_file_path) catch |err| { 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.?); + log.info("builtin config not found, falling back to defualt: {s}", .{build_file.builtin_uri}); + } + } // TODO: Do this in a separate thread? // It can take quite long. @@ -605,7 +614,7 @@ pub fn uriFromImportStr(self: *DocumentStore, allocator: std.mem.Allocator, hand return try allocator.dupe(u8, builtin_uri); } } - return null; // TODO find the correct zig-cache folder + return try allocator.dupe(u8, self.builtin_path.?); } else if (!std.mem.endsWith(u8, import_str, ".zig")) { if (handle.associated_build_file) |build_file| { for (build_file.packages.items) |pkg| { diff --git a/src/main.zig b/src/main.zig index c188fb9..0baac98 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1128,7 +1128,7 @@ fn loadConfigFile(file_path: []const u8) ?Config { const file_buf = file.readToEndAlloc(allocator, 0x1000000) catch return null; defer allocator.free(file_buf); - @setEvalBranchQuota(2000); + @setEvalBranchQuota(3000); // TODO: Better errors? Doesn't seem like std.json can provide us positions or context. var config = std.json.parse(Config, &std.json.TokenStream.init(file_buf), std.json.ParseOptions{ .allocator = allocator }) catch |err| { logger.warn("Error while parsing configuration file: {}", .{err}); @@ -1708,14 +1708,14 @@ pub fn main() anyerror!void { std.debug.print("Falling back to a lookup in the local and global configuration folders\n", .{}); } if (try known_folders.getPath(allocator, .local_configuration)) |path| { - defer allocator.free(path); + config_path = path; if (loadConfigInFolder(path)) |conf| { config = conf; break :config_read; } } if (try known_folders.getPath(allocator, .global_configuration)) |path| { - defer allocator.free(path); + config_path = path; if (loadConfigInFolder(path)) |conf| { config = conf; break :config_read; @@ -1789,6 +1789,30 @@ pub fn main() anyerror!void { 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) { + 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 = try d.createFile("builtin.zig", .{}); + defer f.close(); + + try f.writer().writeAll(result.stdout); + + config.builtin_path = try std.fs.path.join(allocator, &.{ config_path.?, "builtin.zig" }); + } + const build_runner_path = if (config.build_runner_path) |p| try allocator.dupe(u8, p) else blk: { @@ -1821,6 +1845,7 @@ pub fn main() anyerror!void { // 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, ); defer document_store.deinit();