Skip to content

Commit

Permalink
Watch for zls-build-info.json changes
Browse files Browse the repository at this point in the history
  • Loading branch information
SuperAuguste committed Dec 5, 2023
1 parent 4f0e4be commit fbc34f2
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 8 deletions.
19 changes: 18 additions & 1 deletion src/DocumentStore.zig
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,7 @@ pub fn refreshDocument(self: *DocumentStore, uri: Uri, new_text: [:0]const u8) !
handle.cimports = try collectCIncludes(self.allocator, handle.tree);
}

/// Invalidates a build files.
/// Invalidates a build file.
/// **Thread safe** takes an exclusive lock
pub fn invalidateBuildFile(self: *DocumentStore, build_file_uri: Uri) error{OutOfMemory}!void {
std.debug.assert(std.process.can_spawn);
Expand All @@ -675,6 +675,23 @@ pub fn invalidateBuildFile(self: *DocumentStore, build_file_uri: Uri) error{OutO
build_file.setBuildConfig(build_config);
}

/// **Thread safe** takes an exclusive lock
pub fn invalidateZlsBuildInfo(self: *DocumentStore, zls_build_info_uri: Uri) error{OutOfMemory}!void {
const zls_build_info_path = URI.parse(self.allocator, zls_build_info_uri) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
else => return,
};
defer self.allocator.free(zls_build_info_path);

const build_file_path = try std.fs.path.join(self.allocator, &.{ std.fs.path.dirname(std.fs.path.dirname(zls_build_info_path).?).?, "build.zig" });
defer self.allocator.free(build_file_path);

const build_file_uri = try URI.fromPath(self.allocator, build_file_path);
defer self.allocator.free(build_file_uri);

try self.invalidateBuildFile(build_file_uri);
}

/// The `DocumentStore` represents a graph structure where every
/// handle/document is a node and every `@import` and `@cImport` represent
/// a directed edge.
Expand Down
65 changes: 58 additions & 7 deletions src/Server.zig
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const ClientCapabilities = struct {
/// https://github.com/zigtools/zls/pull/261
max_detail_length: u32 = 1024 * 1024,
workspace_folders: []types.URI = &.{},
supports_workspace_didChangeWatchedFiles: bool = false,

fn deinit(self: *ClientCapabilities, allocator: std.mem.Allocator) void {
for (self.workspace_folders) |uri| allocator.free(uri);
Expand Down Expand Up @@ -479,6 +480,10 @@ fn initializeHandler(server: *Server, _: std.mem.Allocator, request: types.Initi
server.client_capabilities.supports_workspace_did_change_configuration_dynamic_registration = true;
}
}

if (workspace.didChangeWatchedFiles) |did_change_watched_files| {

Check warning on line 484 in src/Server.zig

View check run for this annotation

Codecov / codecov/patch

src/Server.zig#L484

Added line #L484 was not covered by tests
server.client_capabilities.supports_workspace_didChangeWatchedFiles = did_change_watched_files.dynamicRegistration orelse false;
}
}

if (request.workspaceFolders) |workspace_folders| {
Expand Down Expand Up @@ -618,7 +623,18 @@ fn initializedHandler(server: *Server, _: std.mem.Allocator, notification: types
server.status = .initialized;

if (!server.recording_enabled and server.client_capabilities.supports_workspace_did_change_configuration_dynamic_registration) {
try server.registerCapability("workspace/didChangeConfiguration");
try server.registerCapability("workspace/didChangeConfiguration", .{});

Check warning on line 626 in src/Server.zig

View check run for this annotation

Codecov / codecov/patch

src/Server.zig#L626

Added line #L626 was not covered by tests
}

if (server.client_capabilities.supports_workspace_didChangeWatchedFiles) {
try server.registerCapability("workspace/didChangeWatchedFiles", .{

Check warning on line 630 in src/Server.zig

View check run for this annotation

Codecov / codecov/patch

src/Server.zig#L630

Added line #L630 was not covered by tests
.watchers = &.{
.{
.globPattern = .{ .Pattern = "zig-cache/zls-build-info.json" },
.kind = .Change,
},
},
});
}

if (server.client_capabilities.supports_configuration)
Expand Down Expand Up @@ -650,7 +666,23 @@ fn setTraceHandler(server: *Server, _: std.mem.Allocator, request: types.SetTrac
}
}

fn registerCapability(server: *Server, method: []const u8) Error!void {
pub fn RegistrationOptions(comptime method: []const u8) type {
for (types.notification_metadata) |notif| {
if (std.mem.eql(u8, method, notif.method)) return notif.registration.Options orelse void;
}

for (types.request_metadata) |req| {
if (std.mem.eql(u8, method, req.method)) return req.registration.Options orelse void;
}

@compileError("No registration options available for method " ++ method);
}

fn registerCapability(
server: *Server,
comptime method: []const u8,
registration_options: RegistrationOptions(method),
) Error!void {

Check warning on line 685 in src/Server.zig

View check run for this annotation

Codecov / codecov/patch

src/Server.zig#L685

Added line #L685 was not covered by tests
const id = try std.fmt.allocPrint(server.allocator, "register-{s}", .{method});
defer server.allocator.free(id);

Expand All @@ -659,12 +691,15 @@ fn registerCapability(server: *Server, method: []const u8) Error!void {
const json_message = try server.sendToClientRequest(
.{ .string = id },
"client/registerCapability",
types.RegistrationParams{ .registrations = &.{
types.Registration{
.id = id,
.method = method,
.{
.registrations = &.{
.{
.id = id,
.method = method,
.registerOptions = registration_options,
},
},
} },
},
);
server.allocator.free(json_message);
}
Expand Down Expand Up @@ -1145,6 +1180,19 @@ fn resolveConfiguration(server: *Server, config_arena: std.mem.Allocator, config
}
}

fn didChangeWatchedFilesHandler(server: *Server, arena: std.mem.Allocator, notification: types.DidChangeWatchedFilesParams) Error!void {
_ = arena;

std.log.info("DID CHANGE!", .{});

for (notification.changes) |change| {
std.log.info("DID CHANGE! {s}", .{change.uri});
if (std.mem.indexOf(u8, change.uri, "zls-build-info.json") != null) {
try server.document_store.invalidateZlsBuildInfo(change.uri);
}
}
}

fn openDocumentHandler(server: *Server, _: std.mem.Allocator, notification: types.DidOpenTextDocumentParams) Error!void {
if (notification.textDocument.text.len > DocumentStore.max_document_size) {
log.err("open document `{s}` failed: text size ({d}) is above maximum length ({d})", .{
Expand Down Expand Up @@ -1712,6 +1760,7 @@ pub const Message = struct {
@"textDocument/didClose": types.DidCloseTextDocumentParams,
@"workspace/didChangeWorkspaceFolders": types.DidChangeWorkspaceFoldersParams,
@"workspace/didChangeConfiguration": types.DidChangeConfigurationParams,
@"workspace/didChangeWatchedFiles": types.DidChangeWatchedFilesParams,
unknown: []const u8,
};

Expand Down Expand Up @@ -1870,6 +1919,7 @@ pub const Message = struct {
.@"textDocument/didClose",
.@"workspace/didChangeWorkspaceFolders",
.@"workspace/didChangeConfiguration",
.@"workspace/didChangeWatchedFiles",
=> return true,
.unknown => return false,
},
Expand Down Expand Up @@ -2082,6 +2132,7 @@ pub fn sendNotificationSync(server: *Server, arena: std.mem.Allocator, comptime
.@"textDocument/didClose" => try server.closeDocumentHandler(arena, params),
.@"workspace/didChangeWorkspaceFolders" => try server.didChangeWorkspaceFoldersHandler(arena, params),
.@"workspace/didChangeConfiguration" => try server.didChangeConfigurationHandler(arena, params),
.@"workspace/didChangeWatchedFiles" => try server.didChangeWatchedFilesHandler(arena, params),
.unknown => return,
};
}
Expand Down

0 comments on commit fbc34f2

Please sign in to comment.