From a8c81522cdf150b2f29c1c5bb5025259169e8a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fn=20=E2=8C=83=20=E2=8C=A5?= <70830482+FnControlOption@users.noreply.github.com> Date: Sat, 24 Jun 2023 09:00:12 -0700 Subject: [PATCH 1/2] Resolve type of simple labeled block --- src/analysis.zig | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/analysis.zig b/src/analysis.zig index f63861d..b0423fd 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -1140,6 +1140,33 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, node_handle: NodeWithHandle) e .handle = handle, }; }, + .block, + .block_semicolon, + .block_two, + .block_two_semicolon, + => { + const first_token = tree.firstToken(node); + if (token_tags[first_token] != .identifier) return null; + + const block_label = tree.tokenSlice(first_token); + + var buffer: [2]Ast.Node.Index = undefined; + const statements = ast.blockStatements(tree, node, &buffer).?; + + for (statements) |child_idx| { + // TODO: Recursively find matching `break :label` (e.g. inside `if`) + if (node_tags[child_idx] == .@"break") { + if (datas[child_idx].lhs == 0) continue; + if (datas[child_idx].rhs == 0) continue; + + const break_label = tree.tokenSlice(datas[child_idx].lhs); + if (!std.mem.eql(u8, block_label, break_label)) continue; + + const operand = .{ .node = datas[child_idx].rhs, .handle = handle }; + return try analyser.resolveTypeOfNodeInternal(operand); + } + } + }, else => {}, } return null; From 0baae921edb1c5b52feebb4cdd0906138264c74c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fn=20=E2=8C=83=20=E2=8C=A5?= <70830482+FnControlOption@users.noreply.github.com> Date: Sat, 24 Jun 2023 10:14:58 -0700 Subject: [PATCH 2/2] Add completion test --- tests/lsp_features/completion.zig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/lsp_features/completion.zig b/tests/lsp_features/completion.zig index 2dc25af..77d2164 100644 --- a/tests/lsp_features/completion.zig +++ b/tests/lsp_features/completion.zig @@ -509,6 +509,17 @@ test "completion - block" { , &.{ .{ .label = "blk", .kind = .Text }, // idk what kind this should be }); + + try testCompletion( + \\const S = struct { alpha: u32 }; + \\const foo: S = undefined; + \\const bar = blk: { + \\ break :blk foo; + \\}; + \\const baz = bar. + , &.{ + .{ .label = "alpha", .kind = .Field, .detail = "alpha: u32" }, + }); } fn testCompletion(source: []const u8, expected_completions: []const Completion) !void {