Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions src/features/folding_range.zig
Original file line number Diff line number Diff line change
Expand Up @@ -184,37 +184,46 @@ pub fn generateFoldingRanges(allocator: std.mem.Allocator, tree: *const Ast, enc
// TODO add folding range normal comments

// Folding range for top level imports
if (tree.mode == .zig) {
if (tree.mode == .zig) blk: {
var start_import: ?Ast.Node.Index = null;
var end_import: ?Ast.Node.Index = null;
var import_count: usize = 0;

const root_decls = tree.rootDecls();
for (root_decls) |node| {
const is_import = blk: {
if (tree.nodeTag(node) != .simple_var_decl) break :blk false;
const is_import = is_import: {
if (tree.nodeTag(node) != .simple_var_decl) break :is_import false;
const var_decl = tree.simpleVarDecl(node);
const init_node = var_decl.ast.init_node.unwrap() orelse break :blk false;
const init_node = var_decl.ast.init_node.unwrap() orelse break :is_import false;

break :blk isImportOrAlias(tree, init_node);
break :is_import isImportOrAlias(tree, init_node);
};

if (is_import) {
if (start_import == null) {
start_import = node;
}
end_import = node;
} else if (start_import != null and end_import != null) {
// We found a non-import after a sequence of imports, create folding range
try builder.add(.imports, tree.firstToken(start_import.?), ast.lastToken(tree, end_import.?), .inclusive, .inclusive);
import_count += 1;
continue;
}
defer {
start_import = null;
end_import = null;
import_count = 0;
}

const start = start_import orelse continue;
const end = end_import orelse continue;
if (import_count < 3) continue;
try builder.add(.imports, tree.firstToken(start), ast.lastToken(tree, end) + 1, .inclusive, .inclusive);
}

// Handle the case where imports continue to the end of the file
if (start_import != null and end_import != null and start_import.? != end_import.?) {
try builder.add(.imports, tree.firstToken(start_import.?), ast.lastToken(tree, end_import.?), .inclusive, .inclusive);
}
const start = start_import orelse break :blk;
const end = end_import orelse break :blk;
if (import_count < 3) break :blk;
try builder.add(.imports, tree.firstToken(start), ast.lastToken(tree, end) + 1, .inclusive, .inclusive);
}

for (0..tree.nodes.len) |i| {
Expand Down
41 changes: 25 additions & 16 deletions tests/lsp_features/folding_range.zig
Original file line number Diff line number Diff line change
Expand Up @@ -424,62 +424,71 @@ test "imports" {
try testFoldingRange(
\\const std = @import("std");
\\const builtin = @import("builtin");
\\const root = @import("root");
, &.{
.{
.startLine = 0,
.startCharacter = 0,
.endLine = 1,
.endCharacter = 34,
.endLine = 2,
.endCharacter = 29,
.kind = .imports,
.collapsedText = "@import(...)",
},
});
}

test "imports with aliases" {
try testFoldingRange(
\\const std = @import("std");
\\const builtin = @import("builtin");
\\const lsp = @import("lsp");
\\const types = lsp.types;
\\const foo = @import("foo");
\\const bar = foo.bar;
\\
\\pub fn main() void {}
, &.{
.{
.startLine = 0,
.startCharacter = 0,
.endLine = 3,
.endCharacter = 23,
.endCharacter = 20,
.kind = .imports,
.collapsedText = "@import(...)",
},
});
// Single import should not create folding range
}

test "imports exclude small count" {
try testFoldingRange(
\\const std = @import("std");
\\
\\pub fn main() void {}
\\const builtin = @import("builtin");
, &.{});
// Imports with gap in between should create separate folding ranges
}

test "imports with gap" {
try testFoldingRange(
\\const std = @import("std");
\\const builtin = @import("builtin");
\\const root = @import("root");
\\
\\pub const foo = 5;
\\
\\const lsp = @import("lsp");
\\const types = @import("types");
\\const foo = @import("foo");
\\const bar = @import("bar");
\\const baz = @import("baz");
, &.{
.{
.startLine = 0,
.startCharacter = 0,
.endLine = 1,
.endCharacter = 34,
.endLine = 2,
.endCharacter = 29,
.kind = .imports,
.collapsedText = "@import(...)",
},
.{
.startLine = 5,
.startLine = 6,
.startCharacter = 0,
.endLine = 6,
.endCharacter = 30,
.endLine = 8,
.endCharacter = 27,
.kind = .imports,
.collapsedText = "@import(...)",
},
Expand Down
Loading