@import and @embedFile completions!
This commit is contained in:
parent
bb89c3518b
commit
43c61b3da6
@ -1398,6 +1398,8 @@ pub const SourceRange = std.zig.Token.Loc;
|
|||||||
pub const PositionContext = union(enum) {
|
pub const PositionContext = union(enum) {
|
||||||
builtin: SourceRange,
|
builtin: SourceRange,
|
||||||
comment,
|
comment,
|
||||||
|
import_string_literal: SourceRange,
|
||||||
|
embedfile_string_literal: SourceRange,
|
||||||
string_literal: SourceRange,
|
string_literal: SourceRange,
|
||||||
field_access: SourceRange,
|
field_access: SourceRange,
|
||||||
var_access: SourceRange,
|
var_access: SourceRange,
|
||||||
@ -1412,6 +1414,8 @@ pub const PositionContext = union(enum) {
|
|||||||
return switch (self) {
|
return switch (self) {
|
||||||
.builtin => |r| r,
|
.builtin => |r| r,
|
||||||
.comment => null,
|
.comment => null,
|
||||||
|
.import_string_literal => |r| r,
|
||||||
|
.embedfile_string_literal => |r| r,
|
||||||
.string_literal => |r| r,
|
.string_literal => |r| r,
|
||||||
.field_access => |r| r,
|
.field_access => |r| r,
|
||||||
.var_access => |r| r,
|
.var_access => |r| r,
|
||||||
@ -1485,7 +1489,27 @@ pub fn documentPositionContext(arena: *std.heap.ArenaAllocator, document: types.
|
|||||||
// State changes
|
// State changes
|
||||||
var curr_ctx = try peek(&stack);
|
var curr_ctx = try peek(&stack);
|
||||||
switch (tok.tag) {
|
switch (tok.tag) {
|
||||||
.string_literal, .multiline_string_literal_line => curr_ctx.ctx = .{ .string_literal = tok.loc },
|
.string_literal, .multiline_string_literal_line => string_lit_block: {
|
||||||
|
if (curr_ctx.stack_id == .Paren and stack.items.len >= 2) {
|
||||||
|
const perhaps_builtin = stack.items[stack.items.len - 2];
|
||||||
|
|
||||||
|
switch (perhaps_builtin.ctx) {
|
||||||
|
.builtin => |loc| {
|
||||||
|
const builtin_name = tokenizer.buffer[loc.start..loc.end];
|
||||||
|
if (std.mem.eql(u8, builtin_name, "@import")) {
|
||||||
|
curr_ctx.ctx = .{ .import_string_literal = tok.loc };
|
||||||
|
break :string_lit_block;
|
||||||
|
}
|
||||||
|
if (std.mem.eql(u8, builtin_name, "@embedFile")) {
|
||||||
|
curr_ctx.ctx = .{ .embedfile_string_literal = tok.loc };
|
||||||
|
break :string_lit_block;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
curr_ctx.ctx = .{ .string_literal = tok.loc };
|
||||||
|
},
|
||||||
.identifier => switch (curr_ctx.ctx) {
|
.identifier => switch (curr_ctx.ctx) {
|
||||||
.empty, .pre_label => curr_ctx.ctx = .{ .var_access = tok.loc },
|
.empty, .pre_label => curr_ctx.ctx = .{ .var_access = tok.loc },
|
||||||
.label => |filled| if (!filled) {
|
.label => |filled| if (!filled) {
|
||||||
|
70
src/main.zig
70
src/main.zig
@ -17,6 +17,7 @@ const shared = @import("./shared.zig");
|
|||||||
const Ast = std.zig.Ast;
|
const Ast = std.zig.Ast;
|
||||||
const known_folders = @import("known-folders");
|
const known_folders = @import("known-folders");
|
||||||
const tracy = @import("./tracy.zig");
|
const tracy = @import("./tracy.zig");
|
||||||
|
const uri_utils = @import("./uri.zig");
|
||||||
|
|
||||||
const data = switch (build_options.data_version) {
|
const data = switch (build_options.data_version) {
|
||||||
.master => @import("data/master.zig"),
|
.master => @import("data/master.zig"),
|
||||||
@ -1853,6 +1854,73 @@ fn completionHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req:
|
|||||||
.global_error_set => try completeError(arena, id, handle, config),
|
.global_error_set => try completeError(arena, id, handle, config),
|
||||||
.enum_literal => try completeDot(arena, id, handle, config),
|
.enum_literal => try completeDot(arena, id, handle, config),
|
||||||
.label => try completeLabel(arena, id, doc_position.absolute_index, handle, config),
|
.label => try completeLabel(arena, id, doc_position.absolute_index, handle, config),
|
||||||
|
.import_string_literal, .embedfile_string_literal => |loc| {
|
||||||
|
const line_mem_start = @ptrToInt(doc_position.line.ptr) - @ptrToInt(handle.document.mem.ptr);
|
||||||
|
const completing = handle.tree.source[line_mem_start + loc.start + 1 .. line_mem_start + loc.end];
|
||||||
|
|
||||||
|
var subpath_present = false;
|
||||||
|
var fsl_completions = std.ArrayList(types.CompletionItem).init(allocator);
|
||||||
|
|
||||||
|
fsc: {
|
||||||
|
var document_path = try uri_utils.parse(arena.allocator(), handle.uri());
|
||||||
|
var document_dir_path = std.fs.openDirAbsolute(std.fs.path.dirname(document_path) orelse break :fsc, .{ .iterate = true }) catch break :fsc;
|
||||||
|
defer document_dir_path.close();
|
||||||
|
|
||||||
|
if (std.mem.lastIndexOfScalar(u8, completing, '/')) |subpath_index| {
|
||||||
|
var subpath = completing[0..subpath_index];
|
||||||
|
|
||||||
|
if (std.mem.startsWith(u8, subpath, "./") and subpath_index > 2) {
|
||||||
|
subpath = completing[2..subpath_index];
|
||||||
|
} else if (std.mem.startsWith(u8, subpath, ".") and subpath_index > 1) {
|
||||||
|
subpath = completing[1..subpath_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
var old = document_dir_path;
|
||||||
|
document_dir_path = document_dir_path.openDir(subpath, .{ .iterate = true }) catch break :fsc // NOTE: Is this even safe lol?
|
||||||
|
old.close();
|
||||||
|
|
||||||
|
subpath_present = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dir_iterator = document_dir_path.iterate();
|
||||||
|
while (try dir_iterator.next()) |entry| {
|
||||||
|
if (std.mem.startsWith(u8, entry.name, ".")) continue;
|
||||||
|
if (entry.kind == .File and pos_context == .import_string_literal and !std.mem.endsWith(u8, entry.name, ".zig")) continue;
|
||||||
|
|
||||||
|
const l = try arena.allocator().dupe(u8, entry.name);
|
||||||
|
try fsl_completions.append(types.CompletionItem{
|
||||||
|
.label = l,
|
||||||
|
.insertText = l,
|
||||||
|
.kind = if (entry.kind == .File) .File else .Folder,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!subpath_present and pos_context == .import_string_literal) {
|
||||||
|
if (handle.associated_build_file) |bf| {
|
||||||
|
try fsl_completions.ensureUnusedCapacity(bf.packages.items.len);
|
||||||
|
|
||||||
|
for (bf.packages.items) |pkg| {
|
||||||
|
try fsl_completions.append(.{
|
||||||
|
.label = pkg.name,
|
||||||
|
.kind = .Module,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
truncateCompletions(fsl_completions.items, config.max_detail_length);
|
||||||
|
|
||||||
|
try send(arena, types.Response{
|
||||||
|
.id = id,
|
||||||
|
.result = .{
|
||||||
|
.CompletionList = .{
|
||||||
|
.isIncomplete = false,
|
||||||
|
.items = fsl_completions.items,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
else => try respondGeneric(id, no_completions_response),
|
else => try respondGeneric(id, no_completions_response),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1910,7 +1978,7 @@ fn gotoHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: reques
|
|||||||
switch (pos_context) {
|
switch (pos_context) {
|
||||||
.var_access => try gotoDefinitionGlobal(arena, id, doc_position.absolute_index, handle, config, resolve_alias),
|
.var_access => try gotoDefinitionGlobal(arena, id, doc_position.absolute_index, handle, config, resolve_alias),
|
||||||
.field_access => |range| try gotoDefinitionFieldAccess(arena, id, handle, doc_position, range, config, resolve_alias),
|
.field_access => |range| try gotoDefinitionFieldAccess(arena, id, handle, doc_position, range, config, resolve_alias),
|
||||||
.string_literal => try gotoDefinitionString(arena, id, doc_position.absolute_index, handle, config),
|
.import_string_literal => try gotoDefinitionString(arena, id, doc_position.absolute_index, handle, config),
|
||||||
.label => try gotoDefinitionLabel(arena, id, doc_position.absolute_index, handle, config),
|
.label => try gotoDefinitionLabel(arena, id, doc_position.absolute_index, handle, config),
|
||||||
else => try respondGeneric(id, null_result_response),
|
else => try respondGeneric(id, null_result_response),
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user