show a warning when using an old zig version (#677)

* show a warning when using an old zig version

* use builtin zig version
This commit is contained in:
Techatrix 2022-09-29 01:30:26 +02:00 committed by GitHub
parent 8cf93fc96a
commit e3803d760f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 43 deletions

View File

@ -127,51 +127,18 @@ pub fn configChanged(config: *Config, allocator: std.mem.Allocator, builtin_crea
config.zig_exe_path = try setup.findZig(allocator); config.zig_exe_path = try setup.findZig(allocator);
} }
if (config.zig_exe_path) |exe_path| { if (config.zig_exe_path) |exe_path| blk: {
logger.info("Using zig executable {s}", .{exe_path}); logger.info("Using zig executable {s}", .{exe_path});
if (config.zig_lib_path == null) find_lib_path: { if (config.zig_lib_path != null) break :blk;
// 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 { var env = getZigEnv(allocator, exe_path) orelse break :blk;
allocator.free(zig_env_result.stdout); defer std.json.parseFree(Env, env, .{ .allocator = allocator });
allocator.free(zig_env_result.stderr);
}
switch (zig_env_result.term) { // We know this is allocated with `allocator`, we just steal it!
.Exited => |exit_code| { config.zig_lib_path = env.lib_dir.?;
if (exit_code == 0) { env.lib_dir = null;
const Env = struct { logger.info("Using zig lib path '{s}'", .{config.zig_lib_path.?});
zig_exe: []const u8,
lib_dir: ?[]const u8,
std_dir: []const u8,
global_cache_dir: []const u8,
version: []const u8,
target: ?[]const u8 = null,
};
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 { } else {
logger.warn("Zig executable path not specified in zls.json and could not be found in PATH", .{}); logger.warn("Zig executable path not specified in zls.json and could not be found in PATH", .{});
} }
@ -231,3 +198,51 @@ pub fn configChanged(config: *Config, allocator: std.mem.Allocator, builtin_crea
try file.writeAll(@embedFile("special/build_runner.zig")); try file.writeAll(@embedFile("special/build_runner.zig"));
} }
} }
pub const Env = struct {
zig_exe: []const u8,
lib_dir: ?[]const u8,
std_dir: []const u8,
global_cache_dir: []const u8,
version: []const u8,
target: ?[]const u8 = null,
};
/// result has to be freed with `std.json.parseFree`
pub fn getZigEnv(allocator: std.mem.Allocator, zig_exe_path: []const u8) ?Env {
const zig_env_result = std.ChildProcess.exec(.{
.allocator = allocator,
.argv = &[_][]const u8{ zig_exe_path, "env" },
}) catch {
logger.err("Failed to execute zig env", .{});
return null;
};
defer {
allocator.free(zig_env_result.stdout);
allocator.free(zig_env_result.stderr);
}
switch (zig_env_result.term) {
.Exited => |code| {
if (code != 0) {
logger.err("zig env failed with error_code: {}", .{code});
return null;
}
},
else => logger.err("zig env invocation failed", .{}),
}
var token_stream = std.json.TokenStream.init(zig_env_result.stdout);
return std.json.parse(
Env,
&token_stream,
.{
.allocator = allocator,
.ignore_unknown_fields = true,
},
) catch {
logger.err("Failed to parse zig env JSON result", .{});
return null;
};
}

View File

@ -133,10 +133,10 @@ fn respondGeneric(writer: anytype, id: types.RequestId, response: []const u8) !v
} }
fn showMessage(server: *Server, writer: anytype, message_type: types.MessageType, message: []const u8) !void { fn showMessage(server: *Server, writer: anytype, message_type: types.MessageType, message: []const u8) !void {
try send(writer, server.allocator, types.Notification{ try send(writer, server.arena.allocator(), types.Notification{
.method = "window/showMessage", .method = "window/showMessage",
.params = .{ .params = .{
.ShowMessageParams = .{ .ShowMessage = .{
.type = message_type, .type = message_type,
.message = message, .message = message,
}, },
@ -1600,6 +1600,20 @@ fn initializeHandler(server: *Server, writer: anytype, id: types.RequestId, req:
log.info("zls initialized", .{}); log.info("zls initialized", .{});
log.info("{}", .{server.client_capabilities}); log.info("{}", .{server.client_capabilities});
log.info("Using offset encoding: {s}", .{std.meta.tagName(server.offset_encoding)}); log.info("Using offset encoding: {s}", .{std.meta.tagName(server.offset_encoding)});
// TODO avoid having to call getZigEnv twice
// once in init and here
const env = Config.getZigEnv(server.allocator, server.config.zig_exe_path.?) orelse return;
defer std.json.parseFree(Config.Env, env, .{ .allocator = server.allocator });
const zig_exe_version = std.SemanticVersion.parse(env.version) catch return;
if (zig_builtin.zig_version.order(zig_exe_version) == .gt) {
try server.showMessage(writer, .Warning,
\\ZLS has been build with a newer version than you are using!
\\This may cause unexpected issues.
);
}
} }
fn registerCapability(server: *Server, writer: anytype, method: []const u8) !void { fn registerCapability(server: *Server, writer: anytype, method: []const u8) !void {