feat: send didChange, didSave and didClose events to language server
This commit is contained in:
parent
1288021682
commit
5375e1449e
5 changed files with 191 additions and 2 deletions
125
src/Project.zig
125
src/Project.zig
|
@ -2,6 +2,8 @@ const std = @import("std");
|
|||
const tp = @import("thespian");
|
||||
const cbor = @import("cbor");
|
||||
const root = @import("root");
|
||||
const dizzy = @import("dizzy");
|
||||
const Buffer = @import("Buffer");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const LSP = @import("LSP.zig");
|
||||
|
@ -185,6 +187,129 @@ pub fn did_open(self: *Self, from: tp.pid_ref, file_path: []const u8, file_type:
|
|||
});
|
||||
}
|
||||
|
||||
pub fn did_change(self: *Self, file_path: []const u8, version: usize, root_dst_addr: usize, root_src_addr: usize) !void {
|
||||
const lsp = try self.get_file_lsp(file_path);
|
||||
const uri = self.make_URI(file_path) catch |e| return tp.exit_error(e);
|
||||
defer self.a.free(uri);
|
||||
|
||||
const root_dst: Buffer.Root = if (root_dst_addr == 0) return else @ptrFromInt(root_dst_addr);
|
||||
const root_src: Buffer.Root = if (root_src_addr == 0) return else @ptrFromInt(root_src_addr);
|
||||
|
||||
var dizzy_edits = std.ArrayListUnmanaged(dizzy.Edit){};
|
||||
var dst = std.ArrayList(u8).init(self.a);
|
||||
var src = std.ArrayList(u8).init(self.a);
|
||||
var scratch = std.ArrayListUnmanaged(u32){};
|
||||
var edits_cb = std.ArrayList(u8).init(self.a);
|
||||
const writer = edits_cb.writer();
|
||||
|
||||
defer {
|
||||
edits_cb.deinit();
|
||||
dst.deinit();
|
||||
src.deinit();
|
||||
scratch.deinit(self.a);
|
||||
dizzy_edits.deinit(self.a);
|
||||
}
|
||||
|
||||
try root_dst.store(dst.writer());
|
||||
try root_src.store(src.writer());
|
||||
|
||||
const scratch_len = 4 * (dst.items.len + src.items.len) + 2;
|
||||
try scratch.ensureTotalCapacity(self.a, scratch_len);
|
||||
scratch.items.len = scratch_len;
|
||||
|
||||
try dizzy.PrimitiveSliceDiffer(u8).diff(self.a, &dizzy_edits, src.items, dst.items, scratch.items);
|
||||
|
||||
var lines_dst: usize = 0;
|
||||
var pos_src: usize = 0;
|
||||
var pos_dst: usize = 0;
|
||||
var last_offset: usize = 0;
|
||||
var edits_count: usize = 0;
|
||||
|
||||
for (dizzy_edits.items) |dizzy_edit| {
|
||||
switch (dizzy_edit.kind) {
|
||||
.equal => {
|
||||
const dist = dizzy_edit.range.end - dizzy_edit.range.start;
|
||||
pos_src += dist;
|
||||
pos_dst += dist;
|
||||
scan_char(src.items[dizzy_edit.range.start..dizzy_edit.range.end], &lines_dst, '\n', &last_offset);
|
||||
},
|
||||
.insert => {
|
||||
const dist = dizzy_edit.range.end - dizzy_edit.range.start;
|
||||
pos_src += 0;
|
||||
pos_dst += dist;
|
||||
const line_start_dst: usize = lines_dst;
|
||||
scan_char(dst.items[dizzy_edit.range.start..dizzy_edit.range.end], &lines_dst, '\n', null);
|
||||
try cbor.writeValue(writer, .{
|
||||
.range = .{
|
||||
.start = .{ .line = line_start_dst, .character = last_offset },
|
||||
.end = .{ .line = line_start_dst, .character = last_offset },
|
||||
},
|
||||
.text = dst.items[dizzy_edit.range.start..dizzy_edit.range.end],
|
||||
});
|
||||
edits_count += 1;
|
||||
},
|
||||
.delete => {
|
||||
const dist = dizzy_edit.range.end - dizzy_edit.range.start;
|
||||
pos_src += dist;
|
||||
pos_dst += 0;
|
||||
var line_end_dst: usize = lines_dst;
|
||||
var offset_end_dst: usize = last_offset;
|
||||
scan_char(src.items[dizzy_edit.range.start..dizzy_edit.range.end], &line_end_dst, '\n', &offset_end_dst);
|
||||
if (lines_dst == line_end_dst) offset_end_dst = last_offset + dist;
|
||||
try cbor.writeValue(writer, .{
|
||||
.range = .{
|
||||
.start = .{ .line = lines_dst, .character = last_offset },
|
||||
.end = .{ .line = line_end_dst, .character = offset_end_dst },
|
||||
},
|
||||
.text = "",
|
||||
});
|
||||
edits_count += 1;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var msg = std.ArrayList(u8).init(self.a);
|
||||
defer msg.deinit();
|
||||
const msg_writer = msg.writer();
|
||||
try cbor.writeMapHeader(msg_writer, 2);
|
||||
try cbor.writeValue(msg_writer, "textDocument");
|
||||
try cbor.writeValue(msg_writer, .{ .uri = uri, .version = version });
|
||||
try cbor.writeValue(msg_writer, "contentChanges");
|
||||
try cbor.writeArrayHeader(msg_writer, edits_count);
|
||||
_ = try msg_writer.write(edits_cb.items);
|
||||
|
||||
try lsp.send_notification_raw("textDocument/didChange", msg.items);
|
||||
}
|
||||
|
||||
fn scan_char(chars: []const u8, lines: *usize, char: u8, last_offset: ?*usize) void {
|
||||
var pos = chars;
|
||||
while (pos.len > 0) {
|
||||
if (pos[0] == char) {
|
||||
if (last_offset) |off| off.* = pos.len - 1;
|
||||
lines.* += 1;
|
||||
}
|
||||
pos = pos[1..];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn did_save(self: *Self, file_path: []const u8) tp.result {
|
||||
const lsp = try self.get_file_lsp(file_path);
|
||||
const uri = self.make_URI(file_path) catch |e| return tp.exit_error(e);
|
||||
defer self.a.free(uri);
|
||||
try lsp.send_notification("textDocument/didSave", .{
|
||||
.textDocument = .{ .uri = uri },
|
||||
});
|
||||
}
|
||||
|
||||
pub fn did_close(self: *Self, file_path: []const u8) tp.result {
|
||||
const lsp = try self.get_file_lsp(file_path);
|
||||
const uri = self.make_URI(file_path) catch |e| return tp.exit_error(e);
|
||||
defer self.a.free(uri);
|
||||
try lsp.send_notification("textDocument/didClose", .{
|
||||
.textDocument = .{ .uri = uri },
|
||||
});
|
||||
}
|
||||
|
||||
pub fn goto_definition(self: *Self, from: tp.pid_ref, file_path: []const u8, row: usize, col: usize) !void {
|
||||
const lsp = try self.get_file_lsp(file_path);
|
||||
const uri = self.make_URI(file_path) catch |e| return tp.exit_error(e);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue