Added label renaming
This commit is contained in:
parent
4952c34481
commit
beb900f1d9
@ -1218,7 +1218,7 @@ fn tokenRangeAppend(prev: SourceRange, token: std.zig.Token) SourceRange {
|
|||||||
|
|
||||||
pub fn documentPositionContext(allocator: *std.mem.Allocator, document: types.TextDocument, position: types.Position) !PositionContext {
|
pub fn documentPositionContext(allocator: *std.mem.Allocator, document: types.TextDocument, position: types.Position) !PositionContext {
|
||||||
const line = try document.getLine(@intCast(usize, position.line));
|
const line = try document.getLine(@intCast(usize, position.line));
|
||||||
const pos_char = @intCast(usize, position.character) + 1;
|
const pos_char = @intCast(usize, position.character);
|
||||||
const idx = if (pos_char > line.len) line.len else pos_char;
|
const idx = if (pos_char > line.len) line.len else pos_char;
|
||||||
|
|
||||||
var arena = std.heap.ArenaAllocator.init(allocator);
|
var arena = std.heap.ArenaAllocator.init(allocator);
|
||||||
|
87
src/main.zig
87
src/main.zig
@ -9,6 +9,10 @@ const data = @import("data/" ++ build_options.data_version ++ ".zig");
|
|||||||
const types = @import("types.zig");
|
const types = @import("types.zig");
|
||||||
const analysis = @import("analysis.zig");
|
const analysis = @import("analysis.zig");
|
||||||
const URI = @import("uri.zig");
|
const URI = @import("uri.zig");
|
||||||
|
const rename = @import("rename.zig");
|
||||||
|
|
||||||
|
// TODO Fix LSP -> byte and byte -> LSP offsets
|
||||||
|
// Implement clangd extension for utf8 offsets as well.
|
||||||
|
|
||||||
pub const log_level: std.log.Level = switch (std.builtin.mode) {
|
pub const log_level: std.log.Level = switch (std.builtin.mode) {
|
||||||
.Debug => .debug,
|
.Debug => .debug,
|
||||||
@ -35,9 +39,11 @@ pub fn log(
|
|||||||
};
|
};
|
||||||
send(types.Notification{
|
send(types.Notification{
|
||||||
.method = "window/showMessage",
|
.method = "window/showMessage",
|
||||||
.params = types.NotificationParams{ .ShowMessageParams = .{
|
.params = types.NotificationParams{
|
||||||
.type = message_type,
|
.ShowMessageParams = .{
|
||||||
.message = message, },
|
.type = message_type,
|
||||||
|
.message = message,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}) catch |err| {
|
}) catch |err| {
|
||||||
std.debug.print("Failed to send show message notification (error: {}).", .{err});
|
std.debug.print("Failed to send show message notification (error: {}).", .{err});
|
||||||
@ -50,9 +56,11 @@ pub fn log(
|
|||||||
|
|
||||||
send(types.Notification{
|
send(types.Notification{
|
||||||
.method = "window/logMessage",
|
.method = "window/logMessage",
|
||||||
.params = types.NotificationParams{ .LogMessageParams = .{
|
.params = types.NotificationParams{
|
||||||
.type = message_type,
|
.LogMessageParams = .{
|
||||||
.message = message, },
|
.type = message_type,
|
||||||
|
.message = message,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}) catch |err| {
|
}) catch |err| {
|
||||||
std.debug.print("Failed to send show message notification (error: {}).", .{err});
|
std.debug.print("Failed to send show message notification (error: {}).", .{err});
|
||||||
@ -78,7 +86,7 @@ const ClientCapabilities = struct {
|
|||||||
var client_capabilities = ClientCapabilities{};
|
var client_capabilities = ClientCapabilities{};
|
||||||
|
|
||||||
const initialize_response =
|
const initialize_response =
|
||||||
\\,"result": {"capabilities": {"signatureHelpProvider": {"triggerCharacters": ["(",","]},"textDocumentSync": 1,"completionProvider": {"resolveProvider": false,"triggerCharacters": [".",":","@"]},"documentHighlightProvider": false,"hoverProvider": true,"codeActionProvider": false,"declarationProvider": true,"definitionProvider": true,"typeDefinitionProvider": true,"implementationProvider": false,"referencesProvider": false,"documentSymbolProvider": true,"colorProvider": false,"documentFormattingProvider": true,"documentRangeFormattingProvider": false,"foldingRangeProvider": false,"selectionRangeProvider": false,"workspaceSymbolProvider": false,"rangeProvider": false,"documentProvider": true,"workspace": {"workspaceFolders": {"supported": true,"changeNotifications": true}},"semanticTokensProvider": {"documentProvider": true,"legend": {"tokenTypes": ["type","struct","enum","union","parameter","variable","tagField","field","errorTag","function","keyword","comment","string","number","operator","builtin","label"],"tokenModifiers": ["definition","async","documentation", "generic"]}}}}}
|
\\,"result": {"capabilities": {"signatureHelpProvider": {"triggerCharacters": ["(",","]},"textDocumentSync": 1,"renameProvider":true,"completionProvider": {"resolveProvider": false,"triggerCharacters": [".",":","@"]},"documentHighlightProvider": false,"hoverProvider": true,"codeActionProvider": false,"declarationProvider": true,"definitionProvider": true,"typeDefinitionProvider": true,"implementationProvider": false,"referencesProvider": false,"documentSymbolProvider": true,"colorProvider": false,"documentFormattingProvider": true,"documentRangeFormattingProvider": false,"foldingRangeProvider": false,"selectionRangeProvider": false,"workspaceSymbolProvider": false,"rangeProvider": false,"documentProvider": true,"workspace": {"workspaceFolders": {"supported": true,"changeNotifications": true}},"semanticTokensProvider": {"documentProvider": true,"legend": {"tokenTypes": ["type","struct","enum","union","parameter","variable","tagField","field","errorTag","function","keyword","comment","string","number","operator","builtin","label"],"tokenModifiers": ["definition","async","documentation", "generic"]}}}}}
|
||||||
;
|
;
|
||||||
|
|
||||||
const not_implemented_response =
|
const not_implemented_response =
|
||||||
@ -110,7 +118,7 @@ fn send(reqOrRes: var) !void {
|
|||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
|
|
||||||
var arr = std.ArrayList(u8).init(&arena.allocator);
|
var arr = std.ArrayList(u8).init(&arena.allocator);
|
||||||
try std.json.stringify(reqOrRes, .{}, arr.outStream());
|
try std.json.stringify(reqOrRes, .{}, arr.writer());
|
||||||
|
|
||||||
const stdout_stream = stdout.outStream();
|
const stdout_stream = stdout.outStream();
|
||||||
try stdout_stream.print("Content-Length: {}\r\n\r\n", .{arr.items.len});
|
try stdout_stream.print("Content-Length: {}\r\n\r\n", .{arr.items.len});
|
||||||
@ -709,6 +717,32 @@ fn gotoDefinitionString(id: types.RequestId, pos_index: usize, handle: *Document
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn renameDefinitionGlobal(id: types.RequestId, handle: *DocumentStore.Handle, pos_index: usize, new_name: []const u8) !void {
|
||||||
|
// @TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn renameDefinitionFieldAccess(id: types.RequestId, handle: *DocumentStore.Handle, position: types.Position, new_name: []const u8) !void {
|
||||||
|
// @TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn renameDefinitionLabel(id: types.RequestId, handle: *DocumentStore.Handle, pos_index: usize, new_name: []const u8) !void {
|
||||||
|
// @TODO
|
||||||
|
var arena = std.heap.ArenaAllocator.init(allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
|
||||||
|
const decl = (try getLabelGlobal(pos_index, handle)) orelse return try respondGeneric(id, null_result_response);
|
||||||
|
|
||||||
|
var workspace_edit = types.WorkspaceEdit{
|
||||||
|
.changes = std.StringHashMap([]types.TextEdit).init(&arena.allocator),
|
||||||
|
};
|
||||||
|
try rename.renameLabel(&arena, decl, new_name, &workspace_edit.changes.?);
|
||||||
|
|
||||||
|
try send(types.Response{
|
||||||
|
.id = id,
|
||||||
|
.result = .{ .WorkspaceEdit = workspace_edit },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const DeclToCompletionContext = struct {
|
const DeclToCompletionContext = struct {
|
||||||
completions: *std.ArrayList(types.CompletionItem),
|
completions: *std.ArrayList(types.CompletionItem),
|
||||||
config: *const Config,
|
config: *const Config,
|
||||||
@ -1140,7 +1174,7 @@ fn processJsonRpc(parser: *std.json.Parser, json: []const u8, config: Config, ke
|
|||||||
|
|
||||||
const pos = types.Position{
|
const pos = types.Position{
|
||||||
.line = position.getValue("line").?.Integer,
|
.line = position.getValue("line").?.Integer,
|
||||||
.character = position.getValue("character").?.Integer - 1,
|
.character = position.getValue("character").?.Integer,
|
||||||
};
|
};
|
||||||
if (pos.character >= 0) {
|
if (pos.character >= 0) {
|
||||||
const pos_index = try handle.document.positionToIndex(pos);
|
const pos_index = try handle.document.positionToIndex(pos);
|
||||||
@ -1206,7 +1240,7 @@ fn processJsonRpc(parser: *std.json.Parser, json: []const u8, config: Config, ke
|
|||||||
|
|
||||||
const pos = types.Position{
|
const pos = types.Position{
|
||||||
.line = position.getValue("line").?.Integer,
|
.line = position.getValue("line").?.Integer,
|
||||||
.character = position.getValue("character").?.Integer - 1,
|
.character = position.getValue("character").?.Integer,
|
||||||
};
|
};
|
||||||
if (pos.character >= 0) {
|
if (pos.character >= 0) {
|
||||||
const resolve_alias = !std.mem.eql(u8, method, "textDocument/declaration");
|
const resolve_alias = !std.mem.eql(u8, method, "textDocument/declaration");
|
||||||
@ -1236,7 +1270,7 @@ fn processJsonRpc(parser: *std.json.Parser, json: []const u8, config: Config, ke
|
|||||||
|
|
||||||
const pos = types.Position{
|
const pos = types.Position{
|
||||||
.line = position.getValue("line").?.Integer,
|
.line = position.getValue("line").?.Integer,
|
||||||
.character = position.getValue("character").?.Integer - 1,
|
.character = position.getValue("character").?.Integer,
|
||||||
};
|
};
|
||||||
if (pos.character >= 0) {
|
if (pos.character >= 0) {
|
||||||
const pos_index = try handle.document.positionToIndex(pos);
|
const pos_index = try handle.document.positionToIndex(pos);
|
||||||
@ -1307,6 +1341,36 @@ fn processJsonRpc(parser: *std.json.Parser, json: []const u8, config: Config, ke
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return try respondGeneric(id, null_result_response);
|
return try respondGeneric(id, null_result_response);
|
||||||
|
} else if (std.mem.eql(u8, method, "textDocument/rename")) {
|
||||||
|
const params = root.Object.getValue("params").?.Object;
|
||||||
|
const document = params.getValue("textDocument").?.Object;
|
||||||
|
const uri = document.getValue("uri").?.String;
|
||||||
|
const position = params.getValue("position").?.Object;
|
||||||
|
|
||||||
|
const handle = document_store.getHandle(uri) orelse {
|
||||||
|
std.log.debug(.main, "Trying to got to definition in non existent document {}", .{uri});
|
||||||
|
return try respondGeneric(id, null_result_response);
|
||||||
|
};
|
||||||
|
|
||||||
|
// @TODO
|
||||||
|
const pos = types.Position{
|
||||||
|
.line = position.getValue("line").?.Integer,
|
||||||
|
.character = position.getValue("character").?.Integer,
|
||||||
|
};
|
||||||
|
if (pos.character >= 0) {
|
||||||
|
const new_name = params.getValue("newName").?.String;
|
||||||
|
const pos_index = try handle.document.positionToIndex(pos);
|
||||||
|
const pos_context = try analysis.documentPositionContext(allocator, handle.document, pos);
|
||||||
|
|
||||||
|
switch (pos_context) {
|
||||||
|
.var_access => try renameDefinitionGlobal(id, handle, pos_index, new_name),
|
||||||
|
.field_access => try renameDefinitionFieldAccess(id, handle, pos, new_name),
|
||||||
|
.label => try renameDefinitionLabel(id, handle, pos_index, new_name),
|
||||||
|
else => try respondGeneric(id, null_result_response),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try respondGeneric(id, null_result_response);
|
||||||
|
}
|
||||||
} else if (std.mem.eql(u8, method, "textDocument/references") or
|
} else if (std.mem.eql(u8, method, "textDocument/references") or
|
||||||
std.mem.eql(u8, method, "textDocument/documentHighlight") or
|
std.mem.eql(u8, method, "textDocument/documentHighlight") or
|
||||||
std.mem.eql(u8, method, "textDocument/codeAction") or
|
std.mem.eql(u8, method, "textDocument/codeAction") or
|
||||||
@ -1314,7 +1378,6 @@ fn processJsonRpc(parser: *std.json.Parser, json: []const u8, config: Config, ke
|
|||||||
std.mem.eql(u8, method, "textDocument/documentLink") or
|
std.mem.eql(u8, method, "textDocument/documentLink") or
|
||||||
std.mem.eql(u8, method, "textDocument/rangeFormatting") or
|
std.mem.eql(u8, method, "textDocument/rangeFormatting") or
|
||||||
std.mem.eql(u8, method, "textDocument/onTypeFormatting") or
|
std.mem.eql(u8, method, "textDocument/onTypeFormatting") or
|
||||||
std.mem.eql(u8, method, "textDocument/rename") or
|
|
||||||
std.mem.eql(u8, method, "textDocument/prepareRename") or
|
std.mem.eql(u8, method, "textDocument/prepareRename") or
|
||||||
std.mem.eql(u8, method, "textDocument/foldingRange") or
|
std.mem.eql(u8, method, "textDocument/foldingRange") or
|
||||||
std.mem.eql(u8, method, "textDocument/selectionRange"))
|
std.mem.eql(u8, method, "textDocument/selectionRange"))
|
||||||
|
@ -61,6 +61,7 @@ pub const ResponseParams = union(enum) {
|
|||||||
DocumentSymbols: []DocumentSymbol,
|
DocumentSymbols: []DocumentSymbol,
|
||||||
SemanticTokens: struct { data: []const u32 },
|
SemanticTokens: struct { data: []const u32 },
|
||||||
TextEdits: []TextEdit,
|
TextEdits: []TextEdit,
|
||||||
|
WorkspaceEdit: WorkspaceEdit,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// JSONRPC error
|
/// JSONRPC error
|
||||||
@ -201,6 +202,33 @@ pub const TextDocument = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const WorkspaceEdit = struct {
|
||||||
|
changes: ?std.StringHashMap([]TextEdit),
|
||||||
|
|
||||||
|
pub fn jsonStringify(
|
||||||
|
self: WorkspaceEdit,
|
||||||
|
options: std.json.StringifyOptions,
|
||||||
|
writer: var,
|
||||||
|
) @TypeOf(writer).Error!void {
|
||||||
|
try writer.writeByte('{');
|
||||||
|
if (self.changes) |changes| {
|
||||||
|
try writer.writeAll("\"changes\": {");
|
||||||
|
var it = changes.iterator();
|
||||||
|
var idx: usize = 0;
|
||||||
|
while (it.next()) |entry| : (idx += 1) {
|
||||||
|
if (idx != 0) try writer.writeAll(", ");
|
||||||
|
|
||||||
|
try writer.writeByte('"');
|
||||||
|
try writer.writeAll(entry.key);
|
||||||
|
try writer.writeAll("\":");
|
||||||
|
try std.json.stringify(entry.value, options, writer);
|
||||||
|
}
|
||||||
|
try writer.writeByte('}');
|
||||||
|
}
|
||||||
|
try writer.writeByte('}');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub const TextEdit = struct {
|
pub const TextEdit = struct {
|
||||||
range: Range,
|
range: Range,
|
||||||
newText: String,
|
newText: String,
|
||||||
|
Loading…
Reference in New Issue
Block a user