Added zig_exe_path option, use it to detect lib path if none is provided
This commit is contained in:
parent
c9af33011a
commit
543cb5816c
@ -55,6 +55,7 @@ The following options are currently available.
|
||||
| --- | --- | --- | --- |
|
||||
| `enable_snippets` | `bool` | `false` | Enables snippet completion, set to false for compatibility with language clients that do not support snippets (such as ale). |
|
||||
| `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/bin/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. |
|
||||
| `warn_style` | `bool` | `false` | Enables warnings for style *guideline* mismatches |
|
||||
| `build_runner_path` | `?[]const u8` | `null` | Path to the build_runner.zig file provided by zls. This option must be present in one of the global configuration files to have any effect. `null` is equivalent to `${executable_directory}/build_runner.zig` |
|
||||
|
||||
|
@ -6,6 +6,10 @@ enable_snippets: bool = false,
|
||||
/// zig library path
|
||||
zig_lib_path: ?[]const u8 = null,
|
||||
|
||||
/// zig executable path used to run the custom build runner.
|
||||
/// May be used to find a lib path if none is provided.
|
||||
zig_exe_path: ?[]const u8 = null,
|
||||
|
||||
/// Whether to pay attention to style issues. This is opt-in since the style
|
||||
/// guide explicitly states that the style info provided is a guideline only.
|
||||
warn_style: bool = false,
|
||||
|
@ -74,7 +74,7 @@ pub const TagStore = struct {
|
||||
|
||||
allocator: *std.mem.Allocator,
|
||||
handles: std.StringHashMap(*Handle),
|
||||
has_zig: bool,
|
||||
zig_exe_path: ?[]const u8,
|
||||
build_files: std.ArrayListUnmanaged(*BuildFile),
|
||||
build_runner_path: []const u8,
|
||||
|
||||
@ -84,12 +84,12 @@ enum_completions: TagStore,
|
||||
pub fn init(
|
||||
self: *DocumentStore,
|
||||
allocator: *std.mem.Allocator,
|
||||
has_zig: bool,
|
||||
zig_exe_path: ?[]const u8,
|
||||
build_runner_path: []const u8,
|
||||
) !void {
|
||||
self.allocator = allocator;
|
||||
self.handles = std.StringHashMap(*Handle).init(allocator);
|
||||
self.has_zig = has_zig;
|
||||
self.zig_exe_path = zig_exe_path;
|
||||
self.build_files = .{};
|
||||
self.build_runner_path = build_runner_path;
|
||||
self.error_completions = TagStore.init(allocator);
|
||||
@ -100,12 +100,14 @@ const LoadPackagesContext = struct {
|
||||
build_file: *BuildFile,
|
||||
allocator: *std.mem.Allocator,
|
||||
build_runner_path: []const u8,
|
||||
zig_exe_path: []const u8,
|
||||
};
|
||||
|
||||
fn loadPackages(context: LoadPackagesContext) !void {
|
||||
const allocator = context.allocator;
|
||||
const build_file = context.build_file;
|
||||
const build_runner_path = context.build_runner_path;
|
||||
const zig_exe_path = context.zig_exe_path;
|
||||
|
||||
const directory_path = try URI.parse(allocator, build_file.uri[0 .. build_file.uri.len - "build.zig".len]);
|
||||
defer allocator.free(directory_path);
|
||||
@ -134,7 +136,7 @@ fn loadPackages(context: LoadPackagesContext) !void {
|
||||
|
||||
const zig_run_result = try std.ChildProcess.exec(.{
|
||||
.allocator = allocator,
|
||||
.argv = &[_][]const u8{ "zig", "run", "build_runner.zig" },
|
||||
.argv = &[_][]const u8{ zig_exe_path, "run", "build_runner.zig" },
|
||||
.cwd = directory_path,
|
||||
});
|
||||
|
||||
@ -204,7 +206,7 @@ fn newDocument(self: *DocumentStore, uri: []const u8, text: []u8) anyerror!*Hand
|
||||
|
||||
// TODO: Better logic for detecting std or subdirectories?
|
||||
const in_std = std.mem.indexOf(u8, uri, "/std/") != null;
|
||||
if (self.has_zig and std.mem.endsWith(u8, uri, "/build.zig") and !in_std) {
|
||||
if (self.zig_exe_path != null and std.mem.endsWith(u8, uri, "/build.zig") and !in_std) {
|
||||
std.debug.warn("Document is a build file, extracting packages...\n", .{});
|
||||
// This is a build file.
|
||||
var build_file = try self.allocator.create(BuildFile);
|
||||
@ -225,10 +227,11 @@ fn newDocument(self: *DocumentStore, uri: []const u8, text: []u8) anyerror!*Hand
|
||||
.build_file = build_file,
|
||||
.allocator = self.allocator,
|
||||
.build_runner_path = self.build_runner_path,
|
||||
.zig_exe_path = self.zig_exe_path.?,
|
||||
}) catch |err| {
|
||||
std.debug.warn("Failed to load packages of build file {} (error: {})\n", .{ build_file.uri, err });
|
||||
};
|
||||
} else if (self.has_zig and !in_std) associate_build_file: {
|
||||
} else if (self.zig_exe_path != null and !in_std) associate_build_file: {
|
||||
// Look into build files to see if we already have one that fits
|
||||
for (self.build_files.items) |build_file| {
|
||||
const build_file_base_uri = build_file.uri[0 .. std.mem.lastIndexOfScalar(u8, build_file.uri, '/').? + 1];
|
||||
@ -471,6 +474,7 @@ pub fn applyChanges(
|
||||
.build_file = build_file,
|
||||
.allocator = self.allocator,
|
||||
.build_runner_path = self.build_runner_path,
|
||||
.zig_exe_path = self.zig_exe_path.?,
|
||||
}) catch |err| {
|
||||
std.debug.warn("Failed to load packages of build file {} (error: {})\n", .{ build_file.uri, err });
|
||||
};
|
||||
|
43
src/main.zig
43
src/main.zig
@ -533,9 +533,7 @@ fn documentSymbol(id: i64, handle: *DocumentStore.Handle) !void {
|
||||
|
||||
try send(types.Response{
|
||||
.id = .{ .Integer = id },
|
||||
.result = .{
|
||||
.DocumentSymbols = try analysis.getDocumentSymbols(&arena.allocator, handle.tree)
|
||||
},
|
||||
.result = .{ .DocumentSymbols = try analysis.getDocumentSymbols(&arena.allocator, handle.tree) },
|
||||
});
|
||||
}
|
||||
|
||||
@ -760,7 +758,7 @@ fn processJsonRpc(parser: *std.json.Parser, json: []const u8, config: Config) !v
|
||||
}),
|
||||
.var_access, .empty => try completeGlobal(id, pos_index, handle, this_config),
|
||||
.field_access => |range| try completeFieldAccess(id, handle, pos, range, this_config),
|
||||
.global_error_set => try send(types.Response{
|
||||
.global_error_set => try send(types.Response{
|
||||
.id = .{ .Integer = id },
|
||||
.result = .{
|
||||
.CompletionList = .{
|
||||
@ -769,7 +767,7 @@ fn processJsonRpc(parser: *std.json.Parser, json: []const u8, config: Config) !v
|
||||
},
|
||||
},
|
||||
}),
|
||||
.enum_literal => try send(types.Response{
|
||||
.enum_literal => try send(types.Response{
|
||||
.id = .{ .Integer = id },
|
||||
.result = .{
|
||||
.CompletionList = .{
|
||||
@ -930,11 +928,19 @@ pub fn main() anyerror!void {
|
||||
}
|
||||
|
||||
// Find the zig executable in PATH
|
||||
var has_zig = false;
|
||||
var zig_exe_path: ?[]const u8 = null;
|
||||
defer if (zig_exe_path) |exe_path| allocator.free(exe_path);
|
||||
|
||||
// TODO: Should we just spawn a child process that calls "zig version" or something
|
||||
// and check that way?
|
||||
find_zig: {
|
||||
if (config.zig_exe_path) |exe_path| {
|
||||
if (std.fs.path.isAbsolute(exe_path)) {
|
||||
zig_exe_path = try std.mem.dupe(allocator, u8, exe_path);
|
||||
break :find_zig;
|
||||
}
|
||||
|
||||
std.debug.warn("zig path `{}` is not absolute, will look in path\n", .{exe_path});
|
||||
}
|
||||
|
||||
const env_path = std.process.getEnvVarOwned(allocator, "PATH") catch |err| switch (err) {
|
||||
error.EnvironmentVariableNotFound => {
|
||||
std.debug.warn("Could not get PATH.\n", .{});
|
||||
@ -957,21 +963,32 @@ pub fn main() anyerror!void {
|
||||
defer allocator.free(full_path);
|
||||
|
||||
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
|
||||
const zig_path = std.os.realpath(full_path, &buf) catch continue;
|
||||
std.debug.warn("Found zig in PATH: {}\n", .{zig_path});
|
||||
has_zig = true;
|
||||
zig_exe_path = std.os.realpath(full_path, &buf) catch continue;
|
||||
std.debug.warn("Found zig in PATH: {}\n", .{zig_exe_path});
|
||||
break :find_zig;
|
||||
}
|
||||
}
|
||||
|
||||
if (zig_exe_path) |exe_path| {
|
||||
std.debug.warn("Using zig executable {}\n", .{exe_path});
|
||||
if (config.zig_lib_path == null) {
|
||||
// Set the lib path relative to the executable path.
|
||||
config.zig_lib_path = try std.fs.path.resolve(allocator, &[_][]const u8{
|
||||
std.fs.path.dirname(exe_path).?, "./lib/zig",
|
||||
});
|
||||
|
||||
std.debug.warn("Resolved standard library from executable: {}\n", .{config.zig_lib_path});
|
||||
}
|
||||
}
|
||||
|
||||
if (config.build_runner_path) |build_runner_path| {
|
||||
try document_store.init(allocator, has_zig, try std.mem.dupe(allocator, u8, build_runner_path));
|
||||
try document_store.init(allocator, zig_exe_path, try std.mem.dupe(allocator, u8, build_runner_path));
|
||||
} else {
|
||||
var exe_dir_bytes: [std.fs.MAX_PATH_BYTES]u8 = undefined;
|
||||
const exe_dir_path = try std.fs.selfExeDirPath(&exe_dir_bytes);
|
||||
|
||||
const build_runner_path = try std.fs.path.resolve(allocator, &[_][]const u8{ exe_dir_path, "build_runner.zig" });
|
||||
try document_store.init(allocator, has_zig, build_runner_path);
|
||||
try document_store.init(allocator, zig_exe_path, build_runner_path);
|
||||
}
|
||||
|
||||
defer document_store.deinit();
|
||||
|
Loading…
Reference in New Issue
Block a user