reimplement document store
This commit is contained in:
parent
ac6353add7
commit
dab7eb81cc
File diff suppressed because it is too large
Load Diff
@ -151,7 +151,7 @@ fn showMessage(server: *Server, writer: anytype, message_type: types.MessageType
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn publishDiagnostics(server: *Server, writer: anytype, handle: *DocumentStore.Handle) !void {
|
fn publishDiagnostics(server: *Server, writer: anytype, handle: DocumentStore.Handle) !void {
|
||||||
const tracy_zone = tracy.trace(@src());
|
const tracy_zone = tracy.trace(@src());
|
||||||
defer tracy_zone.end();
|
defer tracy_zone.end();
|
||||||
|
|
||||||
@ -252,17 +252,19 @@ fn publishDiagnostics(server: *Server, writer: anytype, handle: *DocumentStore.H
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (handle.cimports) |cimport| {
|
for (handle.cimports.items(.hash)) |hash, i| {
|
||||||
if (cimport.result != .failure) continue;
|
const result = server.document_store.cimports.get(hash) orelse continue;
|
||||||
const stderr = std.mem.trim(u8, cimport.result.failure, " ");
|
if (result != .failure) continue;
|
||||||
|
const stderr = std.mem.trim(u8, result.failure, " ");
|
||||||
|
|
||||||
var pos_and_diag_iterator = std.mem.split(u8, stderr, ":");
|
var pos_and_diag_iterator = std.mem.split(u8, stderr, ":");
|
||||||
_ = pos_and_diag_iterator.next(); // skip file path
|
_ = pos_and_diag_iterator.next(); // skip file path
|
||||||
_ = pos_and_diag_iterator.next(); // skip line
|
_ = pos_and_diag_iterator.next(); // skip line
|
||||||
_ = pos_and_diag_iterator.next(); // skip character
|
_ = pos_and_diag_iterator.next(); // skip character
|
||||||
|
|
||||||
|
const node = handle.cimports.items(.node)[i];
|
||||||
try diagnostics.append(allocator, .{
|
try diagnostics.append(allocator, .{
|
||||||
.range = offsets.nodeToRange(handle.tree, cimport.node, server.offset_encoding),
|
.range = offsets.nodeToRange(handle.tree, node, server.offset_encoding),
|
||||||
.severity = .Error,
|
.severity = .Error,
|
||||||
.code = "cImport",
|
.code = "cImport",
|
||||||
.source = "zls",
|
.source = "zls",
|
||||||
@ -283,7 +285,7 @@ fn publishDiagnostics(server: *Server, writer: anytype, handle: *DocumentStore.H
|
|||||||
|
|
||||||
fn getAstCheckDiagnostics(
|
fn getAstCheckDiagnostics(
|
||||||
server: *Server,
|
server: *Server,
|
||||||
handle: *DocumentStore.Handle,
|
handle: DocumentStore.Handle,
|
||||||
diagnostics: *std.ArrayListUnmanaged(types.Diagnostic),
|
diagnostics: *std.ArrayListUnmanaged(types.Diagnostic),
|
||||||
) !void {
|
) !void {
|
||||||
var allocator = server.arena.allocator();
|
var allocator = server.arena.allocator();
|
||||||
@ -966,10 +968,7 @@ fn gotoDefinitionString(
|
|||||||
defer tracy_zone.end();
|
defer tracy_zone.end();
|
||||||
|
|
||||||
const import_str = analysis.getImportStr(handle.tree, 0, pos_index) orelse return null;
|
const import_str = analysis.getImportStr(handle.tree, 0, pos_index) orelse return null;
|
||||||
const uri = server.document_store.uriFromImportStr(server.arena.allocator(), handle.*, import_str) catch |err| switch (err) {
|
const uri = try server.document_store.uriFromImportStr(server.arena.allocator(), handle.*, import_str);
|
||||||
error.UriBadScheme => return null,
|
|
||||||
error.OutOfMemory => |e| return e,
|
|
||||||
};
|
|
||||||
|
|
||||||
return types.Location{
|
return types.Location{
|
||||||
.uri = uri orelse return null,
|
.uri = uri orelse return null,
|
||||||
@ -1327,7 +1326,7 @@ fn completeError(server: *Server, handle: *DocumentStore.Handle) ![]types.Comple
|
|||||||
const tracy_zone = tracy.trace(@src());
|
const tracy_zone = tracy.trace(@src());
|
||||||
defer tracy_zone.end();
|
defer tracy_zone.end();
|
||||||
|
|
||||||
return try server.document_store.errorCompletionItems(&server.arena, handle);
|
return try server.document_store.errorCompletionItems(server.arena.allocator(), handle.*);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kindToSortScore(kind: types.CompletionItem.Kind) ?[]const u8 {
|
fn kindToSortScore(kind: types.CompletionItem.Kind) ?[]const u8 {
|
||||||
@ -1362,12 +1361,12 @@ fn completeDot(server: *Server, handle: *DocumentStore.Handle) ![]types.Completi
|
|||||||
const tracy_zone = tracy.trace(@src());
|
const tracy_zone = tracy.trace(@src());
|
||||||
defer tracy_zone.end();
|
defer tracy_zone.end();
|
||||||
|
|
||||||
var completions = try server.document_store.enumCompletionItems(&server.arena, handle);
|
var completions = try server.document_store.enumCompletionItems(server.arena.allocator(), handle.*);
|
||||||
|
|
||||||
return completions;
|
return completions;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn completeFileSystemStringLiteral(allocator: std.mem.Allocator, handle: *DocumentStore.Handle, completing: []const u8, is_import: bool) ![]types.CompletionItem {
|
fn completeFileSystemStringLiteral(allocator: std.mem.Allocator, store: *const DocumentStore, handle: *DocumentStore.Handle, completing: []const u8, is_import: bool) ![]types.CompletionItem {
|
||||||
var subpath_present = false;
|
var subpath_present = false;
|
||||||
var completions = std.ArrayListUnmanaged(types.CompletionItem){};
|
var completions = std.ArrayListUnmanaged(types.CompletionItem){};
|
||||||
|
|
||||||
@ -1407,10 +1406,11 @@ fn completeFileSystemStringLiteral(allocator: std.mem.Allocator, handle: *Docume
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!subpath_present and is_import) {
|
if (!subpath_present and is_import) {
|
||||||
if (handle.associated_build_file) |bf| {
|
if (handle.associated_build_file) |uri| {
|
||||||
try completions.ensureUnusedCapacity(allocator, bf.config.packages.len);
|
const build_file = store.build_files.get(uri).?;
|
||||||
|
try completions.ensureUnusedCapacity(allocator, build_file.config.packages.len);
|
||||||
|
|
||||||
for (bf.config.packages) |pkg| {
|
for (build_file.config.packages) |pkg| {
|
||||||
completions.appendAssumeCapacity(.{
|
completions.appendAssumeCapacity(.{
|
||||||
.label = pkg.name,
|
.label = pkg.name,
|
||||||
.kind = .Module,
|
.kind = .Module,
|
||||||
@ -1704,13 +1704,14 @@ fn changeDocumentHandler(server: *Server, writer: anytype, id: types.RequestId,
|
|||||||
|
|
||||||
_ = id;
|
_ = id;
|
||||||
|
|
||||||
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse return;
|
||||||
log.debug("Trying to change non existent document {s}", .{req.params.textDocument.uri});
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
try server.document_store.applyChanges(handle, req.params.contentChanges, server.offset_encoding);
|
const new_text = try diff.applyTextEdits(server.allocator, handle.text, req.params.contentChanges, server.offset_encoding);
|
||||||
try server.publishDiagnostics(writer, handle);
|
server.allocator.free(handle.text);
|
||||||
|
handle.text = new_text;
|
||||||
|
|
||||||
|
try server.document_store.refreshDocument(handle);
|
||||||
|
try server.publishDiagnostics(writer, handle.*);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn saveDocumentHandler(server: *Server, writer: anytype, id: types.RequestId, req: requests.SaveDocument) !void {
|
fn saveDocumentHandler(server: *Server, writer: anytype, id: types.RequestId, req: requests.SaveDocument) !void {
|
||||||
@ -1721,10 +1722,7 @@ fn saveDocumentHandler(server: *Server, writer: anytype, id: types.RequestId, re
|
|||||||
const allocator = server.arena.allocator();
|
const allocator = server.arena.allocator();
|
||||||
const uri = req.params.textDocument.uri;
|
const uri = req.params.textDocument.uri;
|
||||||
|
|
||||||
const handle = server.document_store.getHandle(uri) orelse {
|
const handle = server.document_store.getHandle(uri) orelse return;
|
||||||
log.warn("Trying to save non existent document {s}", .{uri});
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
try server.document_store.applySave(handle);
|
try server.document_store.applySave(handle);
|
||||||
|
|
||||||
if (handle.tree.errors.len != 0) return;
|
if (handle.tree.errors.len != 0) return;
|
||||||
@ -1732,7 +1730,7 @@ fn saveDocumentHandler(server: *Server, writer: anytype, id: types.RequestId, re
|
|||||||
if (!server.config.enable_autofix) return;
|
if (!server.config.enable_autofix) return;
|
||||||
|
|
||||||
var diagnostics = std.ArrayListUnmanaged(types.Diagnostic){};
|
var diagnostics = std.ArrayListUnmanaged(types.Diagnostic){};
|
||||||
try getAstCheckDiagnostics(server, handle, &diagnostics);
|
try getAstCheckDiagnostics(server, handle.*, &diagnostics);
|
||||||
|
|
||||||
var builder = code_actions.Builder{
|
var builder = code_actions.Builder{
|
||||||
.arena = &server.arena,
|
.arena = &server.arena,
|
||||||
@ -1790,7 +1788,6 @@ fn semanticTokensFullHandler(server: *Server, writer: anytype, id: types.Request
|
|||||||
if (!server.config.enable_semantic_tokens) return try respondGeneric(writer, id, no_semantic_tokens_response);
|
if (!server.config.enable_semantic_tokens) return try respondGeneric(writer, id, no_semantic_tokens_response);
|
||||||
|
|
||||||
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
||||||
log.warn("Trying to get semantic tokens of non existent document {s}", .{req.params.textDocument.uri});
|
|
||||||
return try respondGeneric(writer, id, no_semantic_tokens_response);
|
return try respondGeneric(writer, id, no_semantic_tokens_response);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1807,7 +1804,6 @@ fn completionHandler(server: *Server, writer: anytype, id: types.RequestId, req:
|
|||||||
defer tracy_zone.end();
|
defer tracy_zone.end();
|
||||||
|
|
||||||
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
||||||
log.warn("Trying to complete in non existent document {s}", .{req.params.textDocument.uri});
|
|
||||||
return try respondGeneric(writer, id, no_completions_response);
|
return try respondGeneric(writer, id, no_completions_response);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1838,7 +1834,7 @@ fn completionHandler(server: *Server, writer: anytype, id: types.RequestId, req:
|
|||||||
|
|
||||||
const completing = offsets.locToSlice(handle.tree.source, loc);
|
const completing = offsets.locToSlice(handle.tree.source, loc);
|
||||||
const is_import = pos_context == .import_string_literal;
|
const is_import = pos_context == .import_string_literal;
|
||||||
break :blk try completeFileSystemStringLiteral(server.arena.allocator(), handle, completing, is_import);
|
break :blk try completeFileSystemStringLiteral(server.arena.allocator(), &server.document_store, handle, completing, is_import);
|
||||||
},
|
},
|
||||||
else => null,
|
else => null,
|
||||||
};
|
};
|
||||||
@ -1878,7 +1874,6 @@ fn signatureHelpHandler(server: *Server, writer: anytype, id: types.RequestId, r
|
|||||||
|
|
||||||
const getSignatureInfo = @import("signature_help.zig").getSignatureInfo;
|
const getSignatureInfo = @import("signature_help.zig").getSignatureInfo;
|
||||||
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
||||||
log.warn("Trying to get signature help in non existent document {s}", .{req.params.textDocument.uri});
|
|
||||||
return try respondGeneric(writer, id, no_signatures_response);
|
return try respondGeneric(writer, id, no_signatures_response);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1912,7 +1907,6 @@ fn gotoHandler(server: *Server, writer: anytype, id: types.RequestId, req: reque
|
|||||||
defer tracy_zone.end();
|
defer tracy_zone.end();
|
||||||
|
|
||||||
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
||||||
log.warn("Trying to go to definition in non existent document {s}", .{req.params.textDocument.uri});
|
|
||||||
return try respondGeneric(writer, id, null_result_response);
|
return try respondGeneric(writer, id, null_result_response);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1956,7 +1950,6 @@ fn hoverHandler(server: *Server, writer: anytype, id: types.RequestId, req: requ
|
|||||||
defer tracy_zone.end();
|
defer tracy_zone.end();
|
||||||
|
|
||||||
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
||||||
log.warn("Trying to get hover in non existent document {s}", .{req.params.textDocument.uri});
|
|
||||||
return try respondGeneric(writer, id, null_result_response);
|
return try respondGeneric(writer, id, null_result_response);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1986,7 +1979,6 @@ fn documentSymbolsHandler(server: *Server, writer: anytype, id: types.RequestId,
|
|||||||
defer tracy_zone.end();
|
defer tracy_zone.end();
|
||||||
|
|
||||||
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
||||||
log.warn("Trying to get document symbols in non existent document {s}", .{req.params.textDocument.uri});
|
|
||||||
return try respondGeneric(writer, id, null_result_response);
|
return try respondGeneric(writer, id, null_result_response);
|
||||||
};
|
};
|
||||||
try server.documentSymbol(writer, id, handle);
|
try server.documentSymbol(writer, id, handle);
|
||||||
@ -1998,7 +1990,6 @@ fn formattingHandler(server: *Server, writer: anytype, id: types.RequestId, req:
|
|||||||
|
|
||||||
if (server.config.zig_exe_path) |zig_exe_path| {
|
if (server.config.zig_exe_path) |zig_exe_path| {
|
||||||
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
||||||
log.warn("Trying to got to definition in non existent document {s}", .{req.params.textDocument.uri});
|
|
||||||
return try respondGeneric(writer, id, null_result_response);
|
return try respondGeneric(writer, id, null_result_response);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2124,14 +2115,6 @@ const GeneralReferencesRequest = union(enum) {
|
|||||||
.highlight => |highlight| highlight.params.position,
|
.highlight => |highlight| highlight.params.position,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(self: @This()) []const u8 {
|
|
||||||
return switch (self) {
|
|
||||||
.rename => "rename",
|
|
||||||
.references => "references",
|
|
||||||
.highlight => "highlight references",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn generalReferencesHandler(server: *Server, writer: anytype, id: types.RequestId, req: GeneralReferencesRequest) !void {
|
fn generalReferencesHandler(server: *Server, writer: anytype, id: types.RequestId, req: GeneralReferencesRequest) !void {
|
||||||
@ -2141,7 +2124,6 @@ fn generalReferencesHandler(server: *Server, writer: anytype, id: types.RequestI
|
|||||||
const allocator = server.arena.allocator();
|
const allocator = server.arena.allocator();
|
||||||
|
|
||||||
const handle = server.document_store.getHandle(req.uri()) orelse {
|
const handle = server.document_store.getHandle(req.uri()) orelse {
|
||||||
log.warn("Trying to get {s} in non existent document {s}", .{ req.name(), req.uri() });
|
|
||||||
return try respondGeneric(writer, id, null_result_response);
|
return try respondGeneric(writer, id, null_result_response);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2223,7 +2205,6 @@ fn inlayHintHandler(server: *Server, writer: anytype, id: types.RequestId, req:
|
|||||||
if (!server.config.enable_inlay_hints) return try respondGeneric(writer, id, null_result_response);
|
if (!server.config.enable_inlay_hints) return try respondGeneric(writer, id, null_result_response);
|
||||||
|
|
||||||
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
||||||
log.warn("Trying to get inlay hint of non existent document {s}", .{req.params.textDocument.uri});
|
|
||||||
return try respondGeneric(writer, id, null_result_response);
|
return try respondGeneric(writer, id, null_result_response);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2272,7 +2253,6 @@ fn inlayHintHandler(server: *Server, writer: anytype, id: types.RequestId, req:
|
|||||||
|
|
||||||
fn codeActionHandler(server: *Server, writer: anytype, id: types.RequestId, req: requests.CodeAction) !void {
|
fn codeActionHandler(server: *Server, writer: anytype, id: types.RequestId, req: requests.CodeAction) !void {
|
||||||
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
|
||||||
log.warn("Trying to get code actions of non existent document {s}", .{req.params.textDocument.uri});
|
|
||||||
return try respondGeneric(writer, id, null_result_response);
|
return try respondGeneric(writer, id, null_result_response);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2402,12 +2382,12 @@ pub fn processJsonRpc(server: *Server, writer: anytype, json: []const u8) !void
|
|||||||
.shutdown => return try sendErrorResponse(writer, server.arena.allocator(), .InvalidRequest, "server received a request after shutdown!"),
|
.shutdown => return try sendErrorResponse(writer, server.arena.allocator(), .InvalidRequest, "server received a request after shutdown!"),
|
||||||
}
|
}
|
||||||
|
|
||||||
const start_time = std.time.milliTimestamp();
|
// const start_time = std.time.milliTimestamp();
|
||||||
defer {
|
defer {
|
||||||
// makes `zig build test` look nice
|
// makes `zig build test` look nice
|
||||||
if (!zig_builtin.is_test and !std.mem.eql(u8, method, "shutdown")) {
|
if (!zig_builtin.is_test and !std.mem.eql(u8, method, "shutdown")) {
|
||||||
const end_time = std.time.milliTimestamp();
|
// const end_time = std.time.milliTimestamp();
|
||||||
log.debug("Took {}ms to process method {s}", .{ end_time - start_time, method });
|
// log.debug("Took {}ms to process method {s}", .{ end_time - start_time, method });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2535,7 +2515,10 @@ pub fn init(
|
|||||||
|
|
||||||
try config.configChanged(allocator, config_path);
|
try config.configChanged(allocator, config_path);
|
||||||
|
|
||||||
var document_store = try DocumentStore.init(allocator, config);
|
var document_store = DocumentStore{
|
||||||
|
.allocator = allocator,
|
||||||
|
.config = config,
|
||||||
|
};
|
||||||
errdefer document_store.deinit();
|
errdefer document_store.deinit();
|
||||||
|
|
||||||
var builtin_completions = try std.ArrayListUnmanaged(types.CompletionItem).initCapacity(allocator, data.builtins.len);
|
var builtin_completions = try std.ArrayListUnmanaged(types.CompletionItem).initCapacity(allocator, data.builtins.len);
|
||||||
|
@ -912,18 +912,16 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
if (node_tags[import_param] != .string_literal) return null;
|
if (node_tags[import_param] != .string_literal) return null;
|
||||||
|
|
||||||
const import_str = tree.tokenSlice(main_tokens[import_param]);
|
const import_str = tree.tokenSlice(main_tokens[import_param]);
|
||||||
const new_handle = (store.resolveImport(handle, import_str[1 .. import_str.len - 1]) catch |err| {
|
const import_uri = (try store.uriFromImportStr(arena.allocator(), handle.*, import_str[1 .. import_str.len - 1])) orelse return null;
|
||||||
log.debug("Error {} while processing import {s}", .{ err, import_str });
|
|
||||||
return null;
|
const new_handle = store.getHandle(import_uri) orelse return null;
|
||||||
}) orelse return null;
|
|
||||||
|
|
||||||
// reference to node '0' which is root
|
// reference to node '0' which is root
|
||||||
return TypeWithHandle.typeVal(.{ .node = 0, .handle = new_handle });
|
return TypeWithHandle.typeVal(.{ .node = 0, .handle = new_handle });
|
||||||
} else if (std.mem.eql(u8, call_name, "@cImport")) {
|
} else if (std.mem.eql(u8, call_name, "@cImport")) {
|
||||||
const new_handle = (store.resolveCImport(handle, node) catch |err| {
|
const cimport_uri = (try store.resolveCImport(handle.*, node)) orelse return null;
|
||||||
log.debug("Error {} while processing cImport", .{err}); // TODO improve
|
|
||||||
return null;
|
const new_handle = store.getHandle(cimport_uri) orelse return null;
|
||||||
}) orelse return null;
|
|
||||||
|
|
||||||
// reference to node '0' which is root
|
// reference to node '0' which is root
|
||||||
return TypeWithHandle.typeVal(.{ .node = 0, .handle = new_handle });
|
return TypeWithHandle.typeVal(.{ .node = 0, .handle = new_handle });
|
||||||
@ -1088,7 +1086,6 @@ pub fn resolveTypeOfNode(store: *DocumentStore, arena: *std.heap.ArenaAllocator,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Collects all `@import`'s we can find into a slice of import paths (without quotes).
|
/// Collects all `@import`'s we can find into a slice of import paths (without quotes).
|
||||||
/// Caller owns returned memory.
|
|
||||||
pub fn collectImports(allocator: std.mem.Allocator, tree: Ast) error{OutOfMemory}!std.ArrayListUnmanaged([]const u8) {
|
pub fn collectImports(allocator: std.mem.Allocator, tree: Ast) error{OutOfMemory}!std.ArrayListUnmanaged([]const u8) {
|
||||||
var imports = std.ArrayListUnmanaged([]const u8){};
|
var imports = std.ArrayListUnmanaged([]const u8){};
|
||||||
errdefer {
|
errdefer {
|
||||||
|
36
src/diff.zig
36
src/diff.zig
@ -1,5 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const types = @import("types.zig");
|
const types = @import("types.zig");
|
||||||
|
const requests = @import("requests.zig");
|
||||||
|
const offsets = @import("offsets.zig");
|
||||||
|
|
||||||
pub const Error = error{ OutOfMemory, InvalidRange };
|
pub const Error = error{ OutOfMemory, InvalidRange };
|
||||||
|
|
||||||
@ -350,3 +352,37 @@ fn char_pos_to_range(
|
|||||||
.end = result_end_pos.?,
|
.end = result_end_pos.?,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Caller owns returned memory.
|
||||||
|
pub fn applyTextEdits(
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
text: []const u8,
|
||||||
|
content_changes: []const requests.TextDocumentContentChangeEvent,
|
||||||
|
encoding: offsets.Encoding,
|
||||||
|
) ![:0]const u8 {
|
||||||
|
var last_full_text_change: ?usize = null;
|
||||||
|
var i: usize = content_changes.len;
|
||||||
|
while (i > 0) {
|
||||||
|
i -= 1;
|
||||||
|
if (content_changes[i].range == null) {
|
||||||
|
last_full_text_change = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var text_array = std.ArrayListUnmanaged(u8){};
|
||||||
|
errdefer text_array.deinit(allocator);
|
||||||
|
|
||||||
|
try text_array.appendSlice(allocator, if (last_full_text_change) |index| content_changes[index].text else text);
|
||||||
|
|
||||||
|
// don't even bother applying changes before a full text change
|
||||||
|
const changes = content_changes[if (last_full_text_change) |index| index + 1 else 0..];
|
||||||
|
|
||||||
|
for (changes) |item| {
|
||||||
|
const range = item.range.?; // every element is guaranteed to have `range` set
|
||||||
|
|
||||||
|
const loc = offsets.rangeToLoc(text_array.items, range, encoding);
|
||||||
|
try text_array.replaceRange(allocator, loc.start, loc.end - loc.start, item.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return try text_array.toOwnedSliceSentinel(allocator, 0);
|
||||||
|
}
|
||||||
|
@ -479,26 +479,26 @@ pub fn symbolReferences(
|
|||||||
if (decl_handle.decl.* != .ast_node) return builder.locations;
|
if (decl_handle.decl.* != .ast_node) return builder.locations;
|
||||||
if (!workspace) return builder.locations;
|
if (!workspace) return builder.locations;
|
||||||
|
|
||||||
var imports = std.ArrayListUnmanaged(*DocumentStore.Handle){};
|
var imports = std.ArrayListUnmanaged(*const DocumentStore.Handle){};
|
||||||
|
|
||||||
var handle_it = store.handles.iterator();
|
for (store.handles.values()) |*handle| {
|
||||||
while (handle_it.next()) |entry| {
|
if (skip_std_references and std.mem.indexOf(u8, handle.uri, "std") != null) {
|
||||||
if (skip_std_references and std.mem.indexOf(u8, entry.key_ptr.*, "std") != null) {
|
if (!include_decl or !std.mem.eql(u8, handle.uri, curr_handle.uri))
|
||||||
if (!include_decl or entry.value_ptr.* != curr_handle)
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check entry's transitive imports
|
// Check entry's transitive imports
|
||||||
try imports.append(arena.allocator(), entry.value_ptr.*);
|
try imports.append(arena.allocator(), handle);
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
blk: while (i < imports.items.len) : (i += 1) {
|
blk: while (i < imports.items.len) : (i += 1) {
|
||||||
const import = imports.items[i];
|
const import = imports.items[i];
|
||||||
for (import.imports_used.items) |uri| {
|
// TODO handle cimports
|
||||||
|
for (import.import_uris.items) |uri| {
|
||||||
const h = store.getHandle(uri) orelse break;
|
const h = store.getHandle(uri) orelse break;
|
||||||
|
|
||||||
if (h == curr_handle) {
|
if (h == curr_handle) {
|
||||||
// entry does import curr_handle
|
// entry does import curr_handle
|
||||||
try symbolReferencesInternal(&builder, 0, entry.value_ptr.*);
|
try symbolReferencesInternal(&builder, 0, handle);
|
||||||
break :blk;
|
break :blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user