Configuration handling fixes (#995)
* Fortify `server.handleConfiguration`. * Move call to `server.registerCapability` within `server.initializedHandler`(was being sent prematurely).
This commit is contained in:
parent
409c203317
commit
b28d3aadd7
@ -69,6 +69,7 @@ const ClientCapabilities = packed struct {
|
|||||||
completion_doc_supports_md: bool = false,
|
completion_doc_supports_md: bool = false,
|
||||||
label_details_support: bool = false,
|
label_details_support: bool = false,
|
||||||
supports_configuration: bool = false,
|
supports_configuration: bool = false,
|
||||||
|
supports_workspace_did_change_configuration_dynamic_registration: bool = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Error = std.mem.Allocator.Error || error{
|
pub const Error = std.mem.Allocator.Error || error{
|
||||||
@ -1853,7 +1854,7 @@ fn initializeHandler(server: *Server, request: types.InitializeParams) Error!typ
|
|||||||
server.client_capabilities.supports_configuration = workspace.configuration orelse false;
|
server.client_capabilities.supports_configuration = workspace.configuration orelse false;
|
||||||
if (workspace.didChangeConfiguration) |did_change| {
|
if (workspace.didChangeConfiguration) |did_change| {
|
||||||
if (did_change.dynamicRegistration orelse false) {
|
if (did_change.dynamicRegistration orelse false) {
|
||||||
try server.registerCapability("workspace/didChangeConfiguration");
|
server.client_capabilities.supports_workspace_did_change_configuration_dynamic_registration = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1995,6 +1996,10 @@ fn initializedHandler(server: *Server, notification: types.InitializedParams) Er
|
|||||||
|
|
||||||
server.status = .initialized;
|
server.status = .initialized;
|
||||||
|
|
||||||
|
if (server.client_capabilities.supports_workspace_did_change_configuration_dynamic_registration) {
|
||||||
|
try server.registerCapability("workspace/didChangeConfiguration");
|
||||||
|
}
|
||||||
|
|
||||||
if (server.client_capabilities.supports_configuration)
|
if (server.client_capabilities.supports_configuration)
|
||||||
try server.requestConfiguration();
|
try server.requestConfiguration();
|
||||||
}
|
}
|
||||||
@ -2090,27 +2095,37 @@ fn handleConfiguration(server: *Server, json: std.json.Value) error{OutOfMemory}
|
|||||||
const new_value: field.type = switch (ft) {
|
const new_value: field.type = switch (ft) {
|
||||||
[]const u8 => switch (value) {
|
[]const u8 => switch (value) {
|
||||||
.String => |s| blk: {
|
.String => |s| blk: {
|
||||||
if (s.len == 0) {
|
const trimmed = std.mem.trim(u8, s, " ");
|
||||||
if (field.type == ?[]const u8) {
|
if (trimmed.len == 0 or std.mem.eql(u8, trimmed, "nil")) {
|
||||||
break :blk null;
|
log.warn("Ignoring new value for \"zls.{s}\": the given new value is invalid", .{field.name});
|
||||||
} else {
|
break :blk @field(server.config, field.name);
|
||||||
break :blk s;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var nv = try server.allocator.dupe(u8, s);
|
var nv = try server.allocator.dupe(u8, trimmed);
|
||||||
if (@field(server.config, field.name)) |prev_val| server.allocator.free(prev_val);
|
if (@field(server.config, field.name)) |prev_val| server.allocator.free(prev_val);
|
||||||
break :blk nv;
|
break :blk nv;
|
||||||
}, // TODO: Allocation model? (same with didChangeConfiguration); imo this isn't *that* bad but still
|
},
|
||||||
else => @panic("Invalid configuration value"), // TODO: Handle this
|
else => blk: {
|
||||||
|
log.warn("Ignoring new value for \"zls.{s}\": the given new value has an invalid type", .{field.name});
|
||||||
|
break :blk @field(server.config, field.name);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
else => switch (ti) {
|
else => switch (ti) {
|
||||||
.Int => switch (value) {
|
.Int => switch (value) {
|
||||||
.Integer => |s| std.math.cast(ft, s) orelse @panic("Invalid configuration value"),
|
.Integer => |val| std.math.cast(ft, val) orelse blk: {
|
||||||
else => @panic("Invalid configuration value"), // TODO: Handle this
|
log.warn("Ignoring new value for \"zls.{s}\": the given new value is invalid", .{field.name});
|
||||||
|
break :blk @field(server.config, field.name);
|
||||||
|
},
|
||||||
|
else => blk: {
|
||||||
|
log.warn("Ignoring new value for \"zls.{s}\": the given new value has an invalid type", .{field.name});
|
||||||
|
break :blk @field(server.config, field.name);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
.Bool => switch (value) {
|
.Bool => switch (value) {
|
||||||
.Bool => |b| b,
|
.Bool => |b| b,
|
||||||
else => @panic("Invalid configuration value"), // TODO: Handle this
|
else => blk: {
|
||||||
|
log.warn("Ignoring new value for \"zls.{s}\": the given new value has an invalid type", .{field.name});
|
||||||
|
break :blk @field(server.config, field.name);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
else => @compileError("Not implemented for " ++ @typeName(ft)),
|
else => @compileError("Not implemented for " ++ @typeName(ft)),
|
||||||
},
|
},
|
||||||
@ -2941,7 +2956,12 @@ fn processMessage(server: *Server, message: Message) Error!void {
|
|||||||
},
|
},
|
||||||
.ResponseMessage => |response| {
|
.ResponseMessage => |response| {
|
||||||
if (response.id != .string) return;
|
if (response.id != .string) return;
|
||||||
if (std.mem.startsWith(u8, response.id.string, "register")) return;
|
if (std.mem.startsWith(u8, response.id.string, "register")) {
|
||||||
|
if (response.@"error") |err| {
|
||||||
|
log.err("Error response for '{s}': {}, {s}", .{ response.id.string, err.code, err.message });
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (std.mem.eql(u8, response.id.string, "apply_edit")) return;
|
if (std.mem.eql(u8, response.id.string, "apply_edit")) return;
|
||||||
|
|
||||||
if (std.mem.eql(u8, response.id.string, "i_haz_configuration")) {
|
if (std.mem.eql(u8, response.id.string, "i_haz_configuration")) {
|
||||||
|
Loading…
Reference in New Issue
Block a user