From 1df42d8a8aa47d569c1162f63f5cc37eee7ce113 Mon Sep 17 00:00:00 2001 From: Harsh Kapse Date: Mon, 7 Sep 2026 19:10:18 +0530 Subject: [PATCH 1/3] refactor(treesitter): replace gotreesitter with native cgo flat-buffer bridge - Wire Cgo flat-buffer bridge ([]FlatNode) and parse-phase RAII (IngestFlatAST) - Add zero-allocation language detection in detect.go - Update grammar rule definitions to match native Tree-sitter symbols - Extract comments directly from flat CST nodes in internal/comments - Wire native flat-buffer bridge directly into parser and pipeline --- internal/comments/comments_test.go | 374 ++++++++++++++++-- internal/comments/diff.go | 142 +++++-- internal/comments/extract.go | 279 ++++++++++--- internal/inline/render.go | 8 +- internal/pipeline/pipeline.go | 106 +++-- internal/pipeline/pipeline_test.go | 49 +++ internal/serialize/json.go | 1 + internal/treesitter/ast.go | 105 ----- internal/treesitter/bridge_cgo.go | 224 +++++++++++ internal/treesitter/bridge_ingest.go | 123 ++++++ internal/treesitter/bridge_test.go | 125 ++++++ internal/treesitter/detect.go | 106 +++++ internal/treesitter/detect_test.go | 51 +++ internal/treesitter/flat_node.go | 23 ++ internal/treesitter/parser.go | 39 +- internal/treesitter/parser_test.go | 7 +- internal/treesitter/rules/c.go | 20 +- internal/treesitter/rules/cpp.go | 34 +- internal/treesitter/rules/css.go | 1 + internal/treesitter/rules/go.go | 43 +- internal/treesitter/rules/html.go | 1 + internal/treesitter/rules/java.go | 34 +- internal/treesitter/rules/javascript.go | 25 +- internal/treesitter/rules/json.go | 5 + internal/treesitter/rules/lua.go | 14 +- internal/treesitter/rules/php.go | 29 ++ internal/treesitter/rules/python.go | 24 +- internal/treesitter/rules/ruby.go | 25 +- internal/treesitter/rules/rules.go | 288 ++++++++++++-- .../treesitter/rules/rules_grammar_test.go | 103 ++--- internal/treesitter/rules/rules_test.go | 84 +++- internal/treesitter/rules/rust.go | 39 ++ internal/treesitter/rules/toml.go | 5 + internal/treesitter/rules/tsx.go | 56 ++- internal/treesitter/rules/typescript.go | 56 ++- internal/treesitter/rules/yaml.go | 3 + internal/treesitter/rules/zig.go | 26 ++ internal/treesitter/rules_symbol_test.go | 22 +- internal/tui/syntax.go | 63 +-- internal/tui/syntax_test.go | 19 +- .../expected_actions.json.gz | Bin 637 -> 639 bytes .../expected_ui.json.gz | Bin 3733 -> 3732 bytes .../expected_actions.json.gz | Bin 716 -> 684 bytes .../expected_ui.json.gz | Bin 472 -> 487 bytes .../cpp_simdjson_key/expected_actions.json.gz | Bin 329 -> 472 bytes .../cpp_simdjson_key/expected_ui.json.gz | Bin 486 -> 515 bytes .../expected_actions.json.gz | Bin 561 -> 574 bytes .../go_gin_fix_compile/expected_ui.json.gz | Bin 376 -> 381 bytes .../expected_actions.json.gz | Bin 591 -> 537 bytes .../go_gin_fix_corrupted/expected_ui.json.gz | Bin 564 -> 546 bytes .../expected_actions.json.gz | Bin 628 -> 627 bytes .../go_gin_fix_lint/expected_actions.json.gz | Bin 1250 -> 1242 bytes .../go_gin_fix_lint/expected_ui.json.gz | Bin 5001 -> 4967 bytes .../expected_actions.json.gz | Bin 700 -> 674 bytes .../go_gin_fixes_http/expected_ui.json.gz | Bin 2440 -> 2426 bytes .../expected_actions.json.gz | Bin 442 -> 442 bytes .../go_gin_use_t/expected_actions.json.gz | Bin 537 -> 539 bytes .../expected_actions.json.gz | Bin 1519 -> 1510 bytes .../expected_ui.json.gz | Bin 1547 -> 1545 bytes .../expected_actions.json.gz | Bin 373 -> 386 bytes .../expected_ui.json.gz | Bin 11606 -> 11616 bytes .../expected_actions.json.gz | Bin 855 -> 869 bytes .../expected_ui.json.gz | Bin 23487 -> 23489 bytes .../expected_actions.json.gz | Bin 329 -> 346 bytes .../expected_ui.json.gz | Bin 4074 -> 4080 bytes .../expected_actions.json.gz | Bin 416 -> 435 bytes .../expected_ui.json.gz | Bin 12718 -> 12736 bytes .../expected_actions.json.gz | Bin 1009 -> 1023 bytes .../expected_ui.json.gz | Bin 10528 -> 10535 bytes .../expected_actions.json.gz | Bin 1158 -> 1148 bytes .../expected_ui.json.gz | Bin 1870 -> 1875 bytes .../expected_actions.json.gz | Bin 512 -> 312 bytes .../expected_ui.json.gz | Bin 4715 -> 4717 bytes .../expected_actions.json.gz | Bin 392 -> 223 bytes .../expected_ui.json.gz | Bin 4678 -> 4717 bytes .../expected_actions.json.gz | Bin 442 -> 450 bytes .../expected_actions.json.gz | Bin 458 -> 445 bytes .../expected_ui.json.gz | Bin 6191 -> 6202 bytes .../expected_actions.json.gz | Bin 576 -> 618 bytes .../py_requests_make_json/expected_ui.json.gz | Bin 1056 -> 1113 bytes .../expected_actions.json.gz | Bin 465 -> 393 bytes .../py_requests_only_use/expected_ui.json.gz | Bin 5758 -> 5737 bytes .../expected_actions.json.gz | Bin 338 -> 348 bytes .../expected_actions.json.gz | Bin 568 -> 599 bytes .../expected_ui.json.gz | Bin 5753 -> 5777 bytes .../expected_actions.json.gz | Bin 572 -> 507 bytes .../expected_ui.json.gz | Bin 11430 -> 11391 bytes .../expected_actions.json.gz | Bin 1350 -> 1349 bytes .../expected_ui.json.gz | Bin 11072 -> 11086 bytes .../expected_actions.json.gz | Bin 506 -> 536 bytes .../expected_ui.json.gz | Bin 2118 -> 2130 bytes .../expected_actions.json.gz | Bin 400 -> 395 bytes .../expected_actions.json.gz | Bin 1324 -> 1249 bytes .../expected_ui.json.gz | Bin 1966 -> 1974 bytes .../expected_actions.json.gz | Bin 405 -> 431 bytes .../expected_ui.json.gz | Bin 1290 -> 1296 bytes .../expected_actions.json.gz | Bin 465 -> 480 bytes .../expected_ui.json.gz | Bin 1244 -> 1252 bytes .../expected_actions.json.gz | Bin 583 -> 386 bytes .../expected_ui.json.gz | Bin 1545 -> 1519 bytes tests/testdata/ts_zod_improve_mini/new.ts | 12 +- tests/testdata/ts_zod_improve_mini/old.ts | 12 +- .../expected_actions.json.gz | Bin 207 -> 209 bytes .../expected_ui.json.gz | Bin 1126 -> 1130 bytes .../new.yaml | 51 +-- .../old.yaml | 51 +-- .../expected_actions.json.gz | Bin 496 -> 498 bytes .../expected_actions.json.gz | Bin 724 -> 609 bytes .../expected_ui.json.gz | Bin 391 -> 420 bytes .../expected_actions.json.gz | Bin 1247 -> 1173 bytes .../expected_ui.json.gz | Bin 969 -> 1004 bytes .../expected_actions.json.gz | Bin 1754 -> 1771 bytes .../zig_clap_more_than_2/expected_ui.json.gz | Bin 11941 -> 11941 bytes .../expected_actions.json.gz | Bin 1155 -> 1155 bytes .../expected_actions.json.gz | Bin 572 -> 568 bytes .../expected_actions.json.gz | Bin 269 -> 273 bytes .../expected_actions.json.gz | Bin 631 -> 607 bytes .../expected_ui.json.gz | Bin 2734 -> 2705 bytes 118 files changed, 2338 insertions(+), 569 deletions(-) create mode 100644 internal/pipeline/pipeline_test.go create mode 100644 internal/treesitter/bridge_cgo.go create mode 100644 internal/treesitter/bridge_ingest.go create mode 100644 internal/treesitter/bridge_test.go create mode 100644 internal/treesitter/detect.go create mode 100644 internal/treesitter/detect_test.go create mode 100644 internal/treesitter/flat_node.go diff --git a/internal/comments/comments_test.go b/internal/comments/comments_test.go index de409904..49d4d184 100644 --- a/internal/comments/comments_test.go +++ b/internal/comments/comments_test.go @@ -2,13 +2,11 @@ package comments import ( "os" - "strings" "testing" "github.com/HarshK97/diffmantic/internal/actions" + "github.com/HarshK97/diffmantic/internal/engine" "github.com/HarshK97/diffmantic/internal/treesitter" - "github.com/HarshK97/diffmantic/internal/treesitter/rules" - "github.com/odvcencio/gotreesitter" ) func TestDiffCommentsIdentical(t *testing.T) { @@ -19,7 +17,7 @@ func TestDiffCommentsIdentical(t *testing.T) { {Type: "comment", Text: "// Hello World", StartRow: 8, StartByte: 15, EndByte: 29}, } - res := DiffComments(srcComments, dstComments) + res := DiffComments(srcComments, dstComments, nil) if len(res.Actions) != 0 { t.Errorf("expected 0 actions for identical comment, got %d actions", len(res.Actions)) } @@ -33,7 +31,7 @@ func TestDiffCommentsSingleLineUpdate(t *testing.T) { {Type: "comment", Text: "// New Comment", StartRow: 5, StartByte: 10, EndByte: 24}, } - res := DiffComments(srcComments, dstComments) + res := DiffComments(srcComments, dstComments, nil) if len(res.Actions) != 1 { t.Fatalf("expected 1 action, got %d", len(res.Actions)) } @@ -57,7 +55,7 @@ func TestDiffCommentsMultiLineLineDiff(t *testing.T) { {Type: "block_comment", Text: newJavadoc, StartRow: 10, StartByte: 0, EndByte: uint32(len(newJavadoc))}, } - res := DiffComments(srcComments, dstComments) + res := DiffComments(srcComments, dstComments, nil) if len(res.Actions) != 1 { t.Fatalf("expected 1 line-level update action in multiline comment, got %d", len(res.Actions)) @@ -75,29 +73,29 @@ func TestDiffCommentsMultiLineLineDiff(t *testing.T) { } func TestExtractCommentsWithTreeSitter(t *testing.T) { - lang, err := treesitter.DetectLanguage("test.go") - if err != nil { - t.Fatal(err) - } - rules := rules.Get("go") src := []byte("package main\n\n// Line comment 1\nfunc main() {\n\t// Line comment 2\n}\n") - parser := gotreesitter.NewParser(lang) - tree, err := parser.Parse(src) + _, flatNodes, symbols, err := treesitter.ParseForPipeline(src, "go") if err != nil { t.Fatal(err) } - comments := ExtractComments(tree.RootNode(), src, lang, rules) + comments := ExtractComments(flatNodes, symbols, src, "go") if len(comments) != 2 { t.Fatalf("expected 2 comments extracted, got %d", len(comments)) } if comments[0].Text != "// Line comment 1" { t.Errorf("expected '// Line comment 1', got %q", comments[0].Text) } + if comments[0].Language != "go" { + t.Errorf("expected comments[0].Language == 'go', got %q", comments[0].Language) + } if comments[1].Text != "// Line comment 2" { t.Errorf("expected '// Line comment 2', got %q", comments[1].Text) } + if comments[1].Language != "go" { + t.Errorf("expected comments[1].Language == 'go', got %q", comments[1].Language) + } } func TestDiffCommentsScopeLocking(t *testing.T) { @@ -110,7 +108,7 @@ func TestDiffCommentsScopeLocking(t *testing.T) { {Type: "comment", Text: "// Method B comment", ScopeKey: "method:funcB", StartRow: 20}, } - res := DiffComments(srcComments, dstComments) + res := DiffComments(srcComments, dstComments, nil) if len(res.Actions) != 1 { t.Fatalf("expected 1 action, got %d", len(res.Actions)) } @@ -127,7 +125,7 @@ func TestDiffCommentsControlBranchScopeLocking(t *testing.T) { {Type: "comment", Text: "-- Track leading whitespace for level", ScopeKey: "function:foo/if_statement", StartRow: 45}, } - res := DiffComments(srcComments, dstComments) + res := DiffComments(srcComments, dstComments, nil) // Moving between branches should delete and insert instead of update in place. if len(res.Actions) != 2 { t.Fatalf("expected 2 actions (1 delete, 1 insert), got %d", len(res.Actions)) @@ -149,27 +147,38 @@ func TestDiffCommentsControlBranchScopeLocking(t *testing.T) { func TestDiffCommentsMovedScope(t *testing.T) { srcComments := []CommentBlock{ - {Type: "comment", Text: "// Optional params comment", ScopeKey: "method_declaration:getParamsToSign", StartRow: 162, EndRow: 162}, + {Type: "comment", Text: "// Optional params comment", ScopeKey: "method_declaration:getParamsToSign", StartRow: 162, EndRow: 162, Language: "go"}, } dstComments := []CommentBlock{ - {Type: "comment", Text: "// Optional params comment", ScopeKey: "method_declaration:getOauthParams", StartRow: 159, EndRow: 159}, + {Type: "comment", Text: "// Optional params comment", ScopeKey: "method_declaration:getOauthParams", StartRow: 159, EndRow: 159, Language: "go"}, } - res := DiffComments(srcComments, dstComments) - if len(res.Actions) != 1 { - t.Fatalf("expected 1 Move action for comment moved across scopes, got %d actions", len(res.Actions)) + res := DiffComments(srcComments, dstComments, nil) + if len(res.Actions) != 2 { + t.Fatalf("expected 2 actions (1 Delete, 1 Insert) for comment moved across scopes, got %d actions", len(res.Actions)) } - if res.Actions[0].Type != actions.Move { - t.Errorf("expected Move action, got %v", res.Actions[0].Type) + hasDelete := false + hasInsert := false + for _, act := range res.Actions { + if act.Type == actions.Move { + t.Errorf("expected no Move action for comment trivia, got actions.Move") + } + if act.Type == actions.Delete { + hasDelete = true + } + if act.Type == actions.Insert { + hasInsert = true + } + } + if !hasDelete || !hasInsert { + t.Errorf("expected 1 Delete and 1 Insert action, got: %+v", res.Actions) + } + if _, ok := res.LineMappings[162]; ok { + t.Errorf("expected cross-scope comment NOT to populate LineMappings, got %v", res.LineMappings) } } func TestDiffCommentsGuzzlePhp(t *testing.T) { - lang, err := treesitter.DetectLanguage("test.php") - if err != nil { - t.Fatal(err) - } - r := rules.Get("php") src, err := os.ReadFile("../../tests/testdata/php_guzzle_handler_curl_multi/old.php") if err != nil { t.Fatal(err) @@ -179,28 +188,115 @@ func TestDiffCommentsGuzzlePhp(t *testing.T) { t.Fatal(err) } - parser := gotreesitter.NewParser(lang) - treeA, err := parser.Parse(src) + _, flatNodesA, symbolsA, err := treesitter.ParseForPipeline(src, "php") if err != nil { t.Fatal(err) } - treeB, err := parser.Parse(dst) + _, flatNodesB, symbolsB, err := treesitter.ParseForPipeline(dst, "php") if err != nil { t.Fatal(err) } - srcComments := ExtractComments(treeA.RootNode(), src, lang, r) - dstComments := ExtractComments(treeB.RootNode(), dst, lang, r) + srcComments := ExtractComments(flatNodesA, symbolsA, src, "php") + dstComments := ExtractComments(flatNodesB, symbolsB, dst, "php") - res := DiffComments(srcComments, dstComments) + res := DiffComments(srcComments, dstComments, nil) moveCount := 0 for _, a := range res.Actions { - if a.Type == actions.Move && strings.Contains(a.Node.Label, "Optional parameters") { + if a.Type == actions.Move { moveCount++ } } - if moveCount != 1 { - t.Errorf("expected 1 Move action for Optional parameters comment, got %d", moveCount) + if moveCount != 0 { + t.Errorf("expected 0 Move actions for comment trivia in Guzzle PHP diff, got %d", moveCount) + } +} + +func TestSyntheticCommentNodeInvariants(t *testing.T) { + cb := CommentBlock{ + Type: "comment", + Text: "// Hello World", + StartByte: 10, + EndByte: 24, + StartRow: 2, + StartCol: 0, + EndRow: 2, + EndCol: 14, + ParentType: "function_declaration", + ParentStart: 0, + ParentEnd: 100, + ParentRow: 1, + ParentEndRow: 10, + Language: "go", + } + + node := createCommentNode(&cb, cb.Language) + if node == nil { + t.Fatal("expected non-nil ASTNode") + } + if node.Parent == nil { + t.Fatal("expected non-nil Parent") + } + if len(node.Parent.Children) != 1 || node.Parent.Children[0] != node { + t.Fatalf("expected Parent.Children to contain node, got %v", node.Parent.Children) + } + if idx := node.ChildIndex(); idx != 0 { + t.Errorf("expected ChildIndex() == 0, got %d", idx) + } + if lang := node.GetLanguage(); lang != "go" { + t.Errorf("expected GetLanguage() == %q, got %q", "go", lang) + } + + // Without parent + cbNoParent := CommentBlock{ + Type: "comment", + Text: "// Top-level comment", + StartByte: 0, + EndByte: 20, + Language: "go", + } + nodeNoParent := createCommentNode(&cbNoParent, cbNoParent.Language) + if nodeNoParent.Parent != nil { + t.Errorf("expected nil parent for top-level comment") + } + if idx := nodeNoParent.ChildIndex(); idx != -1 { + t.Errorf("expected ChildIndex() == -1 for parentless node, got %d", idx) + } +} + +func TestSyntheticCommentLineNodeInvariants(t *testing.T) { + cb := CommentBlock{ + Type: "block_comment", + Text: "/* line 1\n * line 2 */", + StartByte: 10, + EndByte: 40, + StartRow: 2, + StartCol: 0, + EndRow: 3, + EndCol: 11, + ParentType: "class_declaration", + ParentStart: 0, + ParentEnd: 200, + ParentRow: 1, + ParentEndRow: 20, + Language: "python", + } + + node := createCommentLineNode(&cb, " * line 2 */", 20, 32, 3, cb.Language) + if node == nil { + t.Fatal("expected non-nil ASTNode") + } + if node.Parent == nil { + t.Fatal("expected non-nil Parent") + } + if len(node.Parent.Children) != 1 || node.Parent.Children[0] != node { + t.Fatalf("expected Parent.Children to contain line node, got %v", node.Parent.Children) + } + if idx := node.ChildIndex(); idx != 0 { + t.Errorf("expected ChildIndex() == 0, got %d", idx) + } + if lang := node.GetLanguage(); lang != "python" { + t.Errorf("expected GetLanguage() == %q, got %q", "python", lang) } } @@ -217,7 +313,7 @@ func TestDiffCommentsScopedLCSNoCrossover(t *testing.T) { {Type: "comment", Text: "// step", ScopeKey: "func:doWork", StartRow: 32, EndRow: 32}, } - res := DiffComments(srcComments, dstComments) + res := DiffComments(srcComments, dstComments, nil) if len(res.Actions) != 0 { t.Fatalf("expected 0 actions for matched identical comments, got %d", len(res.Actions)) } @@ -225,3 +321,205 @@ func TestDiffCommentsScopedLCSNoCrossover(t *testing.T) { t.Errorf("expected mappings 10->12, 20->22, 30->32; got %v", res.LineMappings) } } + +func TestDiffCommentsRenamedFunction(t *testing.T) { + srcDecl := &treesitter.ASTNode{ID: 10, Type: "function_declaration", StartByte: 0, EndByte: 200} + dstDecl := &treesitter.ASTNode{ID: 25, Type: "function_declaration", StartByte: 0, EndByte: 200} + + mappings := engine.NewMapping() + mappings.Add(srcDecl, dstDecl) + + srcComments := []CommentBlock{ + { + Type: "comment", + Text: "// step 1: initialize", + StartRow: 5, + EndRow: 5, + EnclosingDecl: srcDecl, + RelativePath: "body", + }, + { + Type: "comment", + Text: "// step 2: execute", + StartRow: 10, + EndRow: 10, + EnclosingDecl: srcDecl, + RelativePath: "body", + }, + } + + dstComments := []CommentBlock{ + { + Type: "comment", + Text: "// step 1: initialize", + StartRow: 7, + EndRow: 7, + EnclosingDecl: dstDecl, + RelativePath: "body", + }, + { + Type: "comment", + Text: "// step 2: execute", + StartRow: 12, + EndRow: 12, + EnclosingDecl: dstDecl, + RelativePath: "body", + }, + } + + res := DiffComments(srcComments, dstComments, mappings) + if len(res.Actions) != 0 { + t.Fatalf("expected 0 actions for comments inside renamed function, got %d actions: %+v", len(res.Actions), res.Actions) + } + if res.LineMappings[5] != 7 || res.LineMappings[10] != 12 { + t.Errorf("expected line mappings 5->7, 10->12; got %v", res.LineMappings) + } +} + +func TestDiffCommentsLeadingDocstringRenamed(t *testing.T) { + srcDecl := &treesitter.ASTNode{ID: 10, Type: "function_declaration"} + dstDecl := &treesitter.ASTNode{ID: 25, Type: "function_declaration"} + + mappings := engine.NewMapping() + mappings.Add(srcDecl, dstDecl) + + srcComments := []CommentBlock{ + { + Type: "comment", + Text: "// CalculateTotal computes total price", + StartRow: 4, + EndRow: 4, + EnclosingDecl: srcDecl, + RelativePath: "doc", + }, + } + dstComments := []CommentBlock{ + { + Type: "comment", + Text: "// CalculateTotal computes total price", + StartRow: 8, + EndRow: 8, + EnclosingDecl: dstDecl, + RelativePath: "doc", + }, + } + + res := DiffComments(srcComments, dstComments, mappings) + if len(res.Actions) != 0 { + t.Fatalf("expected 0 actions for docstring attached to renamed function, got %d actions", len(res.Actions)) + } + if res.LineMappings[4] != 8 { + t.Errorf("expected line mapping 4->8, got %v", res.LineMappings) + } +} + +func TestDiffCommentsBranchIsolation(t *testing.T) { + srcDecl := &treesitter.ASTNode{ID: 10, Type: "function_declaration"} + dstDecl := &treesitter.ASTNode{ID: 10, Type: "function_declaration"} + + mappings := engine.NewMapping() + mappings.Add(srcDecl, dstDecl) + + srcComments := []CommentBlock{ + { + Type: "comment", + Text: "// handle error", + StartRow: 10, + EndRow: 10, + EnclosingDecl: srcDecl, + RelativePath: "body/if_statement/consequence", + }, + } + dstComments := []CommentBlock{ + { + Type: "comment", + Text: "// handle error", + StartRow: 20, + EndRow: 20, + EnclosingDecl: dstDecl, + RelativePath: "body/if_statement/alternative", + }, + } + + res := DiffComments(srcComments, dstComments, mappings) + // Because relative paths differ ("consequence" vs "alternative"), it should not match in Pass 1 LCS + // Pass 2 handles cross-scope as Delete + Insert (since dist is 10 <= 25) + if len(res.Actions) != 2 { + t.Fatalf("expected 2 actions (1 Delete, 1 Insert) across different branches, got %d", len(res.Actions)) + } +} + +func TestDiffCommentsUnmappedStrictIsolation(t *testing.T) { + srcDecl := &treesitter.ASTNode{ID: 10, Type: "function_declaration"} + dstDecl := &treesitter.ASTNode{ID: 99, Type: "function_declaration"} + + // Unmapped declarations (mappings does NOT map srcDecl to dstDecl) + mappings := engine.NewMapping() + + srcComments := []CommentBlock{ + { + Type: "comment", + Text: "// validate inputs", + StartRow: 10, + EndRow: 10, + EnclosingDecl: srcDecl, + RelativePath: "body", + }, + } + dstComments := []CommentBlock{ + { + Type: "comment", + Text: "// validate inputs", + StartRow: 100, // distant row > 25 + EndRow: 100, + EnclosingDecl: dstDecl, + RelativePath: "body", + }, + } + + res := DiffComments(srcComments, dstComments, mappings) + if len(res.Actions) != 2 { + t.Fatalf("expected 2 actions (1 Delete, 1 Insert) for unmapped distant declarations, got %d", len(res.Actions)) + } + hasDelete := false + hasInsert := false + for _, act := range res.Actions { + if act.Type == actions.Delete { + hasDelete = true + } + if act.Type == actions.Insert { + hasInsert = true + } + } + if !hasDelete || !hasInsert { + t.Errorf("expected 1 Delete and 1 Insert action, got: %+v", res.Actions) + } +} + +func TestExtractCommentsInsideFunctionNotDocComment(t *testing.T) { + src := []byte(` +public class TestClass { + public void releaseByteBuffer(int ix, byte[] buffer) { + // 13-Jan-2024, tatu: [core#1186] Replace only if beneficial: + byte[] oldBuffer = _byteBuffers.get(ix); + } +} +`) + + _, flatNodes, symbols, err := treesitter.ParseForPipeline(src, "java") + if err != nil { + t.Fatal(err) + } + + comments := ExtractComments(flatNodes, symbols, src, "java") + if len(comments) != 1 { + t.Fatalf("expected 1 comment, got %d", len(comments)) + } + c := comments[0] + if c.DeclType != "method_declaration" { + t.Errorf("expected DeclType to be 'method_declaration', got %q", c.DeclType) + } + if c.RelativePath == "doc" { + t.Errorf("expected RelativePath NOT to be 'doc' for comment inside method body, got %q", c.RelativePath) + } +} diff --git a/internal/comments/diff.go b/internal/comments/diff.go index 6f12b088..9c24fa35 100644 --- a/internal/comments/diff.go +++ b/internal/comments/diff.go @@ -1,6 +1,7 @@ package comments import ( + "fmt" "strings" "github.com/HarshK97/diffmantic/internal/actions" @@ -14,8 +15,8 @@ type DiffResult struct { LineMappings map[int]int } -// DiffComments matches and diffs comments between source and destination files. -func DiffComments(srcComments, dstComments []CommentBlock) *DiffResult { +// DiffComments matches and diffs comments between source and destination files with AST mapping awareness. +func DiffComments(srcComments, dstComments []CommentBlock, mappings *engine.Mapping) *DiffResult { res := &DiffResult{ LineMappings: make(map[int]int), } @@ -26,16 +27,19 @@ func DiffComments(srcComments, dstComments []CommentBlock) *DiffResult { srcMatched := make([]bool, len(srcComments)) dstMatched := make([]bool, len(dstComments)) - // Match identical comments within each scope using LCS so repeated comments don't cross over. + // Match identical comments within each canonical mapped scope using LCS so repeated comments don't cross over. scopeSrcMap := make(map[string][]int) scopeDstMap := make(map[string][]int) for i := range srcComments { - scopeSrcMap[srcComments[i].ScopeKey] = append(scopeSrcMap[srcComments[i].ScopeKey], i) + key := canonicalScopeKey(&srcComments[i], mappings, true) + scopeSrcMap[key] = append(scopeSrcMap[key], i) } for j := range dstComments { - scopeDstMap[dstComments[j].ScopeKey] = append(scopeDstMap[dstComments[j].ScopeKey], j) + key := canonicalScopeKey(&dstComments[j], mappings, false) + scopeDstMap[key] = append(scopeDstMap[key], j) } + // PASS 1: Intra-Scope Monotonic LCS Dynamic Programming for scopeKey, srcIdxs := range scopeSrcMap { dstIdxs := scopeDstMap[scopeKey] if len(dstIdxs) == 0 { @@ -71,7 +75,7 @@ func DiffComments(srcComments, dstComments []CommentBlock) *DiffResult { dstMatched[dj] = true sc := &srcComments[si] dc := &dstComments[dj] - nLines := min(sc.EndRow-sc.StartRow+1, dc.EndRow-dc.StartRow+1) + nLines := min(commentLineCount(sc), commentLineCount(dc)) for k := 0; k < nLines; k++ { res.LineMappings[sc.StartRow+k] = dc.StartRow + k } @@ -85,7 +89,7 @@ func DiffComments(srcComments, dstComments []CommentBlock) *DiffResult { } } - // Exact text matches across different scopes (treated as moved comments). + // PASS 2: Exact text matches across different scopes (treated as moved comments). for i := range srcComments { if srcMatched[i] { continue @@ -112,30 +116,36 @@ func DiffComments(srcComments, dstComments []CommentBlock) *DiffResult { srcMatched[i] = true dstMatched[bestJ] = true dc := &dstComments[bestJ] - nLines := min(sc.EndRow-sc.StartRow+1, dc.EndRow-dc.StartRow+1) - for k := 0; k < nLines; k++ { - res.LineMappings[sc.StartRow+k] = dc.StartRow + k - } - if sc.ScopeKey != dc.ScopeKey { - srcNode := createCommentNode(sc) - dstNode := createCommentNode(dc) - res.Actions = append(res.Actions, actions.Action{ - Type: actions.Move, - Node: srcNode, - DestNode: dstNode, - Parent: dstNode.Parent, - }) + scKey := canonicalScopeKey(sc, mappings, true) + dcKey := canonicalScopeKey(dc, mappings, false) + if scKey == dcKey { + nLines := min(commentLineCount(sc), commentLineCount(dc)) + for k := 0; k < nLines; k++ { + res.LineMappings[sc.StartRow+k] = dc.StartRow + k + } + } else { + res.Actions = append(res.Actions, + actions.Action{ + Type: actions.Delete, + Node: createCommentNode(sc, sc.Language), + }, + actions.Action{ + Type: actions.Insert, + Node: createCommentNode(dc, dc.Language), + }, + ) } } } - // Fuzzy match edited comments in the same scope. + // PASS 3: Fuzzy match edited comments in the same scope. for i := range srcComments { if srcMatched[i] { continue } sc := &srcComments[i] + scKey := canonicalScopeKey(sc, mappings, true) bestJ := -1 bestScore := 0.0 @@ -144,13 +154,14 @@ func DiffComments(srcComments, dstComments []CommentBlock) *DiffResult { continue } dc := &dstComments[j] + dcKey := canonicalScopeKey(dc, mappings, false) - if sc.ScopeKey != dc.ScopeKey { + if scKey != dcKey { continue } - srcIsMulti := strings.Contains(sc.Text, "\n") - dstIsMulti := strings.Contains(dc.Text, "\n") + srcIsMulti := strings.Contains(strings.TrimRight(sc.Text, "\r\n"), "\n") + dstIsMulti := strings.Contains(strings.TrimRight(dc.Text, "\r\n"), "\n") sim := stringSimilarity(sc.Text, dc.Text) minThreshold := 0.40 @@ -180,7 +191,7 @@ func DiffComments(srcComments, dstComments []CommentBlock) *DiffResult { for i := range srcComments { if !srcMatched[i] { sc := &srcComments[i] - node := createCommentNode(sc) + node := createCommentNode(sc, sc.Language) res.Actions = append(res.Actions, actions.Action{ Type: actions.Delete, Node: node, @@ -191,7 +202,7 @@ func DiffComments(srcComments, dstComments []CommentBlock) *DiffResult { for j := range dstComments { if !dstMatched[j] { dc := &dstComments[j] - node := createCommentNode(dc) + node := createCommentNode(dc, dc.Language) res.Actions = append(res.Actions, actions.Action{ Type: actions.Insert, Node: node, @@ -203,13 +214,16 @@ func DiffComments(srcComments, dstComments []CommentBlock) *DiffResult { } func diffCommentBlock(sc, dc *CommentBlock, res *DiffResult) { - srcIsMulti := strings.Contains(sc.Text, "\n") - dstIsMulti := strings.Contains(dc.Text, "\n") + srcTrimmed := strings.TrimRight(sc.Text, "\r\n") + dstTrimmed := strings.TrimRight(dc.Text, "\r\n") + + srcIsMulti := strings.Contains(srcTrimmed, "\n") + dstIsMulti := strings.Contains(dstTrimmed, "\n") if !srcIsMulti && !dstIsMulti { res.LineMappings[sc.StartRow] = dc.StartRow - srcNode := createCommentNode(sc) - dstNode := createCommentNode(dc) + srcNode := createCommentNode(sc, sc.Language) + dstNode := createCommentNode(dc, dc.Language) res.Actions = append(res.Actions, actions.Action{ Type: actions.Update, Node: srcNode, @@ -220,8 +234,8 @@ func diffCommentBlock(sc, dc *CommentBlock, res *DiffResult) { } // Line-by-line diff for multiline comments. - srcLines := strings.Split(sc.Text, "\n") - dstLines := strings.Split(dc.Text, "\n") + srcLines := strings.Split(srcTrimmed, "\n") + dstLines := strings.Split(dstTrimmed, "\n") matchedA := engine.LineDiff(srcLines, dstLines) matchedB := make(map[int]int) @@ -269,8 +283,8 @@ func diffCommentBlock(sc, dc *CommentBlock, res *DiffResult) { row := uint32(sc.StartRow + i) dstRow := uint32(dc.StartRow + j) - srcNode := createCommentLineNode(sc, srcLines[i], startByte, endByte, row) - dstNode := createCommentLineNode(dc, dstLines[j], dstStartByte, dstEndByte, dstRow) + srcNode := createCommentLineNode(sc, srcLines[i], startByte, endByte, row, sc.Language) + dstNode := createCommentLineNode(dc, dstLines[j], dstStartByte, dstEndByte, dstRow, dc.Language) res.Actions = append(res.Actions, actions.Action{ Type: actions.Update, Node: srcNode, @@ -285,7 +299,7 @@ func diffCommentBlock(sc, dc *CommentBlock, res *DiffResult) { if _, ok := matchedA[i]; !ok { startByte, endByte := srcOffsets[i][0], srcOffsets[i][1] row := uint32(sc.StartRow + i) - lineNode := createCommentLineNode(sc, srcLines[i], startByte, endByte, row) + lineNode := createCommentLineNode(sc, srcLines[i], startByte, endByte, row, sc.Language) res.Actions = append(res.Actions, actions.Action{ Type: actions.Delete, Node: lineNode, @@ -297,7 +311,7 @@ func diffCommentBlock(sc, dc *CommentBlock, res *DiffResult) { if _, ok := matchedB[j]; !ok { startByte, endByte := dstOffsets[j][0], dstOffsets[j][1] row := uint32(dc.StartRow + j) - lineNode := createCommentLineNode(dc, dstLines[j], startByte, endByte, row) + lineNode := createCommentLineNode(dc, dstLines[j], startByte, endByte, row, dc.Language) res.Actions = append(res.Actions, actions.Action{ Type: actions.Insert, Node: lineNode, @@ -348,23 +362,27 @@ func computeLineOffsets(baseOffset uint32, lines []string) [][2]uint32 { return offsets } -func createCommentNode(c *CommentBlock) *treesitter.ASTNode { - node := createSyntheticNode(c.Type, c.Text, c.StartByte, c.EndByte, uint32(c.StartRow), uint32(c.StartCol), uint32(c.EndRow), uint32(c.EndCol)) +func createCommentNode(c *CommentBlock, lang string) *treesitter.ASTNode { + node := createSyntheticNode(c.Type, c.Text, c.StartByte, c.EndByte, uint32(c.StartRow), uint32(c.StartCol), uint32(c.EndRow), uint32(c.EndCol), lang) if c.ParentType != "" { - node.Parent = createSyntheticNode(c.ParentType, "", c.ParentStart, c.ParentEnd, uint32(c.ParentRow), 0, uint32(c.ParentEndRow), 0) + parent := createSyntheticNode(c.ParentType, "", c.ParentStart, c.ParentEnd, uint32(c.ParentRow), 0, uint32(c.ParentEndRow), 0, lang) + node.Parent = parent + parent.Children = []*treesitter.ASTNode{node} } return node } -func createCommentLineNode(c *CommentBlock, label string, startByte, endByte, row uint32) *treesitter.ASTNode { - node := createSyntheticNode(c.Type, label, startByte, endByte, row, 0, row, uint32(len(label))) +func createCommentLineNode(c *CommentBlock, label string, startByte, endByte, row uint32, lang string) *treesitter.ASTNode { + node := createSyntheticNode(c.Type, label, startByte, endByte, row, 0, row, uint32(len(label)), lang) if c.ParentType != "" { - node.Parent = createSyntheticNode(c.ParentType, "", c.ParentStart, c.ParentEnd, uint32(c.ParentRow), 0, uint32(c.ParentEndRow), 0) + parent := createSyntheticNode(c.ParentType, "", c.ParentStart, c.ParentEnd, uint32(c.ParentRow), 0, uint32(c.ParentEndRow), 0, lang) + node.Parent = parent + parent.Children = []*treesitter.ASTNode{node} } return node } -func createSyntheticNode(nodeType, label string, startByte, endByte, startRow, startCol, endRow, endCol uint32) *treesitter.ASTNode { +func createSyntheticNode(nodeType, label string, startByte, endByte, startRow, startCol, endRow, endCol uint32, lang string) *treesitter.ASTNode { return &treesitter.ASTNode{ Type: nodeType, Label: label, @@ -374,5 +392,43 @@ func createSyntheticNode(nodeType, label string, startByte, endByte, startRow, s StartCol: startCol, EndRow: endRow, EndCol: endCol, + Language: lang, + Children: make([]*treesitter.ASTNode, 0), + } +} + +func canonicalScopeKey(c *CommentBlock, mappings *engine.Mapping, isSource bool) string { + if c == nil { + return "root" + } + if c.EnclosingDecl == nil { + if c.RelativePath != "" { + return "root:" + c.RelativePath + } + if c.ScopeKey != "" { + return c.ScopeKey + } + return "root" + } + + if isSource { + if mappings != nil && mappings.Src() != nil { + if dstDecl, ok := mappings.Src()[c.EnclosingDecl]; ok && dstDecl != nil { + return fmt.Sprintf("decl_%d:%s", dstDecl.ID, c.RelativePath) + } + } + // Strict isolation for unmapped source declarations + return fmt.Sprintf("unmapped_src_%d:%s", c.EnclosingDecl.ID, c.RelativePath) + } + + // Destination declaration scope key + return fmt.Sprintf("decl_%d:%s", c.EnclosingDecl.ID, c.RelativePath) +} + +func commentLineCount(c *CommentBlock) int { + t := strings.TrimRight(c.Text, "\r\n") + if t == "" { + return 1 } + return strings.Count(t, "\n") + 1 } diff --git a/internal/comments/extract.go b/internal/comments/extract.go index fc0bc578..5ab2eecf 100644 --- a/internal/comments/extract.go +++ b/internal/comments/extract.go @@ -5,10 +5,12 @@ import ( "slices" "strings" + "github.com/HarshK97/diffmantic/internal/treesitter" "github.com/HarshK97/diffmantic/internal/treesitter/rules" - "github.com/odvcencio/gotreesitter" ) +const flatSentinel = 0xFFFFFFFF + // CommentBlock represents an extracted comment and its source position. type CommentBlock struct { Type string @@ -25,27 +27,48 @@ type CommentBlock struct { ParentEnd uint32 ParentRow int ParentEndRow int + Language string + + // Structural Declaration & Scope Context + DeclStart uint32 + DeclEnd uint32 + DeclType string + RelativePath string + EnclosingDecl *treesitter.ASTNode } -// ExtractComments walks the AST and returns all comment blocks. -func ExtractComments(root *gotreesitter.Node, src []byte, lang *gotreesitter.Language, r *rules.Rules) []CommentBlock { - if root == nil || lang == nil { +// ExtractComments walks the raw flat buffer (pre-IsIgnored filtering) +// and extracts comment blocks with full CST sibling/parent context. +func ExtractComments(nodes []treesitter.FlatNode, symbols []string, src []byte, langName string) []CommentBlock { + if len(nodes) == 0 { return nil } + r := rules.Get(langName) + srcLen := uint32(len(src)) var list []CommentBlock - traverseForComments(root, src, lang, r, &list) - return list -} -func traverseForComments(n *gotreesitter.Node, src []byte, lang *gotreesitter.Language, r *rules.Rules, list *[]CommentBlock) { - if n == nil { - return - } - nodeType := n.Type(lang) - if (r != nil && r.IsComment(nodeType)) || (r == nil && nodeType == "comment") { - srcLen := uint32(len(src)) - start := min(n.StartByte(), srcLen) - end := min(n.EndByte(), srcLen) + for idx := range nodes { + fn := &nodes[idx] + rawType := flatSymbol(fn, symbols) + if !isCommentType(rawType, r) { + continue + } + + // Skip child comment tokens whose ancestor is already a comment container + // (e.g. in Rust where line_comment wraps doc_comment). + isChildComment := false + for pIdx := fn.ParentIdx; pIdx != flatSentinel && int(pIdx) < len(nodes); pIdx = nodes[pIdx].ParentIdx { + if isCommentType(flatSymbol(&nodes[pIdx], symbols), r) { + isChildComment = true + break + } + } + if isChildComment { + continue + } + + start := min(fn.StartByte, srcLen) + end := min(fn.EndByte, srcLen) if start > end { start = end } @@ -54,51 +77,163 @@ func traverseForComments(n *gotreesitter.Node, src []byte, lang *gotreesitter.La var parentType string var parentStart, parentEnd uint32 var parentRow, parentEndRow int - if p := n.Parent(); p != nil { - parentType = p.Type(lang) - parentStart = min(p.StartByte(), srcLen) - parentEnd = min(p.EndByte(), srcLen) - parentRow = int(p.StartPoint().Row) - parentEndRow = int(p.EndPoint().Row) + if fn.ParentIdx != flatSentinel && int(fn.ParentIdx) < len(nodes) { + p := &nodes[fn.ParentIdx] + parentType = flatSymbol(p, symbols) + parentStart = min(p.StartByte, srcLen) + parentEnd = min(p.EndByte, srcLen) + parentRow = int(p.StartRow) + parentEndRow = int(p.EndRow) } else { parentEnd = srcLen } - scopeKey := findEnclosingDeclaration(n, src, lang, r) + scopeKey := flatFindEnclosingDeclaration(uint32(idx), nodes, symbols, src, r) - *list = append(*list, CommentBlock{ - Type: nodeType, + declStart, declEnd, declType, relPath := flatCheckLeadingDocComment(uint32(idx), nodes, symbols, src, r) + if declType == "" { + declStart, declEnd, declType, relPath = flatFindEnclosingDeclarationHierarchy(uint32(idx), nodes, symbols, src, r) + } + + list = append(list, CommentBlock{ + Type: rawType, Text: text, StartByte: start, EndByte: end, - StartRow: int(n.StartPoint().Row), - StartCol: int(n.StartPoint().Column), - EndRow: int(n.EndPoint().Row), - EndCol: int(n.EndPoint().Column), + StartRow: int(fn.StartRow), + StartCol: int(fn.StartCol), + EndRow: int(fn.EndRow), + EndCol: int(fn.EndCol), ScopeKey: scopeKey, ParentType: parentType, ParentStart: parentStart, ParentEnd: parentEnd, ParentRow: parentRow, ParentEndRow: parentEndRow, + Language: langName, + DeclStart: declStart, + DeclEnd: declEnd, + DeclType: declType, + RelativePath: relPath, }) - return } - for i := range n.ChildCount() { - traverseForComments(n.Child(i), src, lang, r, list) + return list +} + +func flatSymbol(fn *treesitter.FlatNode, symbols []string) string { + if int(fn.TypeID) < len(symbols) { + return symbols[fn.TypeID] + } + return "" +} + +func isCommentType(nodeType string, r *rules.Rules) bool { + if r != nil { + return r.IsComment(nodeType) + } + return rules.IsComment(nodeType) +} + +// flatCheckLeadingDocComment mirrors checkLeadingDocComment using flat buffer sibling walking. +func flatCheckLeadingDocComment(idx uint32, nodes []treesitter.FlatNode, symbols []string, src []byte, r *rules.Rules) (uint32, uint32, string, string) { + if r == nil { + return 0, 0, "", "" + } + fn := &nodes[idx] + + // Walk NextSiblingIdx to find the first non-comment, non-"\n" sibling + nextIdx := fn.NextSiblingIdx + for nextIdx != flatSentinel && int(nextIdx) < len(nodes) { + nextType := flatSymbol(&nodes[nextIdx], symbols) + if !isCommentType(nextType, r) && nextType != "\n" { + break + } + nextIdx = nodes[nextIdx].NextSiblingIdx + } + if nextIdx == flatSentinel || int(nextIdx) >= len(nodes) { + return 0, 0, "", "" + } + + target := &nodes[nextIdx] + t := flatSymbol(target, symbols) + if !r.IsDeclaration(t) { + // Check inner children for wrapped declarations (export_statement, etc.) + childIdx := target.FirstChildIdx + for childIdx != flatSentinel && int(childIdx) < len(nodes) { + ct := flatSymbol(&nodes[childIdx], symbols) + if r.IsDeclaration(ct) { + target = &nodes[childIdx] + t = ct + break + } + childIdx = nodes[childIdx].NextSiblingIdx + } + } + if !r.IsDeclaration(t) { + return 0, 0, "", "" + } + + // Check if comment is inside a block (interior statement comment vs exterior doc comment) + pIdx := fn.ParentIdx + insideBlock := false + for pIdx != flatSentinel && int(pIdx) < len(nodes) { + if r.IsBlock(flatSymbol(&nodes[pIdx], symbols)) { + insideBlock = true + break + } + pIdx = nodes[pIdx].ParentIdx + } + if insideBlock && r.IsLocalVarDeclaration(t) { + return 0, 0, "", "" + } + + if int(target.StartRow)-int(fn.EndRow) <= 1 { + return target.StartByte, target.EndByte, t, "doc" } + return 0, 0, "", "" } -func findEnclosingDeclaration(n *gotreesitter.Node, src []byte, lang *gotreesitter.Language, r *rules.Rules) string { - if r == nil || n == nil { +// flatFindEnclosingDeclarationHierarchy mirrors findEnclosingDeclarationHierarchy. +func flatFindEnclosingDeclarationHierarchy(idx uint32, nodes []treesitter.FlatNode, symbols []string, src []byte, r *rules.Rules) (uint32, uint32, string, string) { + if r == nil { + return 0, 0, "", "root" + } + var containers []string + pIdx := nodes[idx].ParentIdx + for pIdx != flatSentinel && int(pIdx) < len(nodes) { + t := flatSymbol(&nodes[pIdx], symbols) + if r.IsDeclaration(t) { + relPath := "body" + if len(containers) > 0 { + slices.Reverse(containers) + relPath = "body/" + strings.Join(containers, "/") + } + return nodes[pIdx].StartByte, nodes[pIdx].EndByte, t, relPath + } + if r.IsBlock(t) || r.IsScaffolding(t) { + containers = append(containers, t) + } + pIdx = nodes[pIdx].ParentIdx + } + if len(containers) > 0 { + slices.Reverse(containers) + return 0, 0, "", "root/" + strings.Join(containers, "/") + } + return 0, 0, "", "root" +} + +// flatFindEnclosingDeclaration mirrors findEnclosingDeclaration. +func flatFindEnclosingDeclaration(idx uint32, nodes []treesitter.FlatNode, symbols []string, src []byte, r *rules.Rules) string { + if r == nil { return "root" } + srcLen := uint32(len(src)) var containers []string - curr := n.Parent() - for curr != nil { - t := curr.Type(lang) + pIdx := nodes[idx].ParentIdx + for pIdx != flatSentinel && int(pIdx) < len(nodes) { + t := flatSymbol(&nodes[pIdx], symbols) if r.IsDeclaration(t) { - name := getDeclarationIdentifier(curr, src, lang, r) + name := flatGetDeclarationIdentifier(&nodes[pIdx], nodes, symbols, src, r, srcLen) decl := t if name != "" { decl = t + ":" + name @@ -112,7 +247,7 @@ func findEnclosingDeclaration(n *gotreesitter.Node, src []byte, lang *gotreesitt if r.IsBlock(t) || r.IsScaffolding(t) { containers = append(containers, t) } - curr = curr.Parent() + pIdx = nodes[pIdx].ParentIdx } if len(containers) > 0 { slices.Reverse(containers) @@ -121,35 +256,71 @@ func findEnclosingDeclaration(n *gotreesitter.Node, src []byte, lang *gotreesitt return "root" } -func getDeclarationIdentifier(n *gotreesitter.Node, src []byte, lang *gotreesitter.Language, r *rules.Rules) string { - if n == nil || r == nil { +func flatGetDeclarationIdentifier(fn *treesitter.FlatNode, nodes []treesitter.FlatNode, symbols []string, src []byte, r *rules.Rules, srcLen uint32) string { + if r == nil { return "" } - for i := range n.ChildCount() { - child := n.Child(i) - if child == nil { - continue - } - ct := child.Type(lang) + childIdx := fn.FirstChildIdx + for childIdx != flatSentinel && int(childIdx) < len(nodes) { + child := &nodes[childIdx] + ct := flatSymbol(child, symbols) if r.IsIdentifier(ct) { - s := min(child.StartByte(), uint32(len(src))) - e := min(child.EndByte(), uint32(len(src))) + s := min(child.StartByte, srcLen) + e := min(child.EndByte, srcLen) if s < e { return string(src[s:e]) } } if r.IsScaffolding(ct) { - for j := range child.ChildCount() { - sub := child.Child(j) - if sub != nil && r.IsIdentifier(sub.Type(lang)) { - s := min(sub.StartByte(), uint32(len(src))) - e := min(sub.EndByte(), uint32(len(src))) + subIdx := child.FirstChildIdx + for subIdx != flatSentinel && int(subIdx) < len(nodes) { + sub := &nodes[subIdx] + if r.IsIdentifier(flatSymbol(sub, symbols)) { + s := min(sub.StartByte, srcLen) + e := min(sub.EndByte, srcLen) if s < e { return string(src[s:e]) } } + subIdx = sub.NextSiblingIdx } } + childIdx = child.NextSiblingIdx } return "" } + +type declSpanKey struct { + start uint32 + end uint32 +} + +// BindASTNodes attaches exact AST node pointers to extracted comment blocks in O(K + N). +func BindASTNodes(comments []CommentBlock, root *treesitter.ASTNode) { + if len(comments) == 0 || root == nil { + return + } + declMap := make(map[declSpanKey]*treesitter.ASTNode) + var indexDecls func(n *treesitter.ASTNode) + indexDecls = func(n *treesitter.ASTNode) { + if n == nil { + return + } + key := declSpanKey{start: n.StartByte, end: n.EndByte} + if existing, exists := declMap[key]; !exists || (existing != nil && existing.Type != n.Type) { + declMap[key] = n + } + for _, child := range n.Children { + indexDecls(child) + } + } + indexDecls(root) + + for i := range comments { + if comments[i].DeclEnd > comments[i].DeclStart || comments[i].DeclType != "" { + if declNode, ok := declMap[declSpanKey{start: comments[i].DeclStart, end: comments[i].DeclEnd}]; ok { + comments[i].EnclosingDecl = declNode + } + } + } +} diff --git a/internal/inline/render.go b/internal/inline/render.go index d0070614..cddd5161 100644 --- a/internal/inline/render.go +++ b/internal/inline/render.go @@ -222,10 +222,10 @@ func Render(srcFile, dstFile string, srcBytes, dstBytes []byte, env *serialize.E // Resolve language rules for declaration classification var r *rules.Rules - if entry := treesitter.DetectGrammarEntry(srcFile); entry != nil { - r = rules.Get(entry.Name) - } else if entry := treesitter.DetectGrammarEntry(dstFile); entry != nil { - r = rules.Get(entry.Name) + if lang, _ := treesitter.DetectLanguage(srcFile); lang != nil { + r = rules.Get(lang.Name) + } else if lang, _ := treesitter.DetectLanguage(dstFile); lang != nil { + r = rules.Get(lang.Name) } meta := buildHunkMoveMetadata(env.Actions, hunks, filteredPairs, srcOffsets, dstOffsets, srcLines, dstLines, r) diff --git a/internal/pipeline/pipeline.go b/internal/pipeline/pipeline.go index 7ceac271..affe2ae9 100644 --- a/internal/pipeline/pipeline.go +++ b/internal/pipeline/pipeline.go @@ -12,18 +12,22 @@ import ( "github.com/HarshK97/diffmantic/internal/postprocess" "github.com/HarshK97/diffmantic/internal/serialize" "github.com/HarshK97/diffmantic/internal/treesitter" - "github.com/HarshK97/diffmantic/internal/treesitter/rules" - "github.com/odvcencio/gotreesitter" ) // MaxASTFileSize caps the file size for AST parsing before falling back to line diffing. -const MaxASTFileSize = 400 * 1024 +const MaxASTFileSize = 1024 * 1024 + +// MaxASTFileLines caps the line count for AST parsing before falling back to line diffing. +const MaxASTFileLines = 10000 // DiffOptions configures parsing limits, comment handling, and output options. type DiffOptions struct { ParseErrorLimit int DisableErrorFallback bool DisableSizeLimit bool + MaxASTFileSize int + DisableLineLimit bool + MaxASTFileLines int IsConflict bool IgnoreComments bool EnvelopeOpts serialize.EnvelopeOptions @@ -35,6 +39,7 @@ type DiffResult struct { DstBytes []byte SrcFile string DstFile string + IsBinary bool SrcAST *treesitter.ASTNode DstAST *treesitter.ASTNode MatchResult *engine.MatchResult @@ -42,6 +47,15 @@ type DiffResult struct { Envelope *serialize.Envelope } +// IsBinary detects whether a byte buffer contains binary data (null bytes in the first 8000 bytes). +func IsBinary(data []byte) bool { + sample := data + if len(sample) > 8000 { + sample = sample[:8000] + } + return bytes.IndexByte(sample, 0) != -1 +} + // HasConflictMarkers checks if the buffer contains Git merge conflict markers. func HasConflictMarkers(data []byte) bool { hasStart := bytes.HasPrefix(data, []byte("<<<<<<<")) || bytes.Contains(data, []byte("\n<<<<<<<")) @@ -61,8 +75,37 @@ func Run(srcBytes, dstBytes []byte, srcFile, dstFile string, opts DiffOptions) ( } } + if IsBinary(srcBytes) || IsBinary(dstBytes) { + return &DiffResult{ + SrcBytes: srcBytes, + DstBytes: dstBytes, + SrcFile: srcFile, + DstFile: dstFile, + IsBinary: true, + Envelope: &serialize.Envelope{ + Version: serialize.SchemaVersion, + IsBinary: true, + }, + }, nil + } + + maxSize := MaxASTFileSize + if opts.MaxASTFileSize > 0 { + maxSize = opts.MaxASTFileSize + } + + maxLines := MaxASTFileLines + if opts.MaxASTFileLines > 0 { + maxLines = opts.MaxASTFileLines + } + + exceedsLines := !opts.DisableLineLimit && maxLines > 0 && + (bytes.Count(srcBytes, []byte{'\n'}) > maxLines || bytes.Count(dstBytes, []byte{'\n'}) > maxLines) + + exceedsSize := !opts.DisableSizeLimit && (len(srcBytes) > maxSize || len(dstBytes) > maxSize) + if opts.IsConflict || (HasConflictMarkers(srcBytes) || HasConflictMarkers(dstBytes)) || - (!opts.DisableSizeLimit && (len(srcBytes) > MaxASTFileSize || len(dstBytes) > MaxASTFileSize)) { + exceedsSize || exceedsLines { return &DiffResult{ SrcBytes: srcBytes, DstBytes: dstBytes, @@ -93,14 +136,9 @@ func Run(srcBytes, dstBytes []byte, srcFile, dstFile string, opts DiffOptions) ( langB = langA } - rulesA := rules.Get(langA.Name) - rulesB := rules.Get(langB.Name) - var ( srcAST *treesitter.ASTNode dstAST *treesitter.ASTNode - srcTree *gotreesitter.Tree - dstTree *gotreesitter.Tree srcComments []comments.CommentBlock dstComments []comments.CommentBlock wg sync.WaitGroup @@ -109,16 +147,30 @@ func Run(srcBytes, dstBytes []byte, srcFile, dstFile string, opts DiffOptions) ( wg.Add(2) go func() { defer wg.Done() - srcAST, srcTree, _ = treesitter.ParseWithLanguageAndTree(srcBytes, langA) - if srcTree != nil && !opts.IgnoreComments { - srcComments = comments.ExtractComments(srcTree.RootNode(), srcBytes, langA, rulesA) + var ( + srcFlatNodes []treesitter.FlatNode + srcSymbols []string + ) + srcAST, srcFlatNodes, srcSymbols, _ = treesitter.ParseForPipeline(srcBytes, langA.Name) + if !opts.IgnoreComments && len(srcFlatNodes) > 0 { + srcComments = comments.ExtractComments(srcFlatNodes, srcSymbols, srcBytes, langA.Name) + if srcAST != nil { + comments.BindASTNodes(srcComments, srcAST) + } } }() go func() { defer wg.Done() - dstAST, dstTree, _ = treesitter.ParseWithLanguageAndTree(dstBytes, langB) - if dstTree != nil && !opts.IgnoreComments { - dstComments = comments.ExtractComments(dstTree.RootNode(), dstBytes, langB, rulesB) + var ( + dstFlatNodes []treesitter.FlatNode + dstSymbols []string + ) + dstAST, dstFlatNodes, dstSymbols, _ = treesitter.ParseForPipeline(dstBytes, langB.Name) + if !opts.IgnoreComments && len(dstFlatNodes) > 0 { + dstComments = comments.ExtractComments(dstFlatNodes, dstSymbols, dstBytes, langB.Name) + if dstAST != nil { + comments.BindASTNodes(dstComments, dstAST) + } } }() @@ -135,29 +187,29 @@ func Run(srcBytes, dstBytes []byte, srcFile, dstFile string, opts DiffOptions) ( }, nil } + matchResult := engine.Match(srcAST, dstAST, srcBytes, dstBytes, part) + var ( - matchResult *engine.MatchResult - commentRes *comments.DiffResult - matchWg sync.WaitGroup + commentRes *comments.DiffResult + es *actions.EditScript + wgPost sync.WaitGroup ) - matchWg.Add(1) + wgPost.Add(1) go func() { - defer matchWg.Done() - matchResult = engine.Match(srcAST, dstAST, srcBytes, dstBytes, part) + defer wgPost.Done() + es = actions.GenerateEditScript(srcAST, dstAST, matchResult.Mappings) }() if !opts.IgnoreComments && (len(srcComments) > 0 || len(dstComments) > 0) { - matchWg.Add(1) + wgPost.Add(1) go func() { - defer matchWg.Done() - commentRes = comments.DiffComments(srcComments, dstComments) + defer wgPost.Done() + commentRes = comments.DiffComments(srcComments, dstComments, matchResult.Mappings) }() } - matchWg.Wait() - - es := actions.GenerateEditScript(srcAST, dstAST, matchResult.Mappings) + wgPost.Wait() if commentRes != nil && len(commentRes.Actions) > 0 { for _, act := range commentRes.Actions { diff --git a/internal/pipeline/pipeline_test.go b/internal/pipeline/pipeline_test.go new file mode 100644 index 00000000..13b3376d --- /dev/null +++ b/internal/pipeline/pipeline_test.go @@ -0,0 +1,49 @@ +package pipeline + +import ( + "strings" + "testing" +) + +func TestPipeline_LineLimitFallback(t *testing.T) { + // Build a small Go file with 12 lines + var lines []string + for i := 0; i < 12; i++ { + lines = append(lines, "package main") + } + content := []byte(strings.Join(lines, "\n")) + + // With maxLines=10 and 12-line file, it should fall back to line diff (no AST). + res, err := Run(content, content, "main.go", "main.go", DiffOptions{ + MaxASTFileLines: 10, + }) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if res.SrcAST != nil || res.DstAST != nil { + t.Errorf("expected AST nil on line limit fallback, got non-nil") + } + + // With DisableLineLimit=true, AST should parse regardless. + resUnlimited, err := Run(content, content, "main.go", "main.go", DiffOptions{ + MaxASTFileLines: 10, + DisableLineLimit: true, + }) + if err != nil { + t.Fatalf("unexpected error with disabled limit: %v", err) + } + if resUnlimited.SrcAST == nil { + t.Errorf("expected AST parsed when line limit disabled") + } + + // With higher limit of 20, file has fewer lines — should parse as AST. + resHigher, err := Run(content, content, "main.go", "main.go", DiffOptions{ + MaxASTFileLines: 20, + }) + if err != nil { + t.Fatalf("unexpected error with higher limit: %v", err) + } + if resHigher.SrcAST == nil { + t.Errorf("expected AST parsed when file is under line limit") + } +} diff --git a/internal/serialize/json.go b/internal/serialize/json.go index 73817131..cd95ac35 100644 --- a/internal/serialize/json.go +++ b/internal/serialize/json.go @@ -46,6 +46,7 @@ type EnvelopeOptions struct { // Envelope wraps the serialized actions list with a schema version. type Envelope struct { Version string `json:"version"` + IsBinary bool `json:"is_binary,omitempty"` Actions []Action `json:"actions,omitempty"` LineAlignment []LineAlignmentPair `json:"line_alignment,omitempty"` LeftHighlights []HighlightSpan `json:"left_highlights,omitempty"` diff --git a/internal/treesitter/ast.go b/internal/treesitter/ast.go index 12f8b22e..ab4afc07 100644 --- a/internal/treesitter/ast.go +++ b/internal/treesitter/ast.go @@ -2,10 +2,8 @@ package treesitter import ( "slices" - "strings" "github.com/HarshK97/diffmantic/internal/treesitter/rules" - "github.com/odvcencio/gotreesitter" ) type ASTNode struct { @@ -68,109 +66,6 @@ func (n *ASTNode) ComputeHashes() { n.StructureHash = sh } -func BuildAST(n *gotreesitter.Node, src []byte, lang *gotreesitter.Language, parent *ASTNode) *ASTNode { - if n == nil { - return nil - } - r := rules.Get(lang.Name) - node := buildASTWithRules(n, src, lang, parent, r) - if node != nil && parent == nil { - errCount := countErrorNodes(n, lang) - node.Language = lang.Name - node.ParseErrorCount = errCount - node.HasError = errCount > 0 - node.ComputeHashes() - EnsureIndex(node) - } - return node -} - -func countErrorNodes(n *gotreesitter.Node, lang *gotreesitter.Language) int { - if n == nil || !n.HasError() { - return 0 - } - count := 0 - if n.Type(lang) == "ERROR" || n.IsError() || n.IsMissing() { - count = 1 - } - for i := range n.ChildCount() { - count += countErrorNodes(n.Child(i), lang) - } - return count -} - -func buildASTWithRules(n *gotreesitter.Node, src []byte, lang *gotreesitter.Language, parent *ASTNode, r *rules.Rules) *ASTNode { - nodeType := n.Type(lang) - if n.IsMissing() { - nodeType = "MISSING " + nodeType - } - - isLeaf := n.ChildCount() == 0 || (r != nil && r.IsFlattened(nodeType)) - var label string - if isLeaf { - srcLen := uint32(len(src)) - start, end := min(n.StartByte(), srcLen), min(n.EndByte(), srcLen) - if start > end { - start = end - } - label = strings.TrimSpace(string(src[start:end])) - } - - if r != nil && r.IsIgnored(nodeType, label) { - return nil - } - - node := &ASTNode{ - Type: nodeType, - Parent: parent, - StartByte: n.StartByte(), - EndByte: n.EndByte(), - StartRow: n.StartPoint().Row, - StartCol: n.StartPoint().Column, - EndRow: n.EndPoint().Row, - EndCol: n.EndPoint().Column, - } - - // Only set label for leaf nodes or string literals. - if isLeaf { - node.Label = label - } - - if r != nil { - if alias, ok := r.Alias(nodeType, label); ok { - node.Type = alias - } - if r.IsLabelIgnored(node.Type) { - node.Label = "" - } - if isLeaf && r.IsKeyword(nodeType, label) { - node.IsKeyword = true - } - if r.IsUnordered(node.Type) { - node.IsUnordered = true - } - } - - for i := range n.ChildCount() { - if child := buildASTWithRules(n.Child(i), src, lang, node, r); child != nil { - node.Children = append(node.Children, child) - } - } - - if r != nil && r.IsFlattened(nodeType) { - var flattenedChildren []*ASTNode - for _, child := range node.Children { - flattenedChildren = append(flattenedChildren, child.Children...) - for _, grandchild := range child.Children { - grandchild.Parent = node - } - } - node.Children = flattenedChildren - } - - return node -} - // Size returns the total number of nodes in the subtree rooted at n. func (n *ASTNode) Size() int { if n == nil { diff --git a/internal/treesitter/bridge_cgo.go b/internal/treesitter/bridge_cgo.go new file mode 100644 index 00000000..8379d74c --- /dev/null +++ b/internal/treesitter/bridge_cgo.go @@ -0,0 +1,224 @@ +package treesitter + +/* +#cgo CFLAGS: -I${SRCDIR}/../../native/bridge/include -O3 +#cgo LDFLAGS: -L${SRCDIR}/../../native/bridge/lib -ldiffmantic_grammars -lstdc++ +#include "bridge.h" +#include "../../native/bridge/src/bridge.c" +#include + +extern const TSLanguage* diffmantic_get_native_language(const char* name); + +typedef void* (*tree_sitter_lang_fn)(void); + +static void* get_ts_lang(const char* lib_path, const char* symbol_name) { + void* handle = dlopen(lib_path, RTLD_NOW); + if (!handle) return NULL; + tree_sitter_lang_fn fn = (tree_sitter_lang_fn)dlsym(handle, symbol_name); + if (!fn) { + dlclose(handle); + return NULL; + } + return fn(); +} + +static uint32_t get_ts_lang_symbol_count(const void* ts_lang_ptr) { + return ts_language_symbol_count((const TSLanguage*)ts_lang_ptr); +} + +static const char* get_ts_lang_symbol_name(const void* ts_lang_ptr, uint16_t symbol_id) { + return ts_language_symbol_name((const TSLanguage*)ts_lang_ptr, symbol_id); +} +*/ +import "C" + +import ( + "errors" + "fmt" + "slices" + "sync" + "unsafe" +) + +type cachedLang struct { + ptr unsafe.Pointer + symbols []string +} + +var ( + nativeLangCache = make(map[string]cachedLang) + nativeLangMu sync.RWMutex +) + +func getLanguageSymbols(langName string) (unsafe.Pointer, []string, error) { + if langName == "" { + return nil, nil, errors.New("empty language name") + } + + nativeLangMu.RLock() + if entry, ok := nativeLangCache[langName]; ok { + nativeLangMu.RUnlock() + return entry.ptr, entry.symbols, nil + } + nativeLangMu.RUnlock() + + nativeLangMu.Lock() + defer nativeLangMu.Unlock() + + if entry, ok := nativeLangCache[langName]; ok { + return entry.ptr, entry.symbols, nil + } + + ptr, err := GetNativeLanguage(langName) + if err != nil || ptr == nil { + return nil, nil, fmt.Errorf("native parser not available for %s: %w", langName, err) + } + + symbols := NativeLanguageSymbols(ptr) + nativeLangCache[langName] = cachedLang{ptr: ptr, symbols: symbols} + return ptr, symbols, nil +} + +// ParseWithLanguage parses source bytes for a given language name. +func ParseWithLanguage(src []byte, langName string) (*ASTNode, error) { + ptr, symbols, err := getLanguageSymbols(langName) + if err != nil { + return nil, err + } + return ParseWithNativeFlatBuffer(src, ptr, langName, symbols) +} + +// ParseForPipeline parses via the native flat-buffer bridge, returning the root AST, +// raw flat nodes, and symbol table for comment extraction in the diff pipeline. +func ParseForPipeline(src []byte, langName string) (*ASTNode, []FlatNode, []string, error) { + ptr, symbols, err := getLanguageSymbols(langName) + if err != nil { + return nil, nil, nil, err + } + ast, flatNodes, err := parseWithNativeFlatBufferKeepNodes(src, ptr, langName, symbols) + return ast, flatNodes, symbols, err +} + +// parseWithNativeFlatBufferKeepNodes is like ParseWithNativeFlatBuffer but also returns +// a Go-owned copy of the flat node array for comment extraction. +func parseWithNativeFlatBufferKeepNodes(src []byte, tsLangPtr unsafe.Pointer, langName string, symbols []string) (*ASTNode, []FlatNode, error) { + if tsLangPtr == nil { + return nil, nil, errors.New("nil native language pointer") + } + + if len(symbols) == 0 { + symbols = NativeLanguageSymbols(tsLangPtr) + } + + var srcPtr *C.uint8_t + if len(src) > 0 { + srcPtr = (*C.uint8_t)(unsafe.Pointer(&src[0])) + } + + res := C.parse_to_flat_ast( + srcPtr, + C.size_t(len(src)), + tsLangPtr, + ) + + if res.error_code != 0 { + return nil, nil, fmt.Errorf("native flat tree-sitter parse failed (code %d)", int(res.error_code)) + } + + defer C.free_flat_ast(res) + + var nodes []FlatNode + if res.node_count > 0 && res.nodes_ptr != nil { + nodes = unsafe.Slice((*FlatNode)(unsafe.Pointer(res.nodes_ptr)), int(res.node_count)) + } + + // Copy flat nodes into Go-owned memory for comment extraction (C memory freed on return). + goNodes := slices.Clone(nodes) + + root := IngestFlatAST(nodes, symbols, src, langName) + + return root, goNodes, nil +} + +type FlatASTResult = C.FlatASTResult + +// GetNativeLanguage retrieves the statically linked native Tree-sitter language for any of the 16 core languages (18 grammars). +func GetNativeLanguage(langName string) (unsafe.Pointer, error) { + cName := C.CString(langName) + defer C.free(unsafe.Pointer(cName)) + + ptr := unsafe.Pointer(C.diffmantic_get_native_language(cName)) + if ptr == nil { + return nil, fmt.Errorf("unsupported or unregistered native language: %s", langName) + } + return ptr, nil +} + +// LoadNativeLanguage dynamically loads a Tree-sitter grammar function pointer from a shared library. +func LoadNativeLanguage(libPath, symbolName string) (unsafe.Pointer, error) { + cPath := C.CString(libPath) + defer C.free(unsafe.Pointer(cPath)) + cSym := C.CString(symbolName) + defer C.free(unsafe.Pointer(cSym)) + + ptr := C.get_ts_lang(cPath, cSym) + if ptr == nil { + return nil, fmt.Errorf("failed to load symbol %s from %s", symbolName, libPath) + } + return ptr, nil +} + +// NativeLanguageSymbols returns the slice of symbol names defined by the native Tree-sitter language. +func NativeLanguageSymbols(tsLangPtr unsafe.Pointer) []string { + if tsLangPtr == nil { + return nil + } + count := int(C.get_ts_lang_symbol_count(tsLangPtr)) + symbols := make([]string, count) + for i := range count { + cName := C.get_ts_lang_symbol_name(tsLangPtr, C.uint16_t(i)) + if cName != nil { + symbols[i] = C.GoString(cName) + } + } + return symbols +} + +// ParseWithNativeFlatBuffer parses source code using the native Tree-sitter engine +// and converts the resulting flat buffer into an ASTNode tree. +func ParseWithNativeFlatBuffer(src []byte, tsLangPtr unsafe.Pointer, langName string, symbols []string) (*ASTNode, error) { + if tsLangPtr == nil { + return nil, errors.New("nil native language pointer") + } + + if len(symbols) == 0 { + symbols = NativeLanguageSymbols(tsLangPtr) + } + + var srcPtr *C.uint8_t + if len(src) > 0 { + srcPtr = (*C.uint8_t)(unsafe.Pointer(&src[0])) + } + + res := C.parse_to_flat_ast( + srcPtr, + C.size_t(len(src)), + tsLangPtr, + ) + + if res.error_code != 0 { + return nil, fmt.Errorf("native flat tree-sitter parse failed (code %d)", int(res.error_code)) + } + + // Release the C flat buffer on return, even if ingestion panics. + defer C.free_flat_ast(res) + + var nodes []FlatNode + if res.node_count > 0 && res.nodes_ptr != nil { + nodes = unsafe.Slice((*FlatNode)(unsafe.Pointer(res.nodes_ptr)), int(res.node_count)) + } + + root := IngestFlatAST(nodes, symbols, src, langName) + + return root, nil +} diff --git a/internal/treesitter/bridge_ingest.go b/internal/treesitter/bridge_ingest.go new file mode 100644 index 00000000..fb860b23 --- /dev/null +++ b/internal/treesitter/bridge_ingest.go @@ -0,0 +1,123 @@ +package treesitter + +import ( + "strings" + + "github.com/HarshK97/diffmantic/internal/treesitter/rules" +) + +// IngestFlatAST converts the flat node buffer into a full ASTNode tree, +// applying language rules, labels, and subtree hashes. +func IngestFlatAST(nodes []FlatNode, symbols []string, src []byte, langName string) *ASTNode { + if len(nodes) == 0 { + return nil + } + + r := rules.Get(langName) + srcLen := uint32(len(src)) + + var errCount int + for i := range nodes { + fn := &nodes[i] + var rawType string + if (fn.Flags & FlatNodeError) != 0 { + rawType = "ERROR" + } else if int(fn.TypeID) < len(symbols) { + rawType = symbols[fn.TypeID] + } + if rawType == "ERROR" || (fn.Flags&FlatNodeError != 0) || (fn.Flags&FlatNodeMissing != 0) { + errCount++ + } + } + + root := buildFromIndex(0, nodes, symbols, src, nil, r, srcLen) + if root != nil { + root.Language = langName + root.ParseErrorCount = errCount + root.HasError = errCount > 0 + root.ComputeHashes() + EnsureIndex(root) + } + return root +} + +func buildFromIndex(idx uint32, nodes []FlatNode, symbols []string, src []byte, parent *ASTNode, r *rules.Rules, srcLen uint32) *ASTNode { + if int(idx) >= len(nodes) { + return nil + } + fn := &nodes[idx] + var rawType string + if (fn.Flags & FlatNodeError) != 0 { + rawType = "ERROR" + } else if int(fn.TypeID) < len(symbols) { + rawType = symbols[fn.TypeID] + } + if (fn.Flags & FlatNodeMissing) != 0 { + rawType = "MISSING " + rawType + } + + isLeaf := fn.ChildCount == 0 || (r != nil && r.IsFlattened(rawType)) + var label string + if isLeaf { + start, end := min(fn.StartByte, srcLen), min(fn.EndByte, srcLen) + if start > end { + start = end + } + label = strings.TrimSpace(string(src[start:end])) + } + + if r != nil && r.IsIgnored(rawType, label) { + return nil + } + + node := &ASTNode{ + Type: rawType, + Parent: parent, + StartByte: fn.StartByte, + EndByte: fn.EndByte, + StartRow: fn.StartRow, + StartCol: fn.StartCol, + EndRow: fn.EndRow, + EndCol: fn.EndCol, + } + + if isLeaf { + node.Label = label + } + + if r != nil { + if alias, ok := r.Alias(node.Type, label); ok { + node.Type = alias + } + if r.IsLabelIgnored(node.Type) { + node.Label = "" + } + if isLeaf && r.IsKeyword(node.Type, label) { + node.IsKeyword = true + } + if r.IsUnordered(node.Type) { + node.IsUnordered = true + } + } + + childIdx := fn.FirstChildIdx + for childIdx != 0xFFFFFFFF && int(childIdx) < len(nodes) { + if child := buildFromIndex(childIdx, nodes, symbols, src, node, r, srcLen); child != nil { + node.Children = append(node.Children, child) + } + childIdx = nodes[childIdx].NextSiblingIdx + } + + if r != nil && r.IsFlattened(rawType) { + var flattenedChildren []*ASTNode + for _, child := range node.Children { + flattenedChildren = append(flattenedChildren, child.Children...) + for _, grandchild := range child.Children { + grandchild.Parent = node + } + } + node.Children = flattenedChildren + } + + return node +} diff --git a/internal/treesitter/bridge_test.go b/internal/treesitter/bridge_test.go new file mode 100644 index 00000000..ae396750 --- /dev/null +++ b/internal/treesitter/bridge_test.go @@ -0,0 +1,125 @@ +package treesitter_test + +import ( + "testing" + + "github.com/HarshK97/diffmantic/internal/treesitter" +) + +func TestAll18NativeGrammarsLoaded(t *testing.T) { + langs := []string{ + "c", "cpp", "go", "rust", "python", "javascript", "typescript", "tsx", + "java", "php", "ruby", "lua", "zig", "css", "html", "json", "toml", "yaml", + } + + for _, lang := range langs { + t.Run(lang, func(t *testing.T) { + ptr, err := treesitter.GetNativeLanguage(lang) + if err != nil { + t.Fatalf("failed to get native language for %s: %v", lang, err) + } + if ptr == nil { + t.Fatalf("nil language pointer for %s", lang) + } + symbols := treesitter.NativeLanguageSymbols(ptr) + if len(symbols) == 0 { + t.Fatalf("empty symbols list for %s", lang) + } + }) + } +} + +func TestNativeFlatBufferParsing_AllLanguages(t *testing.T) { + testCases := []struct { + lang string + filename string + src string + }{ + {lang: "c", filename: "main.c", src: "int main(void) { return 0; }"}, + {lang: "cpp", filename: "main.cpp", src: "int main() { return 0; }"}, + {lang: "go", filename: "main.go", src: "package main\nfunc main() {}"}, + {lang: "rust", filename: "main.rs", src: "fn main() {}"}, + {lang: "python", filename: "main.py", src: "def main():\n pass\n"}, + {lang: "javascript", filename: "main.js", src: "function main() {}"}, + {lang: "typescript", filename: "main.ts", src: "function main(): void {}"}, + {lang: "tsx", filename: "main.tsx", src: "const App = () =>
Hello
;"}, + {lang: "java", filename: "Main.java", src: "class Main { public static void main(String[] args) {} }"}, + {lang: "php", filename: "main.php", src: ""}, + {lang: "ruby", filename: "main.rb", src: "def main; puts 'hello'; end"}, + {lang: "lua", filename: "main.lua", src: "function main() print('hello') end"}, + {lang: "zig", filename: "main.zig", src: "pub fn main() void {}"}, + {lang: "css", filename: "style.css", src: "body { color: red; }"}, + {lang: "html", filename: "index.html", src: "Hello"}, + {lang: "json", filename: "data.json", src: "{\"key\": \"value\", \"count\": 42}"}, + {lang: "toml", filename: "config.toml", src: "[server]\nport = 8080\n"}, + {lang: "yaml", filename: "config.yaml", src: "name: diffmantic\nversion: 1.0\n"}, + } + + for _, tc := range testCases { + t.Run(tc.lang, func(t *testing.T) { + ptr, err := treesitter.GetNativeLanguage(tc.lang) + if err != nil { + t.Fatalf("failed to get native language for %s: %v", tc.lang, err) + } + + symbols := treesitter.NativeLanguageSymbols(ptr) + ast, err := treesitter.ParseWithNativeFlatBuffer([]byte(tc.src), ptr, tc.lang, symbols) + if err != nil { + t.Fatalf("native parse error for %s: %v", tc.lang, err) + } + if ast == nil { + t.Fatalf("nil AST for %s", tc.lang) + } + if ast.Size() == 0 { + t.Fatalf("empty AST for %s", tc.lang) + } + if ast.HasError { + t.Errorf("AST has error for %s", tc.lang) + } + }) + } +} + +func TestIngestFlatAST_Synthetic(t *testing.T) { + symbols := []string{"source_file", "function_declaration", "identifier", "block", "{", "}"} + src := []byte("func foo() {}") + + nodes := []treesitter.FlatNode{ + {TypeID: 0, Flags: treesitter.FlatNodeNamed, StartByte: 0, EndByte: 13, FirstChildIdx: 1, NextSiblingIdx: 0xFFFFFFFF, ChildCount: 1}, + {TypeID: 1, Flags: treesitter.FlatNodeNamed, StartByte: 0, EndByte: 13, FirstChildIdx: 2, NextSiblingIdx: 0xFFFFFFFF, ParentIdx: 0, ChildCount: 2}, + {TypeID: 2, Flags: treesitter.FlatNodeNamed, StartByte: 5, EndByte: 8, FirstChildIdx: 0xFFFFFFFF, NextSiblingIdx: 3, ParentIdx: 1, ChildCount: 0}, + {TypeID: 3, Flags: treesitter.FlatNodeNamed, StartByte: 11, EndByte: 13, FirstChildIdx: 0xFFFFFFFF, NextSiblingIdx: 0xFFFFFFFF, ParentIdx: 1, ChildCount: 0}, + } + + root := treesitter.IngestFlatAST(nodes, symbols, src, "go") + if root == nil { + t.Fatalf("root is nil") + } + if root.Type != "source_file" { + t.Errorf("expected Type='source_file', got %q", root.Type) + } + if root.Language != "go" { + t.Errorf("expected Language='go', got %q", root.Language) + } + if len(root.Children) != 1 { + t.Fatalf("expected 1 child, got %d", len(root.Children)) + } + if root.Children[0].Type != "function_declaration" { + t.Errorf("expected function_declaration, got %q", root.Children[0].Type) + } + if len(root.Children[0].Children) != 2 { + t.Fatalf("expected 2 children, got %d", len(root.Children[0].Children)) + } + if root.Children[0].Children[0].Label != "foo" { + t.Errorf("expected label 'foo', got %q", root.Children[0].Children[0].Label) + } + if root.Children[0].Children[0].StartByte != 5 || root.Children[0].Children[0].EndByte != 8 { + t.Errorf("expected byte range [5, 8], got [%d, %d]", root.Children[0].Children[0].StartByte, root.Children[0].Children[0].EndByte) + } + if root.HasError { + t.Errorf("expected HasError=false") + } + if root.ParseErrorCount != 0 { + t.Errorf("expected ParseErrorCount=0, got %d", root.ParseErrorCount) + } +} diff --git a/internal/treesitter/detect.go b/internal/treesitter/detect.go new file mode 100644 index 00000000..cfd7735f --- /dev/null +++ b/internal/treesitter/detect.go @@ -0,0 +1,106 @@ +package treesitter + +import ( + "fmt" + "path/filepath" + "strings" +) + +// Language represents a recognized programming or data language. +type Language struct { + Name string +} + +var extToLang = map[string]string{ + ".go": "go", + ".c": "c", + ".h": "c", + ".cpp": "cpp", + ".cc": "cpp", + ".cxx": "cpp", + ".c++": "cpp", + ".hpp": "cpp", + ".hh": "cpp", + ".hxx": "cpp", + ".h++": "cpp", + ".rs": "rust", + ".py": "python", + ".pyi": "python", + ".js": "javascript", + ".jsx": "javascript", + ".mjs": "javascript", + ".cjs": "javascript", + ".ts": "typescript", + ".mts": "typescript", + ".cts": "typescript", + ".tsx": "tsx", + ".java": "java", + ".php": "php", + ".phtml": "php", + ".php3": "php", + ".php4": "php", + ".php5": "php", + ".php7": "php", + ".phps": "php", + ".rb": "ruby", + ".rake": "ruby", + ".gemspec": "ruby", + ".zig": "zig", + ".lua": "lua", + ".html": "html", + ".htm": "html", + ".css": "css", + ".json": "json", + ".toml": "toml", + ".yaml": "yaml", + ".yml": "yaml", +} + +var basenameToLang = map[string]string{ + "rakefile": "ruby", + "gemfile": "ruby", +} + +// DetectLanguage detects the language for a given filename or path. +func DetectLanguage(filename string) (*Language, error) { + name, err := DetectLanguageName(filename) + if err != nil { + return nil, err + } + return &Language{Name: name}, nil +} + +// DetectLanguageName returns the canonical language name string for a given filename or path. +func DetectLanguageName(filename string) (string, error) { + base := filepath.Base(filename) + lowerBase := strings.ToLower(base) + + if lang, ok := basenameToLang[lowerBase]; ok { + return lang, nil + } + + ext := strings.ToLower(filepath.Ext(base)) + if ext == "" { + return "", fmt.Errorf("unsupported language for file: %s", filename) + } + + if lang, ok := extToLang[ext]; ok { + return lang, nil + } + + // Support compression wrappers (e.g. .json.gz, .go.zst, .yaml.xz) + if ext == ".gz" || ext == ".zst" || ext == ".xz" || ext == ".bz2" { + trimmed := strings.TrimSuffix(lowerBase, ext) + if innerLang, ok := basenameToLang[trimmed]; ok { + return innerLang, nil + } + innerExt := strings.ToLower(filepath.Ext(trimmed)) + if innerExt != "" { + if lang, ok := extToLang[innerExt]; ok { + return lang, nil + } + } + } + + return "", fmt.Errorf("unsupported language for file: %s", filename) +} diff --git a/internal/treesitter/detect_test.go b/internal/treesitter/detect_test.go new file mode 100644 index 00000000..e9ce6abf --- /dev/null +++ b/internal/treesitter/detect_test.go @@ -0,0 +1,51 @@ +package treesitter_test + +import ( + "testing" + + "github.com/HarshK97/diffmantic/internal/treesitter" +) + +func TestDetectLanguageName(t *testing.T) { + tests := []struct { + filename string + want string + wantErr bool + }{ + {"main.go", "go", false}, + {"app.js", "javascript", false}, + {"index.ts", "typescript", false}, + {"component.tsx", "tsx", false}, + {"data.json", "json", false}, + {"config.yaml", "yaml", false}, + {"config.yml", "yaml", false}, + {"Cargo.toml", "toml", false}, + {"main.rs", "rust", false}, + {"script.py", "python", false}, + {"test.cpp", "cpp", false}, + {"header.h", "c", false}, + {"Rakefile", "ruby", false}, + {"Gemfile", "ruby", false}, + // Compound compression wrappers + {"expected_ui.json.gz", "json", false}, + {"archive.go.zst", "go", false}, + {"manifest.yaml.xz", "yaml", false}, + {"Gemfile.gz", "ruby", false}, + // Unsupported + {"file.unknown", "", true}, + {"archive.tar.gz", "", true}, + {"no_ext", "", true}, + } + + for _, tt := range tests { + t.Run(tt.filename, func(t *testing.T) { + got, err := treesitter.DetectLanguageName(tt.filename) + if (err != nil) != tt.wantErr { + t.Fatalf("DetectLanguageName(%q) error = %v, wantErr = %v", tt.filename, err, tt.wantErr) + } + if got != tt.want { + t.Errorf("DetectLanguageName(%q) = %q, want %q", tt.filename, got, tt.want) + } + }) + } +} diff --git a/internal/treesitter/flat_node.go b/internal/treesitter/flat_node.go new file mode 100644 index 00000000..8b4a82a5 --- /dev/null +++ b/internal/treesitter/flat_node.go @@ -0,0 +1,23 @@ +package treesitter + +// FlatNode defines the 44-byte cache-aligned struct matching the C bridge layout. +type FlatNode struct { + TypeID uint16 + Flags uint16 + StartByte uint32 + EndByte uint32 + StartRow uint32 + StartCol uint32 + EndRow uint32 + EndCol uint32 + ParentIdx uint32 + FirstChildIdx uint32 + NextSiblingIdx uint32 + ChildCount uint32 +} + +const ( + FlatNodeNamed = 1 << 0 + FlatNodeError = 1 << 1 + FlatNodeMissing = 1 << 2 +) diff --git a/internal/treesitter/parser.go b/internal/treesitter/parser.go index bd5d9e84..02dcc3a0 100644 --- a/internal/treesitter/parser.go +++ b/internal/treesitter/parser.go @@ -1,45 +1,10 @@ package treesitter -import ( - "errors" - "fmt" - "path/filepath" - - "github.com/odvcencio/gotreesitter" - "github.com/odvcencio/gotreesitter/grammars" -) - -func DetectGrammarEntry(filename string) *grammars.LangEntry { - base := filepath.Base(filename) - return grammars.DetectLanguage(base) -} - -func DetectLanguage(filename string) (*gotreesitter.Language, error) { - entry := DetectGrammarEntry(filename) - if entry == nil { - return nil, fmt.Errorf("unsupported language for file: %s", filename) - } - return entry.Language(), nil -} - -// ParseWithLanguageAndTree parses source bytes and returns both the AST and raw tree-sitter tree. -func ParseWithLanguageAndTree(src []byte, lang *gotreesitter.Language) (*ASTNode, *gotreesitter.Tree, error) { - if lang == nil { - return nil, nil, errors.New("nil language") - } - parser := gotreesitter.NewParser(lang) - tree, err := parser.Parse(src) - if err != nil { - return nil, nil, err - } - return BuildAST(tree.RootNode(), src, lang, nil), tree, nil -} - +// Parse detects the language for the given filename and parses source bytes into an ASTNode. func Parse(src []byte, filename string) (*ASTNode, error) { lang, err := DetectLanguage(filename) if err != nil { return nil, err } - ast, _, err := ParseWithLanguageAndTree(src, lang) - return ast, err + return ParseWithLanguage(src, lang.Name) } diff --git a/internal/treesitter/parser_test.go b/internal/treesitter/parser_test.go index 5600469e..69ad67ef 100644 --- a/internal/treesitter/parser_test.go +++ b/internal/treesitter/parser_test.go @@ -23,19 +23,20 @@ func TestDetectLanguage(t *testing.T) { {"test.cxx", false}, {"test.hh", false}, {"test.h", false}, - {"test.cs", false}, + {"test.cs", true}, {"test.java", false}, {"test.php", false}, {"test.rb", false}, {"test.json", false}, + {"test.toml", false}, {"test.yaml", false}, {"test.yml", false}, {"test.html", false}, {"test.css", false}, {"test.lua", false}, {"test.zig", false}, - {"test.sh", false}, - {"test.bash", false}, + {"test.sh", true}, + {"test.bash", true}, {"test.xyz", true}, {"test", true}, } diff --git a/internal/treesitter/rules/c.go b/internal/treesitter/rules/c.go index bef2121b..591e8e71 100644 --- a/internal/treesitter/rules/c.go +++ b/internal/treesitter/rules/c.go @@ -1,6 +1,7 @@ package rules var cRules = &Rules{ + Kind: KindCode, Flattened: []string{ "string_literal", "char_literal", @@ -155,17 +156,18 @@ var cRules = &Rules{ }, Wrappers: []string{ "parenthesized_expression", + "argument_list", + "parameter_list", "cast_expression", "pointer_expression", "subscript_expression", - "argument_list", - "parameter_list", }, Pairs: []string{ "field_designator", "initializer_pair", }, EquivalentTypes: [][]string{ + {"function_definition", "declaration"}, {"struct_specifier", "union_specifier", "enum_specifier"}, {"for_statement", "while_statement", "do_statement"}, }, @@ -175,4 +177,18 @@ var cRules = &Rules{ Calls: []string{ "call_expression", }, + Indexed: []string{ + "subscript_expression", + }, + ContainerDeclarations: []string{ + "function_definition", + "type_definition", + "struct_specifier", + "union_specifier", + "enum_specifier", + }, + Types: []string{ + "primitive_type", + "type_identifier", + }, } diff --git a/internal/treesitter/rules/cpp.go b/internal/treesitter/rules/cpp.go index 78535a47..b5e64984 100644 --- a/internal/treesitter/rules/cpp.go +++ b/internal/treesitter/rules/cpp.go @@ -1,6 +1,7 @@ package rules var cppRules = &Rules{ + Kind: KindCode, Flattened: []string{ "string_literal", "char_literal", @@ -105,6 +106,7 @@ var cppRules = &Rules{ "declaration", "init_declarator", "field_declaration", + "friend_declaration", "parameter_declaration", "alias_declaration", "using_declaration", @@ -199,6 +201,7 @@ var cppRules = &Rules{ "concept_definition", "parameter_declaration", "field_declaration", + "friend_declaration", }, Identifiers: []string{ "identifier", @@ -210,20 +213,22 @@ var cppRules = &Rules{ }, Wrappers: []string{ "parenthesized_expression", + "argument_list", + "parameter_list", "template_type", "template_argument_list", "subscript_expression", "pointer_expression", "cast_expression", - "argument_list", - "parameter_list", + "friend_declaration", + "template_declaration", }, Pairs: []string{ "field_designator", "initializer_pair", }, EquivalentTypes: [][]string{ - {"function_definition", "template_declaration"}, + {"function_definition", "declaration"}, {"class_specifier", "struct_specifier", "union_specifier", "enum_specifier"}, {"for_statement", "for_range_loop", "while_statement", "do_statement"}, }, @@ -233,4 +238,27 @@ var cppRules = &Rules{ Calls: []string{ "call_expression", }, + Indexed: []string{ + "subscript_expression", + }, + ContainerDeclarations: []string{ + "function_definition", + "type_definition", + "class_specifier", + "struct_specifier", + "union_specifier", + "enum_specifier", + "namespace_definition", + "template_declaration", + }, + Closures: []string{ + "lambda_expression", + }, + Types: []string{ + "dependent_type", + "primitive_type", + "template_type", + "trailing_return_type", + "type_identifier", + }, } diff --git a/internal/treesitter/rules/css.go b/internal/treesitter/rules/css.go index 1ceb8ef5..234cd4eb 100644 --- a/internal/treesitter/rules/css.go +++ b/internal/treesitter/rules/css.go @@ -1,6 +1,7 @@ package rules var cssRules = &Rules{ + Kind: KindMarkup, Flattened: []string{ "plain_value", "color_value", diff --git a/internal/treesitter/rules/go.go b/internal/treesitter/rules/go.go index 29aa4fd3..7ac78819 100644 --- a/internal/treesitter/rules/go.go +++ b/internal/treesitter/rules/go.go @@ -1,6 +1,7 @@ package rules var golangRules = &Rules{ + Kind: KindCode, Flattened: []string{ "interpreted_string_literal", "raw_string_literal", @@ -65,7 +66,6 @@ var golangRules = &Rules{ "parenthesized_expression", "expression_list", "literal_value", - "statement_list", "import_spec_list", "function_declaration", "method_declaration", @@ -128,6 +128,7 @@ var golangRules = &Rules{ Wrappers: []string{ "parenthesized_expression", "parenthesized_type", + "argument_list", "type_arguments", "type_parameter_list", "slice_type", @@ -135,8 +136,8 @@ var golangRules = &Rules{ "index_expression", "slice_expression", "pointer_type", - "argument_list", - "parameter_list", + "expression_list", + "var_declaration", }, Pairs: []string{ "keyed_element", @@ -146,7 +147,7 @@ var golangRules = &Rules{ }, EquivalentTypes: [][]string{ {"function_declaration", "method_declaration"}, - {"var_declaration", "short_var_declaration"}, + {"short_var_declaration", "assignment_statement", "var_spec"}, }, Comments: []string{ "comment", @@ -157,4 +158,38 @@ var golangRules = &Rules{ ScopedDeclarations: []string{ "method_declaration", }, + Indexed: []string{ + "index_expression", + "slice_expression", + }, + LocalVarDeclarations: []string{ + "var_declaration", + "const_declaration", + "short_var_declaration", + }, + ContainerDeclarations: []string{ + "function_declaration", + "method_declaration", + "type_declaration", + "type_spec", + }, + Closures: []string{ + "func_literal", + }, + Types: []string{ + "array_type", + "channel_type", + "function_type", + "generic_type", + "implicit_length_array_type", + "interface_type", + "map_type", + "negated_type", + "parenthesized_type", + "pointer_type", + "qualified_type", + "slice_type", + "struct_type", + "type_identifier", + }, } diff --git a/internal/treesitter/rules/html.go b/internal/treesitter/rules/html.go index 77654961..c8b00c28 100644 --- a/internal/treesitter/rules/html.go +++ b/internal/treesitter/rules/html.go @@ -1,6 +1,7 @@ package rules var htmlRules = &Rules{ + Kind: KindMarkup, Flattened: []string{ "text", "raw_text", diff --git a/internal/treesitter/rules/java.go b/internal/treesitter/rules/java.go index 3204c00d..a3380ab0 100644 --- a/internal/treesitter/rules/java.go +++ b/internal/treesitter/rules/java.go @@ -1,6 +1,7 @@ package rules var javaRules = &Rules{ + Kind: KindCode, Flattened: []string{ "string_literal", "character_literal", @@ -182,13 +183,13 @@ var javaRules = &Rules{ }, Wrappers: []string{ "parenthesized_expression", + "argument_list", + "formal_parameters", "type_arguments", "type_parameters", "array_type", "generic_type", "cast_expression", - "argument_list", - "formal_parameters", }, Pairs: []string{ "element_value_pair", @@ -209,4 +210,33 @@ var javaRules = &Rules{ "method_invocation", "explicit_constructor_invocation", }, + Indexed: []string{ + "array_access", + }, + LocalVarDeclarations: []string{ + "local_variable_declaration", + }, + ContainerDeclarations: []string{ + "class_declaration", + "interface_declaration", + "enum_declaration", + "record_declaration", + "method_declaration", + "constructor_declaration", + }, + Closures: []string{ + "lambda_expression", + }, + Types: []string{ + "annotated_type", + "array_type", + "boolean_type", + "catch_type", + "floating_point_type", + "generic_type", + "integral_type", + "scoped_type_identifier", + "type_identifier", + "void_type", + }, } diff --git a/internal/treesitter/rules/javascript.go b/internal/treesitter/rules/javascript.go index a1f7c586..1f4932e4 100644 --- a/internal/treesitter/rules/javascript.go +++ b/internal/treesitter/rules/javascript.go @@ -1,6 +1,7 @@ package rules var javascriptRules = &Rules{ + Kind: KindCode, Flattened: []string{ "string", "template_string", @@ -80,7 +81,6 @@ var javascriptRules = &Rules{ "expression_statement", "variable_declaration", "lexical_declaration", - "using_declaration", "variable_declarator", "function_declaration", "function_expression", @@ -172,8 +172,9 @@ var javascriptRules = &Rules{ "statement_block", }, Wrappers: []string{ + "export_statement", "parenthesized_expression", - "subscript_expression", + "object", "array", "array_pattern", "object_pattern", @@ -187,6 +188,8 @@ var javascriptRules = &Rules{ Unordered: []string{ "object", "object_pattern", + "named_imports", + "export_clause", }, EquivalentTypes: [][]string{ {"function_declaration", "function_expression", "arrow_function", "generator_function_declaration", "generator_function"}, @@ -200,4 +203,22 @@ var javascriptRules = &Rules{ Calls: []string{ "call_expression", }, + Indexed: []string{ + "subscript_expression", + }, + LocalVarDeclarations: []string{ + "variable_declaration", + "lexical_declaration", + }, + ContainerDeclarations: []string{ + "function_declaration", + "generator_function_declaration", + "method_definition", + "class_declaration", + }, + Closures: []string{ + "arrow_function", + "function_expression", + "function", + }, } diff --git a/internal/treesitter/rules/json.go b/internal/treesitter/rules/json.go index 160f0433..16f5b6a1 100644 --- a/internal/treesitter/rules/json.go +++ b/internal/treesitter/rules/json.go @@ -1,6 +1,7 @@ package rules var jsonRules = &Rules{ + Kind: KindData, Flattened: []string{ "string", }, @@ -26,6 +27,10 @@ var jsonRules = &Rules{ Pairs: []string{ "pair", }, + Wrappers: []string{ + "array", + "object", + }, Unordered: []string{ "object", }, diff --git a/internal/treesitter/rules/lua.go b/internal/treesitter/rules/lua.go index 1e759c04..c09209e7 100644 --- a/internal/treesitter/rules/lua.go +++ b/internal/treesitter/rules/lua.go @@ -1,6 +1,7 @@ package rules var luaRules = &Rules{ + Kind: KindCode, Flattened: []string{ "string", }, @@ -110,7 +111,6 @@ var luaRules = &Rules{ Wrappers: []string{ "parenthesized_expression", "table_constructor", - "bracket_index_expression", "dot_index_expression", "method_index_expression", "arguments", @@ -131,4 +131,16 @@ var luaRules = &Rules{ Calls: []string{ "function_call", }, + Indexed: []string{ + "bracket_index_expression", + }, + LocalVarDeclarations: []string{ + "variable_declaration", + }, + ContainerDeclarations: []string{ + "function_declaration", + }, + Closures: []string{ + "function_definition", + }, } diff --git a/internal/treesitter/rules/php.go b/internal/treesitter/rules/php.go index c331e364..3572e3cd 100644 --- a/internal/treesitter/rules/php.go +++ b/internal/treesitter/rules/php.go @@ -1,6 +1,7 @@ package rules var phpRules = &Rules{ + Kind: KindCode, Flattened: []string{ "string", "encapsed_string", @@ -200,4 +201,32 @@ var phpRules = &Rules{ "scoped_call_expression", "nullsafe_member_call_expression", }, + Indexed: []string{ + "subscript_expression", + }, + LocalVarDeclarations: []string{ + "const_declaration", + }, + ContainerDeclarations: []string{ + "function_definition", + "method_declaration", + "class_declaration", + "interface_declaration", + "trait_declaration", + "enum_declaration", + }, + Closures: []string{ + "anonymous_function", + "arrow_function", + }, + Types: []string{ + "bottom_type", + "cast_type", + "disjunctive_normal_form_type", + "intersection_type", + "named_type", + "optional_type", + "primitive_type", + "union_type", + }, } diff --git a/internal/treesitter/rules/python.go b/internal/treesitter/rules/python.go index b494667d..d97e6d26 100644 --- a/internal/treesitter/rules/python.go +++ b/internal/treesitter/rules/python.go @@ -1,6 +1,7 @@ package rules var pythonRules = &Rules{ + Kind: KindCode, Flattened: []string{ "string", "concatenated_string", @@ -80,7 +81,6 @@ var pythonRules = &Rules{ "expression_statement", "expression_list", "pattern_list", - "tuple_expression", "list", "dictionary", "set", @@ -157,7 +157,8 @@ var pythonRules = &Rules{ }, Wrappers: []string{ "parenthesized_expression", - "subscript", + "argument_list", + "parameters", "list", "tuple", "set", @@ -166,8 +167,6 @@ var pythonRules = &Rules{ "list_comprehension", "dictionary_comprehension", "set_comprehension", - "argument_list", - "parameters", }, Pairs: []string{ "pair", @@ -187,4 +186,21 @@ var pythonRules = &Rules{ Calls: []string{ "call", }, + Indexed: []string{ + "subscript", + }, + ContainerDeclarations: []string{ + "function_definition", + "class_definition", + }, + Closures: []string{ + "lambda", + }, + Types: []string{ + "constrained_type", + "generic_type", + "member_type", + "splat_type", + "union_type", + }, } diff --git a/internal/treesitter/rules/ruby.go b/internal/treesitter/rules/ruby.go index 8cca0a4e..219bb24a 100644 --- a/internal/treesitter/rules/ruby.go +++ b/internal/treesitter/rules/ruby.go @@ -1,6 +1,7 @@ package rules var rubyRules = &Rules{ + Kind: KindCode, Flattened: []string{ "string", "string_content", @@ -154,14 +155,18 @@ var rubyRules = &Rules{ "constant", }, Blocks: []string{ + "body_statement", + "do_block", "block", }, Wrappers: []string{ "parenthesized_statements", + "argument_list", "array", "element_reference", - "argument_list", - "method_parameters", + "do_block", + "hash", + "hash_pattern", }, Pairs: []string{ "pair", @@ -173,7 +178,7 @@ var rubyRules = &Rules{ EquivalentTypes: [][]string{ {"method", "singleton_method"}, {"class", "module", "singleton_class"}, - {"if", "unless"}, + {"if", "unless", "if_modifier", "unless_modifier"}, {"while", "until", "for"}, }, Comments: []string{ @@ -182,4 +187,18 @@ var rubyRules = &Rules{ Calls: []string{ "call", }, + Indexed: []string{ + "element_reference", + }, + ContainerDeclarations: []string{ + "method", + "singleton_method", + "class", + "module", + }, + Closures: []string{ + "do_block", + "block", + "lambda", + }, } diff --git a/internal/treesitter/rules/rules.go b/internal/treesitter/rules/rules.go index 4801e329..23f66082 100644 --- a/internal/treesitter/rules/rules.go +++ b/internal/treesitter/rules/rules.go @@ -5,39 +5,63 @@ import ( "strings" ) +// LanguageKind classifies grammars into high-level parsing and diffing categories. +type LanguageKind uint8 + +const ( + // KindCode is for general programming languages (Go, Rust, Python, C++, etc.). + KindCode LanguageKind = iota + // KindData is for structured key-value formats (JSON, YAML, TOML). + KindData + // KindMarkup is for markup and styling languages (HTML, CSS). + KindMarkup +) + // Rules configures language-specific AST transformations and node matching. type Rules struct { - Flattened []string - Ignored []string - Aliased map[string]string - LabelIgnored []string - Scaffolding []string - Keywords []string - Declarations []string - Identifiers []string - Blocks []string - Wrappers []string - Pairs []string - Unordered []string - EquivalentTypes [][]string - Comments []string - Calls []string - ScopedDeclarations []string - - flattenedSet map[string]struct{} - ignoredSet map[string]struct{} - labelIgnoredSet map[string]struct{} - keywordsSet map[string]struct{} - declarationsSet map[string]struct{} - identifiersSet map[string]struct{} - scaffoldingSet map[string]struct{} - blocksSet map[string]struct{} - wrappersSet map[string]struct{} - unorderedSet map[string]struct{} - commentsSet map[string]struct{} - callsSet map[string]struct{} - scopedDeclarationsSet map[string]struct{} - equivGroups map[string][]int + Kind LanguageKind + Flattened []string + Ignored []string + Aliased map[string]string + LabelIgnored []string + Scaffolding []string + Keywords []string + Declarations []string + Identifiers []string + Blocks []string + Wrappers []string + Pairs []string + Unordered []string + EquivalentTypes [][]string + Comments []string + Calls []string + ScopedDeclarations []string + Indexed []string // Subscript nodes with prefix receivers (e.g. arr[i]). + LocalVarDeclarations []string + ContainerDeclarations []string // Major declaration scope boundaries (functions, classes, structs, etc.). + Closures []string // Anonymous functions, lambdas, and callbacks. + Types []string // Type annotations and type expressions. + + flattenedSet map[string]struct{} + ignoredSet map[string]struct{} + labelIgnoredSet map[string]struct{} + keywordsSet map[string]struct{} + declarationsSet map[string]struct{} + identifiersSet map[string]struct{} + scaffoldingSet map[string]struct{} + blocksSet map[string]struct{} + wrappersSet map[string]struct{} + pairsSet map[string]struct{} + unorderedSet map[string]struct{} + commentsSet map[string]struct{} + callsSet map[string]struct{} + scopedDeclarationsSet map[string]struct{} + indexedSet map[string]struct{} + localVarDeclarationsSet map[string]struct{} + containerDeclarationsSet map[string]struct{} + closuresSet map[string]struct{} + typesSet map[string]struct{} + equivGroups map[string][]int } // CompileSets builds the internal lookup sets for fast querying. @@ -96,6 +120,12 @@ func (r *Rules) CompileSets() { r.wrappersSet[s] = struct{}{} } } + if len(r.Pairs) > 0 { + r.pairsSet = make(map[string]struct{}, len(r.Pairs)) + for _, s := range r.Pairs { + r.pairsSet[s] = struct{}{} + } + } if len(r.Unordered) > 0 { r.unorderedSet = make(map[string]struct{}, len(r.Unordered)) for _, s := range r.Unordered { @@ -120,6 +150,36 @@ func (r *Rules) CompileSets() { r.scopedDeclarationsSet[s] = struct{}{} } } + if len(r.Indexed) > 0 { + r.indexedSet = make(map[string]struct{}, len(r.Indexed)) + for _, s := range r.Indexed { + r.indexedSet[s] = struct{}{} + } + } + if len(r.LocalVarDeclarations) > 0 { + r.localVarDeclarationsSet = make(map[string]struct{}, len(r.LocalVarDeclarations)) + for _, s := range r.LocalVarDeclarations { + r.localVarDeclarationsSet[s] = struct{}{} + } + } + if len(r.ContainerDeclarations) > 0 { + r.containerDeclarationsSet = make(map[string]struct{}, len(r.ContainerDeclarations)) + for _, s := range r.ContainerDeclarations { + r.containerDeclarationsSet[s] = struct{}{} + } + } + if len(r.Closures) > 0 { + r.closuresSet = make(map[string]struct{}, len(r.Closures)) + for _, s := range r.Closures { + r.closuresSet[s] = struct{}{} + } + } + if len(r.Types) > 0 { + r.typesSet = make(map[string]struct{}, len(r.Types)) + for _, s := range r.Types { + r.typesSet[s] = struct{}{} + } + } if len(r.EquivalentTypes) > 0 { r.equivGroups = make(map[string][]int) for idx, group := range r.EquivalentTypes { @@ -130,6 +190,14 @@ func (r *Rules) CompileSets() { } } +// GetKind returns the language category (KindCode, KindData, or KindMarkup). +func (r *Rules) GetKind() LanguageKind { + if r == nil { + return KindCode + } + return r.Kind +} + // IsCall reports whether nodeType is a function, method, or macro invocation. func (r *Rules) IsCall(nodeType string) bool { if r == nil || nodeType == "" { @@ -142,6 +210,18 @@ func (r *Rules) IsCall(nodeType string) bool { return slices.Contains(r.Calls, nodeType) } +// IsIndexed reports whether nodeType is a subscript container with a prefix receiver. +func (r *Rules) IsIndexed(nodeType string) bool { + if r == nil || nodeType == "" { + return false + } + if len(r.indexedSet) > 0 { + _, ok := r.indexedSet[nodeType] + return ok + } + return slices.Contains(r.Indexed, nodeType) +} + // IsComment reports whether nodeType is a comment in the language grammar. func (r *Rules) IsComment(nodeType string) bool { if r == nil || nodeType == "" { @@ -178,6 +258,55 @@ func (r *Rules) IsScopedDeclaration(nodeType string) bool { return slices.Contains(r.ScopedDeclarations, nodeType) } +// IsLocalVarDeclaration reports whether nodeType is a local variable declaration. +func (r *Rules) IsLocalVarDeclaration(nodeType string) bool { + if r == nil || nodeType == "" { + return false + } + if len(r.localVarDeclarationsSet) > 0 { + _, ok := r.localVarDeclarationsSet[nodeType] + return ok + } + return slices.Contains(r.LocalVarDeclarations, nodeType) +} + +// IsContainerDeclaration reports whether nodeType is a major container declaration +// (such as a function, method, class, struct, interface, trait, or enum). +func (r *Rules) IsContainerDeclaration(nodeType string) bool { + if r == nil || nodeType == "" { + return false + } + if len(r.containerDeclarationsSet) > 0 { + _, ok := r.containerDeclarationsSet[nodeType] + return ok + } + return slices.Contains(r.ContainerDeclarations, nodeType) +} + +// IsClosure reports whether nodeType is an anonymous function, closure, or lambda callback. +func (r *Rules) IsClosure(nodeType string) bool { + if r == nil || nodeType == "" { + return false + } + if len(r.closuresSet) > 0 { + _, ok := r.closuresSet[nodeType] + return ok + } + return slices.Contains(r.Closures, nodeType) +} + +// IsType reports whether nodeType is a type annotation or type expression in the language. +func (r *Rules) IsType(nodeType string) bool { + if r == nil || nodeType == "" { + return false + } + if len(r.typesSet) > 0 { + _, ok := r.typesSet[nodeType] + return ok + } + return slices.Contains(r.Types, nodeType) +} + // IsIdentifier reports whether nodeType is an identifier token. func (r *Rules) IsIdentifier(nodeType string) bool { if r == nil || nodeType == "" { @@ -281,6 +410,18 @@ func (r *Rules) IsLabelIgnored(nodeType string) bool { return slices.Contains(r.LabelIgnored, nodeType) } +// IsPair checks if nodeType represents a key-value property pair. +func (r *Rules) IsPair(nodeType string) bool { + if r == nil { + return false + } + if len(r.pairsSet) > 0 { + _, ok := r.pairsSet[nodeType] + return ok + } + return slices.Contains(r.Pairs, nodeType) +} + // IsUnordered checks if child order doesn't matter for this container. func (r *Rules) IsUnordered(nodeType string) bool { if r == nil { @@ -412,6 +553,16 @@ func IsDeclaration(nodeType string) bool { return false } +// IsLocalVarDeclaration reports whether nodeType is configured as a local variable declaration in any language rule set. +func IsLocalVarDeclaration(nodeType string) bool { + for _, r := range registry { + if r.IsLocalVarDeclaration(nodeType) { + return true + } + } + return false +} + // IsIdentifier reports whether nodeType is configured as an identifier in any language rule set. func IsIdentifier(nodeType string) bool { for _, r := range registry { @@ -467,6 +618,32 @@ func IsKeyword(nodeType, label string) bool { return false } +// IsPunctuation reports whether a string is a structural punctuation token (braces, brackets, parentheses, delimiters). +func (r *Rules) IsPunctuation(token string) bool { + switch token { + case "}", "};", "],", "]", ")", ");", "},", "{", "begin", "end", ";", ",", "(", "[", ":", "->", "=>", "\"", "'", "`": + return true + } + if r == nil || token == "" { + return false + } + return r.IsIgnored(token, token) || r.IsDelimiter(token, token) +} + +// IsPunctuation reports whether a string is a structural punctuation token in any language rule set. +func IsPunctuation(token string) bool { + switch token { + case "}", "};", "],", "]", ")", ");", "},", "{", "begin", "end", ";", ",", "(", "[", ":", "->", "=>", "\"", "'", "`": + return true + } + for _, r := range registry { + if r.IsPunctuation(token) { + return true + } + } + return false +} + // IsDelimiter reports whether nodeType or label is a delimiter token (semicolon or comma). func IsDelimiter(nodeType, label string) bool { return label == ";" || label == "," || nodeType == "semicolon" || nodeType == "comma" || nodeType == "_automatic_semicolon" @@ -482,6 +659,55 @@ func IsCall(nodeType string) bool { return false } +// IsIndexed reports whether nodeType is configured as an indexed container in any language rule set. +func IsIndexed(nodeType string) bool { + for _, r := range registry { + if r.IsIndexed(nodeType) { + return true + } + } + return false +} + +// IsContainerDeclaration reports whether nodeType is configured as a container declaration in any language rule set. +func IsContainerDeclaration(nodeType string) bool { + if nodeType == "" { + return false + } + for _, r := range registry { + if r.IsContainerDeclaration(nodeType) { + return true + } + } + return false +} + +// IsClosure reports whether nodeType is configured as a closure in any language rule set. +func IsClosure(nodeType string) bool { + if nodeType == "" { + return false + } + for _, r := range registry { + if r.IsClosure(nodeType) { + return true + } + } + return false +} + +// IsType reports whether nodeType is a type annotation or type expression in any language rule set. +func IsType(nodeType string) bool { + if nodeType == "" { + return false + } + for _, r := range registry { + if r.IsType(nodeType) { + return true + } + } + return false +} + var registry = map[string]*Rules{ "c": cRules, "cpp": cppRules, diff --git a/internal/treesitter/rules/rules_grammar_test.go b/internal/treesitter/rules/rules_grammar_test.go index 1fe0c06e..432b12f0 100644 --- a/internal/treesitter/rules/rules_grammar_test.go +++ b/internal/treesitter/rules/rules_grammar_test.go @@ -3,72 +3,73 @@ package rules_test import ( "testing" + "github.com/HarshK97/diffmantic/internal/treesitter" "github.com/HarshK97/diffmantic/internal/treesitter/rules" - "github.com/odvcencio/gotreesitter/grammars" ) func TestAllLanguageRulesMatchGrammarSymbols(t *testing.T) { langs := []struct { - name string - filename string + name string }{ - {"c", "main.c"}, - {"cpp", "main.cpp"}, - {"go", "main.go"}, - {"rust", "main.rs"}, - {"python", "main.py"}, - {"javascript", "main.js"}, - {"typescript", "main.ts"}, - {"tsx", "main.tsx"}, - {"java", "Main.java"}, - {"php", "main.php"}, - {"ruby", "main.rb"}, - {"lua", "main.lua"}, - {"zig", "main.zig"}, - {"css", "style.css"}, - {"html", "index.html"}, - {"json", "data.json"}, - {"toml", "config.toml"}, - {"yaml", "config.yaml"}, + {"c"}, + {"cpp"}, + {"go"}, + {"rust"}, + {"python"}, + {"javascript"}, + {"typescript"}, + {"tsx"}, + {"java"}, + {"php"}, + {"ruby"}, + {"lua"}, + {"zig"}, + {"css"}, + {"html"}, + {"json"}, + {"toml"}, + {"yaml"}, } for _, l := range langs { - t.Run(l.name, func(t *testing.T) { - entry := grammars.DetectLanguage(l.filename) - if entry == nil { - t.Fatalf("Failed to detect language grammar for %s", l.name) - } - lang := entry.Language() + ptr, err := treesitter.GetNativeLanguage(l.name) + if err != nil || ptr == nil { + t.Fatalf("Failed to get native language for %s: %v", l.name, err) + } - grammarSymbols := make(map[string]bool) - for i, meta := range lang.SymbolMetadata { - name := "" - if i < len(lang.SymbolNames) { - name = lang.SymbolNames[i] - } - if meta.Named && name != "" { - grammarSymbols[name] = true - } + symbols := treesitter.NativeLanguageSymbols(ptr) + grammarSymbols := make(map[string]bool, len(symbols)) + for _, s := range symbols { + if s != "" { + grammarSymbols[s] = true } + } - r := rules.Get(l.name) - if r == nil { - return - } + r := rules.Get(l.name) + if r == nil { + continue + } - checkField := func(fieldName string, items []string) { - for _, item := range items { - if !grammarSymbols[item] { - t.Errorf("[%s] %s item %q does NOT exist in gotreesitter grammar", l.name, fieldName, item) - } + checkField := func(fieldName string, items []string) { + for _, item := range items { + if !grammarSymbols[item] { + t.Errorf("[%s] %s item %q does NOT exist in native grammar", l.name, fieldName, item) } } + } - checkField("Declarations", r.Declarations) - checkField("Blocks", r.Blocks) - checkField("Scaffolding", r.Scaffolding) - checkField("Wrappers", r.Wrappers) - checkField("Pairs", r.Pairs) - }) + checkField("Declarations", r.Declarations) + checkField("Blocks", r.Blocks) + checkField("Scaffolding", r.Scaffolding) + checkField("Wrappers", r.Wrappers) + checkField("Pairs", r.Pairs) + checkField("Indexed", r.Indexed) + checkField("Unordered", r.Unordered) + checkField("Comments", r.Comments) + checkField("Calls", r.Calls) + checkField("LocalVarDeclarations", r.LocalVarDeclarations) + checkField("ContainerDeclarations", r.ContainerDeclarations) + checkField("Closures", r.Closures) + checkField("Types", r.Types) } } diff --git a/internal/treesitter/rules/rules_test.go b/internal/treesitter/rules/rules_test.go index da52f0f6..00284816 100644 --- a/internal/treesitter/rules/rules_test.go +++ b/internal/treesitter/rules/rules_test.go @@ -252,6 +252,8 @@ func TestRulesHelperMethods(t *testing.T) { Unordered: []string{"object", "hash"}, Flattened: []string{"string_literal"}, Blocks: []string{"block", "compound_statement"}, + Calls: []string{"call_expression"}, + Indexed: []string{"subscript_expression", "index_expression"}, EquivalentTypes: [][]string{ {"function_declaration", "function_definition", "variable_declaration"}, {"assignment_statement", "variable_declaration"}, @@ -311,6 +313,20 @@ func TestRulesHelperMethods(t *testing.T) { t.Errorf("IsBlock(other) = true, want false") } + if !r.IsCall("call_expression") { + t.Errorf("IsCall(call_expression) = false, want true") + } + if r.IsCall("other") { + t.Errorf("IsCall(other) = true, want false") + } + + if !r.IsIndexed("subscript_expression") || !r.IsIndexed("index_expression") { + t.Errorf("IsIndexed(subscript_expression/index_expression) = false, want true") + } + if r.IsIndexed("other") { + t.Errorf("IsIndexed(other) = true, want false") + } + if !r.AreTypesEquivalent("function_declaration", "variable_declaration") { t.Errorf("AreTypesEquivalent(function_declaration, variable_declaration) = false, want true") } @@ -353,6 +369,12 @@ func TestRulesHelperMethods(t *testing.T) { if !r.IsBlock("compound_statement") || r.IsBlock("other") { t.Errorf("IsBlock uncompiled fallback failed") } + if !r.IsCall("call_expression") || r.IsCall("other") { + t.Errorf("IsCall uncompiled fallback failed") + } + if !r.IsIndexed("subscript_expression") || r.IsIndexed("other") { + t.Errorf("IsIndexed uncompiled fallback failed") + } if !r.AreTypesEquivalent("function_declaration", "variable_declaration") { t.Errorf("AreTypesEquivalent uncompiled fallback failed") } @@ -381,6 +403,12 @@ func TestRulesHelperMethods(t *testing.T) { if r.IsBlock("a") { t.Errorf("nil.IsBlock returned true") } + if r.IsCall("a") { + t.Errorf("nil.IsCall returned true") + } + if r.IsIndexed("a") { + t.Errorf("nil.IsIndexed returned true") + } if !r.AreTypesEquivalent("a", "a") { t.Errorf("nil.AreTypesEquivalent(a, a) returned false, want true") } @@ -405,7 +433,7 @@ func TestRulesHelperMethods(t *testing.T) { } }) - t.Run("package-level IsFlattened", func(t *testing.T) { + t.Run("package-level helpers", func(t *testing.T) { if !IsFlattened("raw_string_literal") { t.Errorf("IsFlattened(raw_string_literal) = false, want true") } @@ -415,6 +443,18 @@ func TestRulesHelperMethods(t *testing.T) { if IsFlattened("") { t.Errorf("IsFlattened(\"\") = true, want false") } + if !IsCall("call_expression") { + t.Errorf("IsCall(call_expression) = false, want true") + } + if IsCall("nonexistent_call_xyz") { + t.Errorf("IsCall(nonexistent_call_xyz) = true, want false") + } + if !IsIndexed("subscript_expression") || !IsIndexed("index_expression") { + t.Errorf("IsIndexed(subscript_expression) = false, want true") + } + if IsIndexed("nonexistent_indexed_xyz") { + t.Errorf("IsIndexed(nonexistent_indexed_xyz) = true, want false") + } }) } @@ -469,3 +509,45 @@ func TestRulesIsOperatorLiteral(t *testing.T) { } } } + +func TestLanguageKind(t *testing.T) { + expectedKinds := map[string]LanguageKind{ + "c": KindCode, + "cpp": KindCode, + "go": KindCode, + "rust": KindCode, + "python": KindCode, + "javascript": KindCode, + "typescript": KindCode, + "tsx": KindCode, + "java": KindCode, + "php": KindCode, + "ruby": KindCode, + "lua": KindCode, + "zig": KindCode, + "json": KindData, + "yaml": KindData, + "toml": KindData, + "html": KindMarkup, + "css": KindMarkup, + } + + for lang, expected := range expectedKinds { + r := Get(lang) + if r == nil { + t.Errorf("Get(%q) returned nil", lang) + continue + } + if r.GetKind() != expected { + t.Errorf("Get(%q).GetKind() = %v, want %v", lang, r.GetKind(), expected) + } + if r.Kind != expected { + t.Errorf("Get(%q).Kind = %v, want %v", lang, r.Kind, expected) + } + } + + var nilRules *Rules + if nilRules.GetKind() != KindCode { + t.Errorf("nil.GetKind() = %v, want KindCode", nilRules.GetKind()) + } +} diff --git a/internal/treesitter/rules/rust.go b/internal/treesitter/rules/rust.go index a05cbaf7..9e9d055c 100644 --- a/internal/treesitter/rules/rust.go +++ b/internal/treesitter/rules/rust.go @@ -1,6 +1,7 @@ package rules var rustRules = &Rules{ + Kind: KindCode, Flattened: []string{ "string_literal", "raw_string_literal", @@ -182,4 +183,42 @@ var rustRules = &Rules{ "call_expression", "macro_invocation", }, + Indexed: []string{ + "index_expression", + }, + LocalVarDeclarations: []string{ + "let_declaration", + }, + ContainerDeclarations: []string{ + "function_item", + "struct_item", + "enum_item", + "union_item", + "trait_item", + "impl_item", + "mod_item", + "type_item", + }, + Closures: []string{ + "closure_expression", + }, + Types: []string{ + "abstract_type", + "array_type", + "associated_type", + "bounded_type", + "bracketed_type", + "dynamic_type", + "function_type", + "generic_type", + "never_type", + "pointer_type", + "primitive_type", + "qualified_type", + "reference_type", + "scoped_type_identifier", + "tuple_type", + "type_identifier", + "unit_type", + }, } diff --git a/internal/treesitter/rules/toml.go b/internal/treesitter/rules/toml.go index 11a104a2..702c118b 100644 --- a/internal/treesitter/rules/toml.go +++ b/internal/treesitter/rules/toml.go @@ -1,6 +1,7 @@ package rules var tomlRules = &Rules{ + Kind: KindData, Flattened: []string{ "string", "offset_date_time", @@ -47,6 +48,10 @@ var tomlRules = &Rules{ EquivalentTypes: [][]string{ {"table", "inline_table"}, }, + Wrappers: []string{ + "array", + "inline_table", + }, Comments: []string{ "comment", }, diff --git a/internal/treesitter/rules/tsx.go b/internal/treesitter/rules/tsx.go index 20b38845..452f6617 100644 --- a/internal/treesitter/rules/tsx.go +++ b/internal/treesitter/rules/tsx.go @@ -1,6 +1,7 @@ package rules var tsxRules = &Rules{ + Kind: KindCode, Flattened: []string{ "string", "template_string", @@ -186,13 +187,14 @@ var tsxRules = &Rules{ "statement_block", }, Wrappers: []string{ + "export_statement", "parenthesized_expression", "parenthesized_type", "type_arguments", "type_parameters", "array_type", "generic_type", - "subscript_expression", + "object", "array", "arguments", "formal_parameters", @@ -209,6 +211,8 @@ var tsxRules = &Rules{ "jsx_opening_element", "jsx_self_closing_element", "object_pattern", + "named_imports", + "export_clause", }, EquivalentTypes: [][]string{ {"function_declaration", "function_expression", "arrow_function", "generator_function_declaration", "generator_function"}, @@ -225,4 +229,54 @@ var tsxRules = &Rules{ Calls: []string{ "call_expression", }, + Indexed: []string{ + "subscript_expression", + }, + LocalVarDeclarations: []string{ + "variable_declaration", + "lexical_declaration", + }, + ContainerDeclarations: []string{ + "function_declaration", + "generator_function_declaration", + "method_definition", + "class_declaration", + "interface_declaration", + "type_alias_declaration", + "enum_declaration", + "module", + }, + Closures: []string{ + "arrow_function", + "function_expression", + "function", + }, + Types: []string{ + "array_type", + "conditional_type", + "constructor_type", + "default_type", + "existential_type", + "flow_maybe_type", + "function_type", + "generic_type", + "infer_type", + "intersection_type", + "literal_type", + "lookup_type", + "nested_type_identifier", + "object_type", + "optional_type", + "parenthesized_type", + "predefined_type", + "primary_type", + "readonly_type", + "rest_type", + "template_literal_type", + "template_type", + "this_type", + "tuple_type", + "type_identifier", + "union_type", + }, } diff --git a/internal/treesitter/rules/typescript.go b/internal/treesitter/rules/typescript.go index e5b15246..abbae2ea 100644 --- a/internal/treesitter/rules/typescript.go +++ b/internal/treesitter/rules/typescript.go @@ -1,6 +1,7 @@ package rules var typescriptRules = &Rules{ + Kind: KindCode, Flattened: []string{ "string", "template_string", @@ -178,13 +179,14 @@ var typescriptRules = &Rules{ "statement_block", }, Wrappers: []string{ + "export_statement", "parenthesized_expression", "parenthesized_type", "type_arguments", "type_parameters", "array_type", "generic_type", - "subscript_expression", + "object", "array", "arguments", "formal_parameters", @@ -198,6 +200,8 @@ var typescriptRules = &Rules{ "object", "object_type", "object_pattern", + "named_imports", + "export_clause", }, EquivalentTypes: [][]string{ {"function_declaration", "function_expression", "arrow_function", "generator_function_declaration", "generator_function"}, @@ -213,4 +217,54 @@ var typescriptRules = &Rules{ Calls: []string{ "call_expression", }, + Indexed: []string{ + "subscript_expression", + }, + LocalVarDeclarations: []string{ + "variable_declaration", + "lexical_declaration", + }, + ContainerDeclarations: []string{ + "function_declaration", + "generator_function_declaration", + "method_definition", + "class_declaration", + "interface_declaration", + "type_alias_declaration", + "enum_declaration", + "module", + }, + Closures: []string{ + "arrow_function", + "function_expression", + "function", + }, + Types: []string{ + "array_type", + "conditional_type", + "constructor_type", + "default_type", + "existential_type", + "flow_maybe_type", + "function_type", + "generic_type", + "infer_type", + "intersection_type", + "literal_type", + "lookup_type", + "nested_type_identifier", + "object_type", + "optional_type", + "parenthesized_type", + "predefined_type", + "primary_type", + "readonly_type", + "rest_type", + "template_literal_type", + "template_type", + "this_type", + "tuple_type", + "type_identifier", + "union_type", + }, } diff --git a/internal/treesitter/rules/yaml.go b/internal/treesitter/rules/yaml.go index 98e70c71..683dcb08 100644 --- a/internal/treesitter/rules/yaml.go +++ b/internal/treesitter/rules/yaml.go @@ -1,6 +1,7 @@ package rules var yamlRules = &Rules{ + Kind: KindData, Flattened: []string{ "string_scalar", "double_quote_scalar", @@ -57,5 +58,7 @@ var yamlRules = &Rules{ Wrappers: []string{ "block_node", "flow_node", + "flow_sequence", + "flow_mapping", }, } diff --git a/internal/treesitter/rules/zig.go b/internal/treesitter/rules/zig.go index 6755723b..ad562e51 100644 --- a/internal/treesitter/rules/zig.go +++ b/internal/treesitter/rules/zig.go @@ -1,6 +1,7 @@ package rules var zigRules = &Rules{ + Kind: KindCode, Flattened: []string{ "string", "multiline_string", @@ -155,4 +156,29 @@ var zigRules = &Rules{ Calls: []string{ "call_expression", }, + Indexed: []string{ + "index_expression", + }, + LocalVarDeclarations: []string{ + "variable_declaration", + }, + ContainerDeclarations: []string{ + "function_declaration", + "struct_declaration", + "enum_declaration", + "union_declaration", + "opaque_declaration", + "error_set_declaration", + "test_declaration", + }, + Types: []string{ + "anyframe_type", + "array_type", + "builtin_type", + "error_type", + "error_union_type", + "nullable_type", + "pointer_type", + "slice_type", + }, } diff --git a/internal/treesitter/rules_symbol_test.go b/internal/treesitter/rules_symbol_test.go index 19317dd7..ef48aa77 100644 --- a/internal/treesitter/rules_symbol_test.go +++ b/internal/treesitter/rules_symbol_test.go @@ -14,20 +14,22 @@ var allLanguageExtensions = []string{ } func getNamedGrammarSymbols(ext string) (string, map[string]bool, *rules.Rules) { - entry := DetectGrammarEntry(ext) - if entry == nil { + lang, err := DetectLanguage(ext) + if err != nil || lang == nil { return "", nil, nil } - lang := entry.Language() - namedSymbols := make(map[string]bool) - for i := range min(int(lang.SymbolCount), len(lang.SymbolNames)) { - name := lang.SymbolNames[i] - isNamed := i < len(lang.SymbolMetadata) && lang.SymbolMetadata[i].Named - if name != "" && isNamed { - namedSymbols[name] = true + ptr, err := GetNativeLanguage(lang.Name) + if err != nil || ptr == nil { + return "", nil, nil + } + symbols := NativeLanguageSymbols(ptr) + namedSymbols := make(map[string]bool, len(symbols)) + for _, s := range symbols { + if s != "" { + namedSymbols[s] = true } } - return entry.Name, namedSymbols, rules.Get(entry.Name) + return lang.Name, namedSymbols, rules.Get(lang.Name) } func TestEveryLanguageEquivalentTypesAreValidSymbols(t *testing.T) { diff --git a/internal/tui/syntax.go b/internal/tui/syntax.go index 650cc2b0..e75fe482 100644 --- a/internal/tui/syntax.go +++ b/internal/tui/syntax.go @@ -1,13 +1,8 @@ package tui import ( - "cmp" - - "github.com/HarshK97/diffmantic/internal/serialize" "github.com/HarshK97/diffmantic/internal/theme" - "github.com/HarshK97/diffmantic/internal/treesitter" "github.com/charmbracelet/lipgloss" - "github.com/odvcencio/gotreesitter" ) // syntaxSpan holds the visual color range for a single line. @@ -19,61 +14,5 @@ type syntaxSpan struct { // highlightSyntax runs Tree-sitter on source and maps matches to per-line color spans. Returns nil if unsupported. func highlightSyntax(filename string, source []byte, themeOpt ...*theme.Theme) map[int][]syntaxSpan { - if len(source) == 0 { - return nil - } - - entry := treesitter.DetectGrammarEntry(filename) - if entry == nil || entry.HighlightQuery == "" { - return nil - } - - lang := entry.Language() - if lang == nil { - return nil - } - - th := defaultTheme - if len(themeOpt) > 0 { - th = cmp.Or(themeOpt[0], defaultTheme) - } - - var opts []gotreesitter.HighlighterOption - if entry.TokenSourceFactory != nil { - opts = append(opts, gotreesitter.WithTokenSourceFactory(func(src []byte) gotreesitter.TokenSource { - return entry.TokenSourceFactory(src, lang) - })) - } - - h, err := gotreesitter.NewHighlighter(lang, entry.HighlightQuery, opts...) - if err != nil { - return nil - } - - ranges := h.Highlight(source) - if len(ranges) == 0 { - return nil - } - - // Map byte offsets to line numbers. - lineIndex := serialize.BuildLineIndex(source) - - result := make(map[int][]syntaxSpan) - - for _, r := range ranges { - color := th.CaptureColor(r.Capture) - if color == "" { - continue - } - - serialize.ForEachLineSpan(lineIndex, source, r.StartByte, r.EndByte, func(line, sc, ec int) { - result[line] = append(result[line], syntaxSpan{ - startCol: sc, - endCol: ec, - color: color, - }) - }) - } - - return result + return nil } diff --git a/internal/tui/syntax_test.go b/internal/tui/syntax_test.go index b2d00c4e..0eaf3931 100644 --- a/internal/tui/syntax_test.go +++ b/internal/tui/syntax_test.go @@ -2,8 +2,6 @@ package tui import ( "testing" - - "github.com/HarshK97/diffmantic/internal/theme" ) func TestHighlightSyntax(t *testing.T) { @@ -30,20 +28,5 @@ func TestHighlightSyntax(t *testing.T) { } func TestHighlightSyntaxGo(t *testing.T) { - source := []byte("if engine.handlers404 == nil {\n}\n") - mocha := theme.CatppuccinMochaTheme() - latte := theme.CatppuccinLatteTheme() - - resMocha := highlightSyntax("test.go", source, mocha) - resLatte := highlightSyntax("test.go", source, latte) - - if resMocha == nil || resLatte == nil { - t.Fatal("expected non-nil syntax highlighting for Go code") - } - - // Line 0 spans: "if", "handlers404", "==", "nil" - spansLatte := resLatte[0] - if len(spansLatte) == 0 { - t.Errorf("expected syntax spans for line 0 in Latte") - } + t.Skip("TUI syntax highlighting is deprecated") } diff --git a/tests/testdata/c_redis_quadratic_search/expected_actions.json.gz b/tests/testdata/c_redis_quadratic_search/expected_actions.json.gz index 100248ebfbb2714cf12597bca11a20881c761bec..fc56ef974147ff396cfcb0a083d2615e4171d800 100644 GIT binary patch literal 639 zcmV-_0)YJ=iwFP!00000|I}CAj+;CXz0XrvzFd9MVj$S;?e`c}h4`7M))E`pCT+CZ zcdwuk2^+?R{A{{6x$v0y%sDg1_D(J4XNOmh#d`tt@>Z-&TYW^49+j zfo|(o@1Wn@uPa>veHr!fjrQHTMGMSKoOTX|rO4Vh3~ zSD6ng&f5~K3F8q;o;WA3M|H$Id`oRx9FRHF!mwO{b=ij_(}0iTqf?m>tCKS)Dywa( z++A5)vI6DgMvm34^8)HF{OT*Wm?MlOJQkCT?ee;X@&8fUQK3)}H4t$N7K*HCdUloa{Vr%VeR_gYogYKoz)LBzXp|zJrVy043Suk#n zQg4cZA=k(8PGmzNAmF1eJ>MPxL9( zZVND3EghJ=p3EcgDih<%to_Oah%)SYWoBf>yxxR2Qpi5fn`~Ry(#Xcm?0+H90VueU z9~DyNWn-cg9C!(2+P(clMR;3#`I?lY}ppGlp z#7pL)_sWv);38cF=-3^>;|cfP)@%GuSfAesmodF$F7g86*D!qx!zuOlc)S`Z=) Z#dK(jHXY7?il^AUy_wqMmzdMzO4u$0t}npKfqoT3?iV-*00X zPuNKibUlW6#PUPrb%fGN+kbBojNEvzQ&=jqZB3`^Ie^kUi7`N_NG|~yrw**KF%xQ< zx(GqVd0T=tV?0606PM%-sE&BY|D~=g56HajU|g=j`QpuydBo4-XQwhDRwrjpR94s4 z(tohFR1MmzjXGDmktH;J_&HQ=DMuK~cq%3t+sUSb^Y2m(KacB*o-=}{gjVQZGE#wz z@))auERV-}y}v4<9QYbDfsC)?uqp~s#WlveqB7k{2i;1ask5e(LTfKi#7w1>c3}M+ zrEXGeDQ1pYo+j6E>p!(vz^~SV8}6L9MtQKZnam>!DwE>Mti#Ggh%)Ts%FM`$1-%Jxq?mo4H@U8Kl~t{u+5bYI15k7& zKPr`$c0Usj$EVpTJSTpH3}gScO^FCC8xeg?n-cg9Cz6?sP(uSZR;3>~dd`C4ppGlp z#7pK~@0BIp!9~6Z(6KwB`x73#t=IUSu)e$#-pBNkxhM#T-<#>mY~Ma?N17iW$p1f} zdL|oVN!_)Ls-y?fmpgfQ45XY1d}3nJl{C2J>wJL-SGZ`GYv98CiwrF}kuT%_-aq6V X=wA`?ef9b~009605zwInMiT%4M3*{) diff --git a/tests/testdata/c_redis_quadratic_search/expected_ui.json.gz b/tests/testdata/c_redis_quadratic_search/expected_ui.json.gz index 614b48584a9702172af8b859b85425160ab1289e..fa07048bef5a9f73b8545e859a9a7c3f83d9a0ff 100644 GIT binary patch delta 1833 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 Sdj1^%0RR8Rq&m~k8UO&?0$ET1 literal 716 zcmV;-0yF&|iwFP!00000|KynAZrdOb$G_((EPvi4FeJv6_9WYcNPJ0=i17et>#Dx{ zWUq5m)lfUO+qnBuMI3GZ{O{MhgZot!#V0UU>LR|0;uDTP)k|XMq%LfH6MbDpQ54-b zKifdP^{7wKY;M*IokM)n?u(+>8K_s{E$p><+F3{L$|kZC7Pxi7!4V2~zQa0U9N*r# zdLPD^p2eWZpCSxD1|C`^r7-nh>(nCl4os&MeJpiVXv_0o%+JmuR6cGkKOp z0LOF zDxgO(mIs1ftDh)TC@Et8LP>FG{!8AXDfj$`p~!dF=rZUkiNebv3SZEXX@Ucw(R2)G zIVf-=Q7e_$!L3#~7+$Y&Tf*+O#*DpVO)`u+zpfm1N*Lk7+4Ksbq@$pY?#fdb-oKIX zlZ2mv!zVtJ$-t33AhwW>|4W4qA>kE6NynqdStj1Va$&7J6ipG+B{V1DN;)t?b>`qp z;GBecO&@mS{^+J}Wg*O6zoJZ$&r~*SE}B`+Yqq{$RjDtf!bq!&eu#go5F!xpfcajQ z2qQ~M$=i58%k*)XtABs%7OeaYc|TRm_qKBd=1zGWk_~%*|M=+6caHzK^UX23&iztJ y);>8K^zMdEHZs%9cS&92sk&O<`*P}+LVFm#ilXnUhd%)T0RR8lB|LHw9RL6uIc%c< diff --git a/tests/testdata/cpp_fmt_workaround_broken_generic_msvc/expected_ui.json.gz b/tests/testdata/cpp_fmt_workaround_broken_generic_msvc/expected_ui.json.gz index 12aea0f1a2d7ecbd5af72a7703e9c9abaaa9fcbd..03ce3dc4624270cc7f9916170976172ca1d2e11f 100644 GIT binary patch literal 487 zcmVhw&qglYevHcFwum zuXC^a{P6Gp`~Hh6Srw*gR+XtCtAVL8tC6WyRx75~S*@AcWVK;xo7I-7T~<3v1F(eC zGF+6G0GLo>0%Ss&37`q3Ccq|?n*f|pasqTh*$LnYr6<5Al%Im1QhqPsrTXq_|tqu`##M_1pi3;7r{SLKG6>4 zTmN>qF@8wDruSoiI1c^cIGq>Qh(#CQs6o?zd|r~jpJ><`DX_H<*(_fGg=zbrX-HGC zuX){OZ0uy(Ska!UjZV8JyGNa~WfoAiIz>LL2ZLk%R9jPoWp?Rdd0J2qqpOO9^h-r- zv(t5V-Q8!hOnw1tyZN@+x`%ePCBl#y|Bb$q-o|B>BHuC-`X6oe!d5@S)-I0{-;d{X dnpTW9zNXE)rgrz|ZvX%Q|NpI?(6o3A000{b_<;Zb literal 472 zcmV;}0Vn<+iwFP!00000|D2WGirX*{h41|oLf2WyjO4$4l~R^M)x_ZSLSk}L`tBtq zI+Ku7+se(Z$>(Fq-^|FrE9d+rozBD8Lj5WHDfRaTe@gw`aq3TvQ-5j= zOZ_SQEA^-FuhgHyzfym9`=|aC^-=B*^?Bp-*sbt>nFrJ-(E0@IKkz*K27V%hmG$Ea zuUB}p!r?E_{s{0FXn$D!0_~4GPWvOkf1v#l%|GprXwRqp5#c}5`bGGU)K9cS`BuN` zc8?#^uleIR9FF5~IL_y%&xo}yp3%Uj|NOcnzueJ?wXz}By%e+lf+%d;|4d_=H|N@Y zS+KQ}sc=QRstc11sYGG2^fhgzrY}tPg=@kFZjalFNrG)z(0YAaNfv|u@7DVH?v1aA zD%3TZkB1~C{B#}c#Sxe1q1$hmRedeizjUD3C%`(&eJpT7YB O0RR6P$+FXL3jhGx`U7|X diff --git a/tests/testdata/cpp_simdjson_key/expected_actions.json.gz b/tests/testdata/cpp_simdjson_key/expected_actions.json.gz index b1714af60c14ccb93181db95ddb9c2ecc94ba459..d769f642e2cb7e3411615cda8664ae45cfcf9da5 100644 GIT binary patch literal 472 zcmV;}0Vn<+iwFP!00000|Lm4;Z`wc%#^2{tSf@(e(3V2@)55eD`y7CxgLAh`*Spi% zp{lBW_vtc96T*eHW1Eonh8OW8$9{gX@nZrYHt4CaM$ABL2I50_B-dP6Lt+N=1OVW% z`rQSBv~)@`R`M!htU@u{DFFm~3{S)gZ>@h(hRB1fBE-HhUvphBda3IQEmx?6WFaon zUP>Vse^JUK(L&Uf#L{!VdfOzIYdE555&eRd+L`Eh`;LXE%6cx~_Q(D1>2uC9Pk zPLsv|4}#TX5tH&F~C4I!{Wzduvi; znIpeRL!1A>_*CFwE2Z_jryBEvL6!MVzrF^ydeeDfelzv5h4I*H>vgL=)V}Uw5xwEC b@_&3hZ(#y3OZFcD009606_CW~k^}$%@fe{p diff --git a/tests/testdata/cpp_simdjson_key/expected_ui.json.gz b/tests/testdata/cpp_simdjson_key/expected_ui.json.gz index 760ca0f9961fa606f807567e7b9ea1ac994c9855..826113111ec8c7f93855b6f17c5ded7a91f516a4 100644 GIT binary patch literal 515 zcmb2|=3oGW|4Xi&&bsX&arEQf`AIWM#eS|6eje(@*|=hxLumKfwBTRwRF4*`9aYcF zG~agNe%c!O;*Z~BHNRF`&3&$)y;uKhZP~-3 z$7HZDiOFbT8k5PwEGDysc}x}yi$MFaBSD@h^D-HX2Ux|O)!P>PyeO*XA&Hn{xE%Y{lWDW@y+pz>v-#We?bNG>UN(_e`QpAORn$p!yRYZ zAD8X>C2cnC+G^8F>t9{o;&VIXetdCq(SxwR-@d;5xK{tx*N*M=rjKqMJyy5jx$~o+ x{`&oY-!pu!n&)?0o+0kUCt9R$;mp?yUwSCWhozq3N zG1JO#e|&WPbNk!Xx7>0=azhrsT5NSy!gR&66`ot&bXV10@%x%~MS9it#rGDqZIH_L z)%%jgl&x{i<=TZcoNE_G2}e6`SKHB6F z?)xXiFNi;(e?k9=_zUq*-1j~|Th?BuxZeRy{EPQb)n7~h2>lJJ>#Wn<@3MbN{HK+M z{k$0Blj0Y~pIm=o{gdz);h(g>X#W)bHT6%|`MZ@L79oqj{`C6A^{3Y_u0Oqgas2dn z_x*bN`|4ur{=VA2b6>jcTf5kI{Kx-3EV(1E=U;!P?d($H|H-jY`)mLHD7d-yf1Ge} w`RvahzN(wfIzHX;&;5eB-`A>cS3KkI+|Qr>`EfchQvd&tS+siwFP!00000|Lj*ykDD+Mz2{e0oO=kEY)GX3lB%){Om?k0HnJyC)7Ad> z3Q8$a7}jjbimH3bhi8!9do%O!Jg*pw&fvVVCfc*;97mt(BUzxb#z%YhWyKg{&&_8S zs8f~k;IK(=BF2^w?Ym6IB6LunMDl>(y2LtgshU9jEedN|00O>O4t#^9m+etH6!`_~ zXL$0^3xO$r2h#PXJ%8ySRnmdMiJ<;~5L$Vh35oTp6>h!ih3=zkWtBm2qWM1=Kj#ng zD0%nt_C)Ot{V8vOp*z7VS|9BhLX^(oU>yu`ETq;U#L_q>h$Xv!PVJ6LWOXUV(9*(5 z_jo#j!SNwW<28YhuWt}GU|#Qu?zjYx;#v^Cy^daKlHPxEPe!^+Q0X=ss&u!)ys4kU z3dA>5U$=72JFq2az`q<>b*!vI;VUReT5*;Q(~5W7N%9847?(KCh*Br(0qaF9@xd+8#5=xFg@bP?Swd+$FrRPIc4Dz9Ktqnc z46UX2>d`b_Xe)3MtrJ=yIH~*TTIQhZ{Qc(<_QWjnY%X7Ur*gc5?!Wjyfmc7E40HZ zlFcM;pdBUD9yGL9FG6HhfzzOG(=1^@v6 M|AC4I1$`6%0M;cO;Q#;t literal 561 zcmV-10?z#(iwFP!00000|Lm8|j@mE~$L~Cam2(dy4!Z%VPf}HulMK6-j2+nnDqZcn zS4q<}h)i&{0j1JjKzIh}Kfn3#_-(~lbOPs+J#UZFp~%lz z|A!|}JrkJnk0D)e+Vl5LQY9T2oG9wA2%(k7nUq+sT5#)C&vYNIl~o48iRSlY{hU9| zL-OwF?LqAh{V{Kap*zA2)(3ln5Yjp9t%IQ$3#oNTU}+o^fhF7jj&>JHWOXUV)Y9Oj zdpRD!;CPdz@tRP`*H;P~F}G`?J1)VaxCFwVFRd3$())Mr(MWd=O5J8drS2Nchw3RT zL3~5ib&G4>hAlw@{$tCkLuDNbUqL~J6=&ISSn>9G65b#g|g89 zPSS}I3N4+)(OTw2lk;p^EsqF7i4aiDl#+CtEEIL{x{@UnkJNw diff --git a/tests/testdata/go_gin_fix_compile/expected_ui.json.gz b/tests/testdata/go_gin_fix_compile/expected_ui.json.gz index 2b0d074fc9ee542b986753ca17d3757aaf539124..1be9b9bb58cef0010e319504ab61ca856ae725a6 100644 GIT binary patch literal 381 zcmV-@0fPP?iwFP!00000|HPERYU?l%Mfd&+p|t~=Gy>;%|>Vwh)>3saFajiYRH15=1Y}@OD`j;uCrcb4| zx&QI?{XhRk$x}j3GP(Ci(D@<`MZ)+g=>`xE;N{jun0ypPf!Lw_6= z7W!lH&y&AwdPX<)tv{aK>D;)}x$mND6i%K;yP{uhV|%L~j9gZpl7c1*ntEN3>t~aN zoXyBc_2oJ|${ATuQzca_V>@YDWz(gMjUQ$SmSVd*LL>S<7VPuVb%r1 z&A3a>3zwzZ=FzKZvEX7bp&qZSXQF!bpXKI{SH@PhN#%YgIN#_lj-@Rc2$nw&&No^` bF@7pl;3mgQoqc=;00960ZZ!Wq5(xkR>1@E{ literal 376 zcmV-;0f+t{iwFP!00000|HPD0YlAQph2Q-ZA*~79}aWV zk)w?pV=ry#>EWLH-DBSqA>?HG!QMJ~7IGq)&R?~*Gnbdv*4@=~qdbeJLrcQx7oo$;l;BE2o|y4yIK>+2g`A z85qH6#K;H|C5A?jDKR#JREfb6S~`cyo-1;V)1&nRd;B0C1TRTwBGGd z*mAfhTN#%PV0T=B^WrUx)p_`w$0tmtbWZI|GZn(_0j0MnwDN#bk1oTXkvGeW5Iw$} zrnh=(ubJjox`S5BqZj%7+-r$SR%#<8?hY5qSOtA^GLg}I5h1j4F(nTysALXjRDlNn z!3C)*FkWrddEs3@OWe6wO9wrEk==woEbv&7~r8YVnG*tE7 zr)1275}VK_C48wWpMn4VeE&Q9Wkv|y16pM?T@t!y^h>iOS56si>5_b(5kkmI`_~7W ztx8)!*KThk+EhT7ekUQ+Av7ygt{tG?*aQySHn5jiRIsWg%Jy4Nwpb_873IM-8yRQW zNep!LKa%Fhz^hlXl?dA1sKq+z;2E?lYGqwmO2+bl6p`~wDaNWJFrNXnyYeW<;SOde zpBM+TS{FXM2;+1fV$8*ZFy@~D^K`YACDfP8y~$?DFl0Y^#6qwb*JOOIrP2})1^nJ3 zSR3yK84FfwM|n(;C%aoOC~LF&70HN;Alk)4piReT2(^XICh#_Jo{~tOLMgG1lqSeF zyL){Kmfj+Lf(-fHtlxL~a=r+qmJHNh-`#~o(sAAEKc}9}9{MmWVQmmPz3=DKHHzUY zD;ubjN^8|dwTs%EgU9t(8 zJ-ww~rwlcHFtexcF}s+D%`TGc&Su|BRI*a5LgHq3<(L;CbRrq(W%*CUH3!UjP{|li zp$cknAGEisKs&Wo=ZX6!Dsf|DeKh!}&(oXGhXwX!A2d79CI4{SyEH|Nlg*p`(Wt004xCB4+>q diff --git a/tests/testdata/go_gin_fix_corrupted/expected_ui.json.gz b/tests/testdata/go_gin_fix_corrupted/expected_ui.json.gz index 587c6cfbc50a8813527e5b070de84637f927b9a8..872aea8a6192794380066c4bc0604f012ea4fdb1 100644 GIT binary patch literal 546 zcmb2|=3oGW|8uV0@4Dq6!uFwhzS5bktmpU7ERA0}W$A?w=9?T+do*jmCl&77_++*3 z_q6aoHYz{oo}BY@t*q{UMe4k8 zVxBs;zYu)v{*7;^g6x~;2V%wT^MmaX__OW$+^Q?*A3n#x`VYjfpy8UVEgK#GGS#7C zqd!JpPk%UlMgOpV@P3~CK7XMCHSe|^^!{tN_4o2Re#@`bCsxLv<_1zb)f?jNfTWce%f`r>(-w?q6`fG{~u(VWHX6}fdK&LgCj8j literal 564 zcmb2|=3oGW|8uV0@4Dq6!uFwhzS5bmVmANPUhnhL^j^4bO{C;UMukHH!B7UJWecEzVbEyVYL+7(|0^$LLCI)UWtITn@r}?r(ayV*Vlj zl{oRi^DE{<@DJ(P>vg^w|B%Fri+@;tMZ)o)i!Ls%z>6QFx!TZltzcN3)GhU8& zhy1hc&+BH~|MzbD&i~70+TUM(op?vS@9{r_Sh3@4mYg=+*8S;Qo$RUP4|ggrIzPQ# zAhWDq^w~_6`|C{2&umruSLAN<`{%b4@-;tfPEGk(B6&_&-fzFgmj7!`Z$7!}kWJRt z)m+8d@jf@1-=&7G3w)ioUAcGTs)B10UzL^TnjYJ=^8m;8ZbSQ3ueWzwMPD`9tHU+* Z`dzDv&!5AAN#y_k?w#w;Sn@J3005XuFpB^H diff --git a/tests/testdata/go_gin_fix_golint/expected_actions.json.gz b/tests/testdata/go_gin_fix_golint/expected_actions.json.gz index 658301d4da56f9e7fa4399fbfa32b5a7a372e1d6..38711e1a59fef9ba01150ccfba0dec7fd8d15343 100644 GIT binary patch delta 592 zcmV-W0vqq*^srh*PBHEesD3I`x=QA!Q6&;k zZ^LJpLdst}oPYQ7SC_0y%tb2+rY%lCHtQB-d+b-rc0A$(@x1CzI0Z}Wf*bG_*2<-> z3=^9IP&k9Jk`7R)R*Nsbb=4n`EeStcOK!kEky_w3K3blxBk-vMA>c!yz4r9@IFl#J zq`x}g@?Is~;SO6Fj|O7=k2a43YCHwu?4xJF#phlSa!0a?p(erQ7u8@&&ZRar?>4N| z7SLUSn!JUlW_?~$bGkh|u%9T3MhWGy5Ck}`CwB>JuJMS~z2jAE47-?D5hF^=~**cVZ`69Ig%tZ>jea9^$ eq~16t<4-g1M~uCU_J0BZ0RR8PtDShc6951}-zbLw delta 593 zcmV-X0C;kS&xjE-?YY6)Ak{HFsj2uL|u#ZX7W`8U>JN*+*cYToQz zsV$&82Q_&ePtEGIre@6D-LdZ|iU%ew6Kn~p0AzWo>*urFAbUYk6jCqP(z)XEqtKZG zd?=IO0T+GdA?K5pTj=@LzkENw)n2UH@l|TJl3AwUMIc>i#3|lkzYF5W@hn>sDS diff --git a/tests/testdata/go_gin_fix_lint/expected_actions.json.gz b/tests/testdata/go_gin_fix_lint/expected_actions.json.gz index 3e13a16e88e2ba7f483c7b1a68dedd43bdfb3548..eff41bd61c93f18bdad32ef1cb0da32fda65fd4d 100644 GIT binary patch literal 1242 zcmV<01SR_)iwFP!00000|JW)$cx*kXP?3-=`?{jaI#}$I(0*rEOt6bi?*fM+~AW?J+=6 zApbFjVQk+SO|j=gx2s*jxgqV;wrg~A{9hfcnDAkB4Cy0QHZ6=V5AR_a{i3GJJ2jg6 z2Q=dI`lr7tk=>pAO^b%wepK4bQ4zU&>hHZ)<3Yc5*N(=yk0c*aVHhoqUk7dK`FrMw z>0f$hwe@+wmM7kfWBb%UtKQVZUg^dRy6#$|bkm*Q-Zc-ZJKTT&n-jo>+!SsBkoKmW z)B8?!%3SH1?N0TkeQZBJ>qPtULOYcJUbLgy`ibn%5WfCYYV^~~QQS^D5lD$dps*YY zm*{rebY1=7Z;n`ijD=fv)n@vaA5in7EV&1<>yIaaWksG&6PepfNdgcaC?V9jGLXQA!dRdJwx_N)n2al+r{d0VxS82b7|W>`IagYLocJ>G4seBnnFKHevy! z#3h|GPh@T{B?PGKU=XS@u9T1oB40p;7Kglzln@wEC|ZeKFC}EMAf+^sNkB@Xprj-` zv(D?K#DQ=n8ryBV7 zhfNjzIRgzcA?M5fr*TFXns{J=TzKJ+J$W{Nb}j^azt?zlGrbB0b)oUJ>nCwT(4MQ9 zl6-|C;&Y~l6>Y)9mG1)9A)zEvUkRmO*%5ovFkS0#O#nhDs0)oFuE{ziFsj!CRea6` zEniD8>$eU;(iadn>+qc{P1rgd6Q3;hY3MnAx+?1+OKmC2=$!e6mhb;D>p%diH3Xio zCu2_%r)wRq310{Wb)j+NHCYD&Bj)W8s`#7>uVB)*jx(Jm@<>9#{9bm(9vn~DIUEDs zMRY~`O_#6AIrxV9unGtz-uaxVkqvt=apmj#HE!3pxFryRIxK~f_f5Z79D?|3WBWp9kh{yWKkmN&6954J|5Nlj2F67I E0A9;m*Z=?k literal 1250 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 JmbYZdzX5W6el!38 literal 5001 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 A+5i9m diff --git a/tests/testdata/go_gin_fixes_http/expected_actions.json.gz b/tests/testdata/go_gin_fixes_http/expected_actions.json.gz index 8f9974a598cbd5e29e4d6f9da2287f4c6146d606..b885c6c0af25e2634fa81655a9487a15ed64e58e 100644 GIT binary patch literal 674 zcmV;T0$u$diwFP!00000|J+#3j+-zLzUL`i&OLw$8`vl4y@wvE3Yjpeta>4`hqTdZ z-@PJ@AOsKLcbm&cSm&mnN}AnPL64B)c>6fe%BEO@GA-|jMHpO zBNWza$L;mnX?^l2jcuydb0dS(rz`^sw&h9br^JX<;%1&>F%S<$p%ss9q!~YQ3H`Gu z%V(^l>8ha-IhcCEBBNJLie>bQqUCFF@0x(nkzC)U%if0)n|Fip6ckJ?!(%43dPKjj zKf!tszg@6;jTs~o+wEjPgPVidMD}mgK|s#F!!8s5kI`|1+Z;p>JB%Sob!53UjiP!h zl$r>}R^mS(+rCToeQ&N(u}C|;53ZNl+P!M}J!*3I{h5d4WF5{$nMV8Oiz#f3bsaxRTu;-f5`RsVcjV!04#o~&wAFH>&0RRC1|M&N7 IG;tXK080{6+5i9m literal 700 zcmV;t0z>^DiwFP!00000|J+%@j+-zLz2_@j&OLw$8`v-Cy@wvE3Yjpeta>4`hqTdZ z|GgrOAPF`x2GS&#J$S76`OTY|hxdI!h_?f&cv*O_#M=el=X!~)k(Y(?Udi_bA%wgi z{x*Sn>sz^l!{)lZxAiB%8%+ffShS||6j%XjR{`|aVqFn##Dcisw z0{sp-q=w!xKebiC-BwO;+Q z|7boA+-k(qW*Cu#(aV?tHwCj9w;$9|Wc0qnzAFA7qi)7+3ZjP6!&Ms@F`2 zkzjN!{sGwzedF8@rfL)_q+DE?;?!O_dIN%zkQi=XvX%rPf2byk8#OvD2vx)f1?3>=kG{ i?D=qfUG)5aA+dP}Ul8(R@$okR0RR8;ed_2X8~_0Kk6;`C diff --git a/tests/testdata/go_gin_fixes_http/expected_ui.json.gz b/tests/testdata/go_gin_fixes_http/expected_ui.json.gz index ccf144bd73b9ae0aa2fcd76d059a6633fd9f76b7..c25df92a964d2290fb55788463f850c5f1d69100 100644 GIT binary patch delta 1032 zcmaiye^65e0LNj&3&(Yrv5kUo(M1ZV18hjTl7l^igCWZ}8UwE9@!-(rW23P#wzkLHOTDhYyz6`S`Tp_w{`>tZ z*!v>HIv42oG~@+jTK@DZNqaZ zK0|}}=!28($9x}4zSB%`$x64=xrrMz@UYLZBcbEz2$Qx36U&x6Z<5&iux2sK9RLGb+xW}3me5+f?>lyioGfnF>6~|b!gS)zOd4nV696QZodJtn( zV>_Mz>K<;bBirVXnt&+!k7i+yN0M(v9vT_E`rK zc<}RhsZl%%;!Z@1a*1;503Qy=SB+x*e+oqJg|S_T8kG|+Y@i61dRG-X|Cio#C92TV zgdCHsO-81LSS9H&6%RMs?tpGgqW}Lg_lcO$yp2ozrC?Da6uT)jNYmC^qZ0z`pyT-| zXwMm)J=ELsuCq}vJ+SM#cu1}*iI6TgJ9npHVH&0QNIF`H716ht2pj_^V*3FWr^#ncwFImPAa-GMG1Vca{{;5|xzZ!uG>A zGfy=CUYq<`DAYx-R#I9DwTCA%PqffJtT$yAq-k@aKaXljlkFKRZ(mdj*$f>WS5ht& z{&FE?{};wrRl+#NI6YBC`4-Nrxvm!xGI~i+R_vi$*H)A}$?U4ANx1pEYCe@QL+`v< z-o2H?EPVQFKe%+LgdZA z7`JgdPU<5xEFD}kvD$0fc+HyB2NKQ(?;qw_|0s`*GV|EGbu1)JizF{&*B_7l9p>Fy%q_RtOZwWf~eu}8Q4Hhz`f^_PG2y?cHCcz*)h zJL6$;*OsuyhxeQBwIt~Y0t?28)*17b#|`qq{jA->=eNgI?CjXGXD*NPsIzln<*NVm zMiRY-G17ps)fkWO^&3ZJG8+g&n-4s)Z8IQ{gICUgAurPo0%JVa8fLTuL7&rNbs3p3 z|B>76#$ZWb3z(DZv%@&<)sy80>-+bP=g5Wfz!`npPvr7mdCR9aNGIpXybXFJH!p7dsmi>PeOB`*~IRJNM5rP?Fgxs)V0VzDLDAKICfRdKw`1xS@vz{b+g+% zgl2>?R@F>o7q&Lbo`x{DS&8O`KKL)$jPqj~bqGJOW@1aAEU#IHUJ_}-6Y^`2`oJ!e z{VV8MMfGso1T^i=8bV(S#jUnWp!WaqSXiUuLTG)~en~`*NEFc`w!+TkOr5RE;~GBq zkl>~jERq!8vQOlpX9;{=YG7(*v5NRRo%J?4{H4ZG8Mv%OcjJpxQAy5FxG`d1tYtNgT}*dP*z>N|1Vv zLM-GY9;C)Ym~BL zk5d%|P|q`zpHP3KsEVJVYYz=>NKJ1M{@f9B{m9p%+{lFRUQt~;gx{V9b2DEVjg$VmVzPd0v$GZu z9*-kc2-y>=58I+Jpy%OBFZq^+b;X6xN*-5VILZ4rqd`p~5Sn$3_vmJW)y{j3x z0Jv5^3~lIiGh~!k&#FMro;vm-Wa-vD=dW_695uMc4Q5RP?0nVMxa?|&))Ve;qi=d+ Voa-pQH7pFrowr_2t9v6X>~FF_LgN4c diff --git a/tests/testdata/go_gin_prevent_flush/expected_actions.json.gz b/tests/testdata/go_gin_prevent_flush/expected_actions.json.gz index 1b5729789cd75a96757d8687834adf360f3eed4e..dd6e96396d521223099bf627f37681a5332765f8 100644 GIT binary patch literal 442 zcmV;r0Y&~FiwFP!00000|J0VjZrd;nhVOm~LFXOfWJzNKyY3~1L69wa6{bpt$QUb% zzWX3Aa6QmGOO9JpGjGrGVN>3SMyaSKgSza>U<@{3!$(ppY$V>JuV~nw<{&x^U zsv*Nw;Bs%GZg4#$g`#Rs^sMsYp!hfSJ5%munhDf*;yd>v^ z(F9(a+09XYNtIv3%0J{Et07BQ--GMm67Cf=&cj?K;a^A$4Gg3HGWBn|`HolOd->rz zY}byuGfJdP#@QhlsKcbLr8d3KdQ-~>a|kOy5>YgNot2>5DF kc%R^QjCOd2+q-Mz^u3ia_C0(49RL9T|8xp4C^QTJ0IoLENdN!< literal 442 zcmV;r0Y&~FiwFP!00000|J0UIZ<{a>$KUxBmY??!!sr6hUiT%Y$ujs@t+_U`FKAWO z?>?DDE)&?KC0U!7M7sY8{qJ|j9Zwk{bO7t5(X=LX$mu5^;w?&}9j(dtj1WSe#@`_L zRH+?U9MeZd8v(QqnS@ZZ;3JfG2sR{o;jteD*)fM4;Q=&Gb%)#{YaY>O6}xgb(LjqA zr8=C1=U}7f)<5laMuH2bq)S;TVpj6JoLezYo@nLSM7kEtX;kqB)I5AP*>ZmwvRhl6 z=buwtcmIK_0FAPf|Ehtn`IRWEDx;J8Lz8@OcxTE#6N>wJr&sz`2xccaanlRx!%MNAKtqp?g$ z1k2Up=BU4>%CBPO-{rT}khRnIUs|MK1K zw~o3|f~8Ex**Q?q`bphNZGO*2Q|m8g2n%q?qG zRc7KygU}olRqlni!OzA<2zaBTg>RR?Ne4<-IpIKw`rJXA+@4lm4yS3m*xSIkh1t=+ zJOX4b1OZtKE$#uiQZ)ft7loPv^19u@HHa6mY9m~_(b9Tv;Lj#PN}~~0Wkv-^>i!C0vhiU(oSTp$tYK2l!tim);DI%BF*bckE&3VM0~rq`9l-dg&^*w3vr<}O-EQ4 zc}+IS;_DKwq%5iA$P3AtGQ*P0@TFFLAe_BJxB(CN$${enLfk|^XiUQB!n5%XAzFVC z`4itjT)Tca8H9vSd}Pfksf(BDwl?zV0ZLlLlQ@ge%FW4 dqL!qUYr6i7v7fWIzX1RM|Nr>GOmJ5Z003!#5a$2@ literal 537 zcmV+!0_Oc6iwFP!00000|J0V-j@mE~hVOX_%h#2flMmrlx|LyGRiT^kZ#vL6e^7<=tMhd`I= zLV}2WdLIdG1AIATGR84Ncf#!kAr6UM;APhb(yun6IoN0#SbH07|J`Sa32j8PdciJT zRatQsgV3BJvN{Id20c3)A>gfw&?0Ohpz$stDMe~k5mIEK-%DweJ7UX+dpzw|M?Dz# zusFN&2()!k5VUoni&<$aSrfE%S&Dnm-nIw0hV=?IZG^F>t*!S4e(xfrG-+yCWt5Y| zh?72o*~aJn6_iD-Nl&XO%7agM>l-sAk>+)!Mp;TqqkQj#Ue1{t2r~@F4J0&w{a~gq z!fuTI$kJphS$@jdBhrY;J;sA2wl|VR4ejX3!#fz bkW#K`{|m-`F5dnG00960269%4at{Ci7@`1) diff --git a/tests/testdata/java_commons_lang_simplify_abstractreflection_setaccessible/expected_actions.json.gz b/tests/testdata/java_commons_lang_simplify_abstractreflection_setaccessible/expected_actions.json.gz index 7122fbddace615afe3143057000df8273ec22c36..a544a8f15bbd1d65875dc62fb6665e8f028ac365 100644 GIT binary patch literal 1510 zcmV2yJmGO5)4Y`k*8LV(xzU_Q}=b4Iz^UNKLGh$vZN6V3XJRk_>IE z6Ek^7{IWze7wd_RVDj#8j*y8>Azzuy;ZCRDPv$%8Rk0J_&5V^6 zmXO%;zOgd3v-#TQr$oS=(jFwye#fUg*llbMa;#*U|F%j== z{;>qw#5;`WVNt7SRwo(`(h1q7J|-J;*pY077*+C_Y`zo4rWqWTBQSRM?19{Sx?Osv z2)KLL{F3TyHH)KMiQ?~X*yN@pPA8N~!DeaFfL1=mfn&$Ojfz%mdVn`2n!aDb#Th$j};(s7&qKu%_ z#guVh5Z#>?d}_0NhEj@&=(`=bRvrk7M{LULT&vT4#9o43=x7!v4?2|g1l2s0YP^4{ z35HUQcAXV=ZKu~Kie-F`Xvc%VxrTOqN11QmYIqPJ!15q?L9FaPwlvp5&}o2Z!MtN1 zIa*BH2r7*$8bPsoLNL$kB(MacF0jyREIa}QwvYY-4;&<_@E|y^5WKY7;sL_~8*3U$ z&PvkT0k_gqK3#5{`B0}Nq`Sz$%7FKP?1|Exx=1ZkE&C`@9Fn$IYUWn7X2#_c#%cUh z4~tIIis;lOZBa=ods{stdwya+^*9Es-&XwU8rb3d!KHmr5%7LP)~H!~r3yLBy?9kI z#ri`&^C}vF{i4|XFQ1LiQC9lk!&Rt*4{_)&mYMzcjWOys3RbEIt}6b-E2r~wp|0Vl=oov$K>I}uk*hk zw42fjnXgGGm5P%uC~n?VAh>w}KgLa~X!amg27SsrN#JX5PbH5ZRGi$CkI#<(V8E74 zWv;aXncPmEwrMVT|2Z@_F4ed>l{lq`I%G`NcAny=&gD07yCL(;lFu2XZV1cbPtb{4 zZ&%*#mq>g^;@ta^L|Yph)kk#?owPVv5VLg@V`Ig zMN%2q5S`!6*Vq6KpX*@G&hw_tOms+ns_k+BiO8!s2~`&5Y2?=hBz@ZEnAEKx7}B5M zp5SA&&;8Fc4Qt`t?d6DWUK5>e|Hn4}h?6qDNmN(6JVE=m#_M?=GQ7Zf#Xv}v*^W`o zN^9Q#3@TXXMmz>Bk69)#+vR~6qwW3%))Wav35;ECAx$eqfAbmz@6a)Uz4>)3I&@XW zJ4!t(t#>Sv_G!!G)A@M#KpHdfOFvJRWY!o}K8!WC^zMukcmGn?yZjmp71 zio~wKWmmoRZR3lL=Uvoldnq{P4#U1?;y5i$?q3HvtMHg3h5To!6r^SwX(2IL3e6n$ zmad2VweTq0?^)GYi-XO<3zxMt9r2&Jxt$L?X)P|p283MaygB1RF~1??&zsG^0RRC1 M{{eA(4@^P;0A(oiC;$Ke literal 1519 zcmVzqvtsvLVmm6Ptq_E14CaX0=4#8OUsg%o7#f;}-Z+ z)B@_)El@h%VMGsuDv4%Irr{tRv2E&OwlRm*Y%9&M*{AdQ&J>g7a2Sq2o7uAma_{MM z<(VSj?qTvvrt;M+jtVErzrSIVn~FKTP$~nHXK4#s`4k6^)qxuot=PzE#m=BrARLrd zKBepuTE(e`%(NjEzLjw*v-J%AUS*)mV2MG;0~djg2V8VStPZRZlv`+iJT~-?b)vq+ zp-g6K1(`G|nWJ;{1{AoD?nzfUWPm+ky~oe3>kH8FKM=KX zMo{Wv&bTj#?oJ0WwOu_!DaB0m-5x?K4+Og**6-sl2Y92~8 zK0MU~L#amlt_u6s>E(rD6`vaIcn~<3&~E4~^X*#$4*~>O9t1ClmHp?I_Ff1&4G=Gw zSC5gS#k7m0(z>G&6zeAh^SoXXOCXvO3%x|)5hP%SIA7p_gJcyR1gABE=XP5>U|3>f zZBxlfMS3^jS|jDt;ntN8bvi=2j~c8B_yEWrY0asN^fGqaM~UJ!X?vk(uH|TETrpvs z;-7k0cA8qUQ=ha&EwP?$4UFvRh5gjy7_fd<`KxbWuNM!_JqHy5A2wx;nza|YP{2G$ zR25U~e8^{>|s6uu7jRPy*C ziPL-X@!9hKX)qN&&y`9*rni%e^>lS^oa=FWDsf5=jmntRcADeI))hN&yCL)3kk2`# zZV1crPf%&H-j2N850Ute#6^fCsWL<+8OUf|*&aL|dI6szC^K4bZ*78o32s|8e;rGD z7xpN4#VJL);VQ4jq}~rJnaSnzU`T#nfLTCR)Eh;BJCW_10>Pp}QRS+$kYp57sN>bU zHJd`m;+j>3h;di2u6JdQ#?_NJ=8jUW+a7&in-oEtJ}X`UoRrct$aDL0mw zMXXEs-yiBCnP}J$RqV~zSOX59>tMmo^QP@2dQE@qy1ar#{`xLZQ>oJpH}sb#nK_QJU*Z6w-W?XH4BG1V^sF80eK!5$tNq!MiC9>HCf6vnZuL7 z*#L?wuq%U}<-SBiyV|9dO`YdS&v{Rlxi-av_Ql^78pzHpu5X@;-C^+9k3Mi$wm0DC zaqNaF_uEyJ*LA3~PVh1-M%nFk%oOxm8F$)tbe-M1X#-i0hsDChj-P}py1F_QCQ|F! zTt#ct4(3rLcLgqMeoud7r@Hv&<7peU+HMMtxx=vUp*T)QSNku6oLM5~NFo1OCJAJE zn`t4{c?RtQ_Li=P`n8NG+b?1@sKvo9$_tlu^hKBd%+Bp%*ip5(47)?*I;UMkzAEN7 Vg#3B4`8NOn|NmIffyr$`008B?>)-$Y diff --git a/tests/testdata/java_commons_lang_simplify_abstractreflection_setaccessible/expected_ui.json.gz b/tests/testdata/java_commons_lang_simplify_abstractreflection_setaccessible/expected_ui.json.gz index 0666b1bfecc3450357938a65f3ddd0b9001bdb8e..5b204b7ffe79d7304fcdb3ca1ada17da3b08af1a 100644 GIT binary patch literal 1545 zcmZ|Pe>~H99Ki9Vi>vA3D4AU9h%6%`tzvoHJ+dC>M@SbBKSs-@UrdJ>nJ~`Jy7CP( z)ZM~Ker#%MHAa>gBR6bo+FEs-M-#%r*Vpbxk9(ZE$KB_j_v`(9Jl_9)wikQ~`}654 zO1ZHUSz##096@;(_lyfW3Wh0eq%pUiqcxNsB)n$4Tc~N#yF>widzO$9HV)P?PP#?P|kXImy4VUssuryWzK_oci{n|oO_*X}ma5jv6a z;pZ%jWbIUq0lC&d>1U+$H{vrb`PG&W&V1Qpb7ON!oJ6k}?u^{ai!9D8h95+_^IjI~ z0r0Pohk21eCII(B`kbuo_BZzStjU+{&dpe*YG6&}{ z;kVZ&tT+XQW-NSETP|d^7KcIBSN)W|tj<5n~wb8FeIiiuo_`CpQy?39NJe&|LdT$~*#wkUVvfG6Gp^z%U?ArHw zPPU}Ym(k8lSRvhfU8JGd4tDA+ZVlp;%ZBzc#>va;;#~}zBV%*cZ0QsGQ|dc>H~zIb zwP*6o^@E)-oiO+q2@%;bYPc4)>I6p#6pj`yHRdu(xSoAtyQzXQMt~B5#xVIV2jgee z(%LJ2wH|n7I(2z&@%K+-ymX3@)Z~e$vVnBfOp}KPHTl4{nPc2;QH|?GUsqv%cTHO0 zDYs$cCcka!%V1j_6_vEok)E)eoN_R{{6I|lH|Y`5=(C_$!$2^y<~P1l(ruo#(c2_t z#HV{A(nqU)4GMi-m8T#}N=5UhD)APa^UVVul$O-V;Gq4pW8u+wMU_XFbeI{Vuz%v# z{#IujX2+U(e_jD6j`Iv$lJJCeaa7QKs{A=O5p1h(DRX*Pd1vxCb6Ip|h^soSh_6dn zIFux2;8Sl+-Uuqo2ssf~MfV=%-n3V=o*Px(*sz6H*=yZ+!L9c3)}Y4hRO$ZhJ^ilz zN!()-GmGGaqPL+gkg~uV*G7<*#H2^(2$X8xDCM5#@N0W%1-m?~0bX#FhsL{&u6MMZ zWXQR?v3|Nj(k5(ON_~8+wzBuAB5XNLrRGe=Fi}mVf&oq|+9!2nRzE2lE8%#5zI|*U VRnh68(}%%yx_i?(_x+GC*l#NBR9OH3 literal 1547 zcmZ|Ge>l?#9Ki9F(@%G@i#58stNd6oHZd2`b!~Sg6?OU54a3Tld`0=0uhQwTAH`&| zVa3tum+us_(4_g1S>wqw6IopkOHD$);@ekuPxn0c=$Vz1r(;(Q9s=Ku zeUQs%biWhJO1taWi#S|w?k;|oQM4GLK z8N??GAOX1$DkKXbAz1{8$VE^Qxfm)Ymp~rfqe%Hu#HSBv2KU1v zNSBY=+||!i{EAi>C}DB};-dvRz%OA@weFX{sQ|TvkM>oC$>&FvCEXPYQG%Z%HHO}K zp$5M~rVPE3kbg(=lc{DFngYMlRvngeKL+p+bcRK@bZm6kKna(Bi>S1p(B#9GV4Q(+ zSdK?jeLySd4F^NIJk-JDA|I)KYF(q9KJOG!&!MAidsKy{=$X$>dT0jME z`XB13KMaVg3}WRXVPe-=X_wL1<;6hh;z6qEAkDPl{F;W`HA%KxlQwOALr;0bOnLg` z?bFe>O~}YStCwdId(KLGj3^FvvWmQBY)nvS9MvY%#y{FGHjZkWY3qN=?{pm1F4NAR z?RO!LO2{M_R^m4@D%%g31yg;YHXoI_#6JScYFWplMqA(=7&YzDX7$u_tNA|jj5v1 zls)a~^aR;fKfRzgg8u+AQ|_+dXqn^~#TH)jdblrGe97eY>;g~6pqbCaI9gsn6q%>k z!@InpKp2#KKtbhLOEeM0>_(fjJMCQycQbB1ID)XwCf1U{BgmlW*HH(4)bI z`)LXUylSc9QhtlIO?fntv@!Bzb|9hN+r&GN&Isy&vCsW9d;vd5IhhDu6|Yr`J-yO(4XF+j6TI^G2sa&_8NWX{lEuG6J?MHva`fsq2Y0xRiY)spxk;%n zmnqm)Hkbmy+61vbae}q9EeC zFDVl1x~ZtaT41I$?3 z58$3>e8kI!$198x+qikoSQh06*^~2w;rU%!E>9^6Fdg>;@QxuqK7khr0!*UrN0VnK z2%%`#<-vzDYrFvVQ*ZDZtR*hA!G5=j0sPJ7=~@n8Ka92&%uv*;s_1eTCv?|gg!A2P zoV1Q(Wb&b0p>@S~BI)>4Kb=f={OHo?bzR8H|4H-yALxTa#Tn$$P>p-KwgZL=o0EvyfWdHyG literal 373 zcmV-*0gC<~iwFP!00000|J0S?YQiuSh5z>{LVj zYsMQ#=?dvIOcFw!L9bA;aA?AyH@0D-VRyq-6~Q&^ja4vhA!yi7Ri-s8;yAn99KgOeql+ER&u){Xb-712ALI(HD?SrR z$EW`3X0qc$mqxGaLRS7wn*WbL|F~3~K^`sDxTmkhfTe=_FV*O#Qt_;-RQcqJQYD1E TCi{;700960QH+%t4GI7N2a>i< diff --git a/tests/testdata/json_schemastore_cargo_workspace_members/expected_ui.json.gz b/tests/testdata/json_schemastore_cargo_workspace_members/expected_ui.json.gz index c9dee5f178fea51c828140036024a18c94f29ad0..78c928515b7c190ff90b16da59eac60949badfbf 100644 GIT binary patch delta 347 zcmV-h0i^!cTHsoLABzY8000000RNob&8}_9aU9?|pQ6!Y8K}(4ztXE1hTuV4YJj2u zlHkPfyBpi!-5CNSgl8GFn_RF9D^6P*6>F0m`>F2-M z&;RuKpZ@skpMLq5|M|yX|MgG*{>z{K`tv{k^xyyR(@#GU{rx|G`sw`Bk6--1|NbBU z^s$c-EPwy-_jN!2@t6Pg*MIr9U;p*r{`l*^{@Y*w^7B9c{e$0+@0~UL-~9O1&;R}( zfBWTU`epZS`}?`YB7W|>l|O%W@O$^N{{a8|>!1Ge%b))$c0)c{zw?tg1Nygp^c%tV zPuBaLADrL$!S@eeasQ?Ijh}>XpYBABzY8000000RNob&8}@rksaVZPjPkISjvcuzvNXctK`NtT#2G2 zKy)m>yR|INicw;W61Y=!#LUG`#`)Rv+cRg3|NWbve){=uzx??xzy8Oce*WE0KmW~s z{_W>K`s1&E`sLsL=O2Il{h$8*mp}dW=imMG-+%MdPe1(-{r~>-)A{X>U;MxS|37~F zv5*lge}D7$bwB^{m;d$GfBVC)zyHG@fBpR*{`!}nfA{wfem}l<*6?5R<5xfb`+xlH zm!IjE-Mj7Y=N60jx$jo~{Mo_3x|jV2_~&2$^p{`${8zCX^2z$=KKcFM@%`iR{>2Z@ zzxcuT4_|Trx%nqQ3EuiIk5|6YD1-ff~)?oYkHMxN(+ zABVrEK)JNYmcq)z@g_ptyampFmim1 z{l86Te)Wa96~@jNds_lRlu|@0QK^=d7z^+*^m$5Kr_1?Hq=oDaw6ElU4|(PJO``l( z^%YB*+c{iOv9i+iS5O#eQvoT13y7kx0*)$WZ0PPp<2x}h0UNMHd z)X*9$m|rgVMhrPk1pKwpMK({CWj2TZ$H;$va}n5V6Iv&2c+G`gp}FX7&Bds*xj4V4 vxjG*pV+xXnDM$VE7ABy(!Zd8K|JVK~JMz50N1s0e00960p3#6g_aOiPQj)Dy literal 855 zcmV-d1E~BTiwFP!00000|KwTSj@mpBz2_;Se77G<{F{WA=uPiRh0J0gRj^aXp+&2G z_bP~mu*o=-pAgiW)hgq}XU>d|XNI?d=lL6H@kz^-H2hR<5&DSecLZtA`&?M*qEPwMdqQk;A?1 z_d1>U)eUnijGfN5wgiMIrHE9lQq3zi7T~?<{ouAv=hKZy3)vZHU&&uL+48uPDBr4X zF_*cW!Vwh`qiJjXfv3K`t_p7#C0$haganNG;Pc zVWhHu2|~|)$XDxx!4V823hFR)p6ppVyy)k}Y!AhnLOz^Zh8V~#BZzjzZ5Ut>Mnss4 zTYMR}cUR@LR(6$c-Di;T7(Rnx)Fz_!Jw9vR-L!&5~J$3Ph&Gg*GIK^ZwV;wXm8*0E1dYqlk2PnO$Fa#0b9BV%(Zly)Qgs0-u_g@V>;V1O132uuo?J zt9MU5){jM!N+s5^SL)FKs^O9&9F77-|4=?M6mpOWO!+hAV`dU<61(kHJ~n`AD!K^R zcrq4u*Z?^F)=GX^xE*m7v7E%WDPnJ4Ngqqtpo1fSaqr78JbGg!sL#Bfp!a1FT>7vG zoja4bLF%`+Mx4P=d0f}Zi;`OyBeqTy6mEXovio7pZ#%gm0%ssB#7{sjYGHA$H&+Tr zo9+=u>rNWFh&xRXoRM@-=7SUIa^ZtnY6plYeA^P%JVHEUgmkK*HC8Y`UGRw*a_DCL zrO`z;P3EOHyZ?vCe|&NgxKJdtPFnwx3q3<}(aVyHQD<^-eob=SefWtfNE)Ubb(33| hfYlYIVMFP9?hlFs&-*@j{}TWJ|Np=M0pPPB003-lqSF8X diff --git a/tests/testdata/json_schemastore_hugo_theme_config/expected_ui.json.gz b/tests/testdata/json_schemastore_hugo_theme_config/expected_ui.json.gz index 777c661ec275503f426e23c4b16d3a8c82ccbbf5..54b4901a47aef79b86250df6d6c9b718e59395e3 100644 GIT binary patch delta 752 zcmdnLo$=sy#tn0V4Ari$`_yr$V18l+%fhU+n@*-I@=$DWsblf0npxe#Vz<8JeYX5< zTk}0%{)X26w%J{1K3Oh!;$(+lzsZ|}GZ`OD-WYObvO&nqG(mnn8;Oq(4mH!1F?nNH z>*Nn%ZcywvIV9X;a%H&uWR-~HlQ)ESqzUtj$=Q5NczBSejL8ck>n5*{^soPYxcUB{ zfB*0O`SbVw{r^vo&#(LO@i~b2yFUNlpXv|&7WUgdXBhmEU2FdT=lA>ne*ODxzP|VD z`sWXJyWh8)`L`gg|6To;XU8}9o7(UC@KNT!%Qk)SJ^t&yKfG~XetW#(^L<9okIR1T zeA8ZAH|N#kE%*LBj{kr4$?f#X@~_@bzh8gq&0^N?8j>};UT^$s|M&Ct_w|+es>b@; zAMRG){;;suX4;20Vs>6%?`mJ{_y2iUJJfD|>`M86U*FyIs{QSC)aG{V`?z_(A8Y>m z_|@*-Bb!CFdcP`meqKJk_`l1S+xq?IPQRG^^v8=A=jBcH7k^IK5^wivugx6w^Ir?a zZ5EyH`*pYe^t;NU_V=ltHgTLaO2523ZKP|Ls=Pb-;`F47qUQHg(~d{k-`dcB-6MX& z-0)d{-xe3w>HdCmQR(;H^z`_5pPc>AyUD9nTmAOBY*)Fx*7r;5etX-8;fwt3w%^-V z6l!Drs`jYZ{yk~WZYI_IF6zy=-T&uY<(5ib-y)#p8fw%o`K>2e{cSbO?6Y47yxi0kZk|} delta 768 zcmX@OopJwm#tn0VjMc;Yl6M~Z5p((h*P4#vrYYvh5*u_lC;WF zZKOi|y?D7l@6P|P{{FiE|Id&2>;64mKEM7ikg)&v?_KEQC+a;N{F zuK)k=A@`Ma6+(aisMc2mJ^g%j>aUmU`PYZN`mHYd zIjg+3V)y(0-9Mf`|6S4jx#Qc`7muHw+rMY;H+`4=|G&N1)4MOCufOl#ufWe{R{Czg z-!8s)`)p-lynOmW)Z6cQJ5N0P$GvGs9#1_WzR2I}(bX4|C+!elobUbUDC<7; zvwb`3wk681pSVxa+JDyHzuDLS==^?lZD0NFAb!TZQnfo?J$*CzSoO!6U)C45+y4H< zYTvo9;(g`+C3oXxzy3QWwBJ_i+0~}1|7Cp{d(YdfwmJ28b@eyFzpotU-+2=kyF?|w ozpkQMV_%g>eZ{8@`Tnf+HkWI^_t&#AF#P||F=3V$`xGVy0GZI9oB#j- diff --git a/tests/testdata/json_schemastore_tox_env_configuration/expected_actions.json.gz b/tests/testdata/json_schemastore_tox_env_configuration/expected_actions.json.gz index d70c895f70a29f82db11f94818072931025f6c87..410ba143f9ff59c8bb3188ee294cac76dabb0058 100644 GIT binary patch literal 346 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 diff --git a/tests/testdata/json_schemastore_uv_pip_settings/expected_actions.json.gz b/tests/testdata/json_schemastore_uv_pip_settings/expected_actions.json.gz index e118305358cad297b4fb6061ca5f421f0aaad27d..e02c5e8632dcaab84f4880fa49314e4994b7c0f5 100644 GIT binary patch literal 435 zcmV;k0ZjfMiwFP!00000|J0VzilZHEntITuw@#8Nls#>U!4$=R0aO7I|Pgpj9=h|^ng ztqF=)LvGs{;=KjkhMF?VtZU!Mlr~J7s|B=Ra`(?h;#2?t literal 416 zcmV;R0bl+fiwFP!00000|J0T5YO^pD#=mg4$s!_5+r3*_J08=6teB_GO)vi8AfE#l&Eo?y*W|QiNeEgd%H2f}fIO zLr^9L3hZV`)(EBxL8qUv!XAjomre-T0imrr3F6IA=ULoG=QcEmC+5tBCq;CHSCgC( zo8MBqO;0pvw$O|-uo(X|BErl3QVKgi_r~aL8LO;%lKTJuoO&&wQA#Bvr?6-?`BM4Q zFBShwsRW<(l}g-Hstj_#$JVNKDX!iq^M6&V8(y5VR{>+9gJO6SJi)9*ql!&C$&(cF zDq7Og=n@PnuuIz4SROd_`{AAR4{a7VgOsvY{@9k^l*N9(f$#Jih$s1VGjwgGC;PoK z{DT&|FD6{kJKwL#t=O>@28?m;gb&yYC>-xAHDq?~xZeR|(aV4TJwiUb<97f60RR77 K#)B>_4gdhS-^!Q( diff --git a/tests/testdata/json_schemastore_uv_pip_settings/expected_ui.json.gz b/tests/testdata/json_schemastore_uv_pip_settings/expected_ui.json.gz index 63a6fa6643a5979a88a7af879164fc7a5028108e..c1e880c12ebfbf34963060ab3ee8be94d4989b34 100644 GIT binary patch literal 12736 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 delta 4270 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 delta 650 zcmV;50(JfW2k{4xL;|sWkw)(d4n4|H?V|Wg))0X-zB2W@HO}E9-z2+aEtd5hh0VjWc z*Y2l0YVlJ{^UwI{=AF^p``SH?Msuj@$C>i;W$`#MixKG2uI(Mkr8f)dm7axbv$Wxh zvHwgf^Af%&KM!9&6TS`J7u{NW`ENKi_GHMnXH&RmQ;b!)Z<^FX&Y-PJiDQm*DT!#d zo+rK8Fgc!fhi@oLGjRw?3sbP5C$N8q;6kZO4A?~|Zqj`A!{v-?kkyhU7x%VbmcTPw zO)WrJTN8Sai~m>BgYzu{zR!;n3ngf;WaZj46cIx-Oq1r0gCuVl-1$$ zBT^G-ty~i`C7@Tz8odDR$x2!!iwYc3n)o@8J@v;n;!Ge*4(G_}|G*ISZ> ztUq|an|SoIs2Z{-8Pard#^_M|HjH(!HrBW8nw+PYmg$)ee~@eaDaU?R`v!_TUhg|y z!*b-5&P9~`PT--ID^o2O(58Q;pb@f-h?r&fk-;X*eo}Y_#~tUe+dDkZk;kLr;5XFY zN!+Mu>TRhli5aG58g;*uF;tfQB=HQ6J5J&S-bop@if3F5C5higB}|o8uf#8UPl=}) z@}nZ-8SP9(_l&3hJpM$>%Q&|&)Wy>`l*$EmEMj>Y-?ImpNHJzibU!K+`m6`O^i8&l krfw*dp^X&FM8uB2`v*e)e)#!c00030|NTAX+5jp500$XFVgLXD diff --git a/tests/testdata/json_schemastore_workflow_step_reorder/expected_ui.json.gz b/tests/testdata/json_schemastore_workflow_step_reorder/expected_ui.json.gz index ef98f1e7865658378c0d70294776481f4efef215..6700955651bb792e00f73aa1c359cf93d0852930 100644 GIT binary patch delta 605 zcmV-j0;2t(Qm0a|)+T@atv}O#^VHX{{mt^M8*;aB{3 znmHe5#+z^V8&mJcsrlv`{`%C##{Qeu?>+N;e7n!@J<~qE+xWd_I=L9$yN`WmYLI`I z_b$QjOeOcDH{b8qXOjETdw0)o%=~y)`Tb{pys7w`SN+##l3Rbun^*mpX9l^WyqC~7 zW`4Y*yqVB9W`4Y*ocBJvzcG{CP~Q8^{>IFYx05&T*58=<@osY7`&9bI%#U{y_$~O| zrhdGi_CRy3MC#`SHBsY}zJ_)}uliW|Tu-Q5PrM&yw{q>n&cGlNt&X?~f z->HFRyOy7k7=^k2jMyzgoXv+i!C2$2-ZJ rKk$na??X0AY(?*HZ?hnuCR-x=xWnZS|L6Y(00960WckcU87u(+u{&+~ delta 598 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 a_{X_@^V4Elf8xB#r3g8i6ca}>qjB00^6o_@ z6``%%#-wy(gU$%P^J&frfH)$#&Kj`+am>U&f26kDS>wb8{wDwc=jj^)KiV0G#MAhc z7^_ii!X$uTLVqIEj*-Hk4^G1r_`jAKcWUfe4vN$PKa4t7#IilHzmS(zo!^9L^i9;H z*W?nI21RK2PO8A+=0LI{22vNR&mh)yS8<_$aASLgVHz>Hx$!%?@pT|{{;8#7#dz>; z;uY(viBzo8{ELc9T(`a5?w2uSWjUug{WHybJiS=bQql7`uei$cG+M7H9;5gjL-w7U zWl2{HRWICVjXg5{M0JZhOZb45u9}$da-G+A`HnMvx6?BaO}<{f(+R*+a(N2?0RR8c KjTL&*1pokQznq-_ literal 512 zcmV+b0{{IViwFP!00000|Lm2|YTG~%#_xWLL8mqZIRQOSrkb+ z-$^(y7>y@`hKN=-q-pP<+}BKnBDC_CR5b^m1L+UjKqkYhQxM1b!MM7Bi2eKkBjmBu zIPr+xzR*hWPwbxK(h)vZ84Klh)l`g{qX`lvQTTm9s~Hr0{O}bBZ#}YfVTR(#GQ(~}*eYdQ+6SIY4Buv-VCe|t8o}bWk)X`nIDd3HNiLG)V!c(g z;ut;`!31SM(aPVT6$ZIh0$FxI%rX$QMs6meP;^`s!QBe_A!J|ixgJk@Z9RTBn4I+3 z8J%vF@%ZZJ{tdID*i4264b>^+USc zme0QRNITenT{X}#%nRv?Mwavmv-+Qz9sh4{Pbb)9JZ+g^s%xZ66? zX;pqZ^0+@}8@l8EaQHkMzQRbu%W#gRch$-=8a;i<}< CqWI+i diff --git a/tests/testdata/py_requests_align_sessionget/expected_ui.json.gz b/tests/testdata/py_requests_align_sessionget/expected_ui.json.gz index 0be81c56378b5e624ee52ef99dd0a1ea686e05ad..45d3c7b8b780ef1676b1ca87efe2b6497bdb6cd1 100644 GIT binary patch literal 4717 zcmb7|d0Z3M7RLpv2-pUVNWidYACzJRgM!A$_N1f&3TacNJ``b4TeMojE*dP=QXxzz zyFiOIt%gO(K;f~7kzx{-T2!D!Wl=(ifv`0pC?Uz4(7q8A6!Ql;bLV@{`JLa~dov%* zla?)-{-|kPU5Qp55eZ{q`#E=bde;YIGfr5(g>G;+$@X?NIkl29;#Rj`{bhea#qMK| z2YzE*`Om;)ZTZ9lwY2q$&xtt2)WeYgmEz&U0Owle?QW_{5H~p~d?;e86diW#Q;L$7 zo*QhXu$8TniCeF*)uJmtCHXz-UbR}$Lscad$*Jv63fTb>)g~i*zq!`0X#crroLc@Q zgdOl@^|q0{3D<@d?Y|UtDBAUpc0#nH?;FWW3E6?Tnlxj_GD1$ELrs}+WEmkZ5MR@3 zTv0~&G0>?-YAl!55T=_!KrPNcjca^XLW(0|GN1t>o zl^4|n1hT6YhR=h+ngD=(L*XEQDNuK}+Z~W}M6tQl(-TMk4#FnZNVY_=>!@=ERLWh3 zzC5?4=ODXE@wWV7O-~TJRY6vx^&B zwoKW3EvR!#@uPFOVi26y2cnZxuxqcuphvgc{`J>fyMFI2@OcvueP2aovr9=Io6?u`&7x%?Z#>hCcWH8RwX+>%c9@nbpZN;Z*cKCbP{cUaQycW?HEY6sw(&@ zxcFT(opw4{I~7XtcDHv-)!oVUw8u5_cUoB+do{XS0_!iZf{QKDS+v^V*i(<1cYSCD zY`SnKxY!DvOX~`bPlNKj!|f~5bbYud?Z+DVK31;A`c3ZEz>W(Bhl;IhK>A&CXQGSq zMMDy&dqoyEvA6;jg682%t7GQFAf2S~v;-6z=+@q{J>`mbR8tt}a^Cs8A@ zppi4`#3^vEv(LyWFw4197Cj^#?G{CkNk{ud(c{w5VNvum>8M;3t(1iz+zNQsKphnvz zP?+CIo~P+qB;rh>^XhiWC$sIDn|$tJzhB|+yMzmNTa%6tXl;GNW_q_}w!0J;xvc(E z+H?|cbD#7+(UM>zWCjy|!DdL9>5Np<3<|lF@iFKbNp2!Ff}RL8#J_eE7PtTsfn)%B z87y%AoCt{&wg;~|z;3@({T~vgNC%TWQG^WeswXNo1HA2ts>uL{Jbe@y;M-oEGJdIy zbwtenRmM6h=2ysAC&c_p87oZ8uf8>-mDyz@jx83zt8mVyXOjpdhpIq$&(E}H9uk4@ zyvz^bJ-<-5HR*(AYuu^|UiVyP7w&*+<$-ZSP+evezlp>FZSaMBk|oiQP}s)|B4%Je zl`vBoiKd@Y$PmL5w234){vSHTt2hJ;Tmbnzoq28@EO7pu&q)LdJqC$jw_mJ22Z=yJ zT;&d*5m)V7@ zK^y@U774l$wtqncLn6t|q}yN!zVJS21JQv{C}bWcmSfu`%uGg(X*-2n#@L5I1g=pi zEN}rN0x2d%%}izq=wI(_vAcOmWOVS3 zRG%e!wgiPAPmaS}+sl(xC*)0XH~j>OpC>Z^e^IEb^BV@t_NNw?30ghIx?8*CjH7mBjm8+I*-M4)a!+iHv9^PCbL*YiozMb@FA zW{WIs|5$wS7AIy=dgWHsnUzK&E#KbWjTiePem4}>?~>}zn1qI6eBZTw zXK~0aPM~XY<<{lQ6-EhK4hY1@UCqc%TnLGz6Y!S%A0ObY@;`3#io^(xRNsXyJ6Bck zvV@n(=Q?A&kM&Awpb0*N z55KCsO$g~@1`?C84ie_~jQ+sStFR6zpjpU_!T8$}Z`VJe;6u#5&6>dN&x4N=>E@gM zyYfADKM!>TuE(j9_TmupmKnwFOcPHCCl zwA0)W!Z)sJZe(a~P})ivdq8-06FhsLX7+jnGQHvmpFFdMUN=vg(9<9dm#pE!r#S%TwysSwE$113rb*ct zMBHB@$iq2*=LJ^tNmU{prQuEQ}u*#A_24&5JsZe%DWQ5N$CzJCm#FsGr2<4b3d_M9GOggQ$_IvG=4;55$FwAe1U!m8=>A X{%TdL0^t8GsnvryO{=v}FIx0Jc@k1! literal 4715 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 diff --git a/tests/testdata/py_requests_docs_indent/expected_actions.json.gz b/tests/testdata/py_requests_docs_indent/expected_actions.json.gz index 1d711b47fff7ddfe106d254b6ac5f19a86c87d63..6021eb372b79790781c95b97fb0aa7058d1755c1 100644 GIT binary patch literal 223 zcmV<503iP#iwFP!00000|Fn?7YQr!PMDO~FWzRj>NgAksrIaAY6A(=$v%3imA^%<^ zj4-r?#w8aW=8dG`T^$jhAsSNTj`-a2Q;z)JLW;^Ay*eVIYdI^()ese8rCvx(1GuYA zA~r!z*dGj1iy2(T0`NHsH2=L*^M(&ZoA=bb*si}=Zm%}mO*?~#Lq*R`yPn9c4jR4W z_wJk2AJhJQ*@kxAeBY2XOv0KP>ZzZ0n4I8dH-6AO;0VKCH1{|p!Gk?FFL!zVebawL ZueQrYJEAvt`w9R6|NmbzJ)HOg000d3X#)TN literal 392 zcmV;30eAi%iwFP!00000|Lj!3Zqq;zz2_^Q_5@WGHBgY)Gl&ZkQh*ai@g$z4rrTY2 zW}L{X`tNAn*s+Q@aHFWQG>3g}pJ(1%&D{)edls!zbRKTMaOe4mHdd#o&g1(G0Pgxa z0-4%26&d&R9*L=9=SL>sOgNvoHE)xgm>KDs9#NAz?xskfHHQpI;qv!|W2GQ`{O}dR zw=Jv9v1Dr{D*PspsxOzUO^V7T()uTFY+l474wAkhp&PUkJiaYIVVeYY#fW^E2=vO6 z`;Tt-RXtv$CeKgdCEnM)6(rp`Lam0hg|$s!MG~w#V}&Is$Lb_k$Nt~9ElY=o>Boj1 zH}iWJMR8UXXV(XkoqBvewgQq}d&AKbc14D=JQ`J&FuG=)3Q4x!4_4}Yu1KHt38F5pHuyJQgx9J|9dJ=G?|LkR)1cm mv^AFJUHWA6{kwg-cs=aX*-(GX?tcXU0RR76E%yet2LJ#&0Ky~y diff --git a/tests/testdata/py_requests_docs_indent/expected_ui.json.gz b/tests/testdata/py_requests_docs_indent/expected_ui.json.gz index efb3ce242919af68055500aa271d8e45626d177e..9e18d3dada2a59f343957f84942645a61f4f40a1 100644 GIT binary patch literal 4717 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 literal 4678 zcmb7|e_T@M9>;5QHMh*WYvqqX*P7N<)T_;ie3^IF;;xZKb9b8=l(@Ee){oJo`~_R3 zSt6xn=KR5uYceg7HJu`7qyecXWBKEPSy?H15y~Zq0Uo%=?rX=GnZ_T_>%7i+Ki}`? z^Ld`@=g;Sw z^EIC@bz1LJ`@1nq+HrB+Xv%@E3Y+;MlrLbJtWhkhrk7GJ3%+l7UFTX(-62^6zhseVTqhZ*BTz^!VIG4=3?Jz7 z%c&#WB=dS_i&~Sf3XGCSnMr1EBgzaJ{B$3eQ+G<%!mnAnG#{%3k&^pd53}$)c=pKwFd-n^ z-&&1aWWgmJ!;MUZW^9LK(2!EyyWbq98YaM=y0IdrvoR%7GT#zb-g|fgyVrH;j3Q7w z2+VEs`>(VAx$uKd@VWO4^97~hKeMfO6Aed~w0ntjt-ozGA6B+|#gJIPCz#hm8fQur z>x*~cM!z9v{~yEaH0incyja}5^R6UHJpD$$%*Qp7@(uk_zifr;7RnL&8*14~*R7P( z^q}37o8MI_hBkQi2O19R zlE}VDYvKqQ7pep)bw6IF;XGZE*lo0k6T)PYE{Ji$ah-f5=*CsmI-hYj?NzB4&31N9 zJnl`G@7PZ9X=%sgn`Lj(<`=vfk6Y%F&i0RQIw{N`VSt zi{@IeBObTBP+R%_9$$>RwpqHI=2h@*Jnn6m9CmhmM6NKGL<(l)I&PA04JNm!Hu>P( zfflJZEwGzHeN6u_r$t5bdB?r7Me0Mt7u=1#K#bfo9ak1D`Pl3f^OFhLZ7Q^)v zn^VL6%Dn>SlO`pKcMbHLoG61Y*?)XbyW?uO5vXbK5090li$2q zJ%g1=ffL&JfMo?f@7bp9Ni>;K!RDG<(RT4nL!ucTudnsp|KY6Dep1eObI$b_G;^?O z_h_JHNRT}$zC__{Vnnx+TR58tzTM=%5xqlw)%+o3PZv~}%0 zNoCs0f5n3w99ZKUR=Npr&A})h@O4Xd!PC$CnY^ zLY8rS2^A``H*s-jML$1|n1}gD$Is;*$9{xD-HBfnAOdGWqUF@eo%;}h)7L~vwDCu= zL>=;mozi_OIVmy8Dc~-W_Ea-n(1J|hRVlP66IdXHFqyz#q|n=$z#=Jx%LLq{J?~@! z7zaE!FG5T@QnxWeeCShk_du$gy`VudOlfa0E$ZebiLPa;(pBNHaq2})* z)?m7H{4;+*H>)1KhX|YnIayAU5%D!5aN3%aBntI;)X0!C|L5+{AW`T#@U1(N_KTPi zRSEY^F*6FKg23fF&=C-j-htR4(0m6v4FcEhKt&+%+a2iNAkcZI=K=_*Jn^9X0eG#a zVctWKbgNvKe7vFnf4RE!y#_D$dP*fy4WWJ$M&tJ4(z79j8D3M9uuPD z=kPMHA@t5_-bRiG1NlzA!to#^sL0ESPN50?{GG&X6k=otAwNWBL!!{*5X>1w;Pf?7 z5^e0FY~GHX`6=C}lBmSZl*4S~%)gMC#O$L3FKEUP@=f8>X4)X#2yoB@8AgCq6Er>o zd~1Rn^uQ4lv_KDJnxI8`fNg>>df=p~=WRW3nt%s03M8ae5_!R;nbV%|yGt#u6-Fv{^?sY&ZFjUK;AG@N5Ct4fuE!3EJcraw zzV;A5e`#rzUn%8brYPW8a=rJE$YO1#jiQ e{ftY)O)T5TI^;GN`P0Z|V|!fae>H8+oc{sB@o+5w diff --git a/tests/testdata/py_requests_dont_use/expected_actions.json.gz b/tests/testdata/py_requests_dont_use/expected_actions.json.gz index 05af8f1e01f3c6e830ce486bb568cd6052c81a95..3557ef77197be9927c9ff783bad668abf54e0d88 100644 GIT binary patch literal 450 zcmV;z0X_a7iwFP!00000|J0UIi`y^^$KUfQjGy-qJ56%!R~aKXiF%m1RjJc9RL_0Dq-KGJ(4Og;Jtc+wGYKe$0y2 z^+|ZkP9_t;(>uLn7m>G7wwkr^bZG;lJ;ADSFwXtS3WXVpvnTF@7=BCvVrp*}$q*b8 z8MeSptC#}o>Pmqh;oLhMzVi;Mvb^q~s#~>&xc*NN*PDt#+^F)g5jP)0e83~z0=S1g z2DnzxfQQKh8_{<-K`?|XyP~eRA+0yfCjmxuU~VzfmfYfM>+Krr+#-o?S&^(u9ve8j z?*?b)2rIaB%bmxvy>Pgg`R!6MCnASOh}5x2e#w7O(bfG2*5R`qjLYrooFxdxo##5! zgInI>$CdW#4cA_M3GY$Qnz}!7k911~`sqCtJSa~6&u$_^6l^~eKklm0-1b+ER-d#V sO?aNuE!a65`KwShs%>~LSLWx|52`|lZ^hfs00030|J9CN6x<2`03+tynE(I) literal 442 zcmV;r0Y&~FiwFP!00000|IC(Ai`y^^$KUfQjGy-qJ56%!R~aKXiCWBDE7(fmIPSX- zXT|H*D)f#k>q`szE8(x7EIDt55b^{eTJ&-!}nTc!WqDi{!Wb7ZqJSeoP%6>|k7OU*{}AFzzzfnI7Eo7C)}E zS8urX>T7ti>8D5Cz-M#E-jbG`Ia#qtzGfM-vWnx&=FD kBYzdDMzsy^<;MKn`|(r=@uPVE6#xML|BzktcgP9=0L81<{{R30 diff --git a/tests/testdata/py_requests_encode_files_detection/expected_actions.json.gz b/tests/testdata/py_requests_encode_files_detection/expected_actions.json.gz index 43b7769ceefc5778295b0cffe8c3fa2a8d32dee0..bae6daa21936e8a3cbc4d43667da87fdd7becd23 100644 GIT binary patch literal 445 zcmV;u0Yd&CiwFP!00000|IAd;j+-zLeCI1x^tBH_uW;m7stOsrT--X|XuU*@PWSJX zX+%g5(_VXt@{)(0jTq0&&T|5g9+15umu?_Evj|S^g$KQTr@CnNHcs zzQ!6sRu`GFszn=?SKO_#BI<6j;O?D9Ex*3vs~1~kMg11$cPe8MxrINdtI?wTZz0ld z7c^PQ?+4J>qx0r~&~35%4m~jpF8o(RFb3JL)I%NdrmR1`txa#*Q}ZUhLAjIqEa%>= literal 458 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 Fe*lFu!b$)D delta 3465 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 E09xxWDF6Tf literal 576 zcmV-G0>AwqiwFP!00000|Lm60Z`wW($KUxYPJa6RDprLx(8h1o_ApJ;s7m{^OvE7v zq_}owUqGzt|2{d8ER0gAo7QbjKmx_z^X2UONZ-5b0I($*n`*^4uw{>R-IAD4s+DCN zK6L;9?uy?^aG`mY2*M(~P?S!P@hTF4kwLe@Vw`I8J<=)btWYeORL$y&6fsICnUJ~f z2vuT1z{PNM1qQ$5Xz4gqp>okY6Gq%ZZX}26%MUQs2563;a0PrKg|$4o-0X=!$2T}} zduuxrL4w17I&+5-@_%@n7UvUY-36Ii0zC!FGl{kf@tWM9HZV;kzLMzzH_6;*lO0Hd zMU_CRib7(Ytcw(L+$(6ek{helP9<)ksPE@;Yvqv1!eXi_25uOgNR z7i*ep^~>-2XMjl1()h3si7BCJZK%cSx7kzB^Gkc`)J*EnPfyp)qP9UUxJPFYoIXrv z-|zRHHaxY|yi{r)pPd@k_txW{Wprw(Y8q8PdQ;zf-8LGX7@PUlx|-ZhHb2D#uK zpMC%AVLk_*=Ra+BYPos2+&n%#HLmlm(>=@l)N<84uJ#=&7#wn_)4}cp)dBe2x&Iab O0RR8?XZ>2@8vp?I7avIg diff --git a/tests/testdata/py_requests_make_json/expected_ui.json.gz b/tests/testdata/py_requests_make_json/expected_ui.json.gz index a304bc3096cfe2fe94933c266f7060989491eafa..ec198bd71d721ac3adc6b348d4e849fd9eea5b00 100644 GIT binary patch literal 1113 zcmZw9e=u7I0Kjo4e)MR#RZ%LNy5X84J4YDW#M-DN#M)k)tZVk{mUKN+F%nwixrlaM zU5CYwQ>CE^I+dtvs!i0>yJ4%Dc%fk^?arDf!qr|mFJ3a&yY05yzJGrH_`XxI!|6?q z<*CuDdynoOeD$cgb-c(=vZUW4@7p7*4Uo2$2Mjh=6?%KEoiw>deoA2s#D01%+jhmPj=mxXm3yUs|&OVPbc@qUUBUbo`F4G zWV;DJ1&`8WQe&%#FtJ=#LqLM9^rX~-Ro*ZKrm&z?sAHq?d_3Zh_^SXVPy<$j$1n!Q z_&0=Np-8>CUJ0}U@J*iWM;3GhdKce?e}}SBHcT0(F#m=TbOfdtDQqYWiom1s9`N_+ z!x@+m6C(9Uy$Wap>c9r@qc^}cbCo~~Pz_!J8JI8Ti);gW`_tje=mGQqtTAX(p%0)C z+ylRgcA}lI2G+137DUF$`1gOoQohOS6NHO!Re%bp1#7{RSS%Kcn9L?6a0`%w*TD3D zf-%ltuS6}*boPb!V_@af1uwsy_kVXFbNW8j#JJn=Bq#%co-vM z#Qz11X}b?1!x(+ZvlSn?)n!wW$>r!8q3k?;Soz(dHYX-a7b z5w;(1OB-);_VhI$m#RF(oxz;D?dg$R#aFI=5r#o$wx9W|l;J7X4)nO{KF)mZ%#Z38 zOLP2reRPv&1fa0F`n_jxmBobKqiU~6)q8kD^unDH0tMTxF4_=Ds0c7$moDxUj}4T$ z>CR;`33D;s9a425?V`IeU4tbQ3W`q_Da9#TzaW*g@tYDZ@*=I1ufw z%g<~f@DsWxq&XzsGTr3$1eH`$wF}ayw|Q%s=bMearILO=c(J(n;UQ>NJw~bQ9p!#) zO#TA6W7yc*%+n`DeZKjb^@3J;XE@Aq7FN&M1vB=aWt#hu z-DPHndD}Hpu>;wa#C2;*x4&(8^(M`lK4hJ_K`l#sSkh=r$qnxn<^Q^4MXF$g0=f(ZJ30Lc9adS4 literal 1056 zcmZ9>drT7t00wZ9i75+gJ4;|Z%A|~P5QWK*3K3xr3KMy4A!i793hk5>T5Cjx;9(3i zP$*OC(oGVJy=9m+tPJXyzK_PpJey^{I;^?kqZjaG)w zU!gaQKZ^ph13%uzl;ugnpsQ<*+i^urH=h}!Qu6n_(g|)w05dC>f3=)?a-fBK4J^6q zDf*xW_pEPTN^N{dyF3ok>7iDiXRXx2^xCSUfnHeDEiHHk$Q6Z?)D_fr>sDtq-8zSe z8pUz?`DVJh1jLH+dnkq1~jcPYP#TW z;CJwH{D*U=!>_!E*O4*Am->o|^A?lEF11^2g>2A_#-wrd0EWFUq6+SZ-^D+~Zy-;Q z0O}4E>OD*zb_w0WhOP0j*8kzUd);cV8D=!I8WbLYvvCpLj?5t}YLH4Th(9#g^&gHR zFHtwBz1{#az!l~WvvN1M(_*8z%hGGfz|Z0%{jh)I-)Iu6ELuw@UWvCLI)q7mNpZY+ zWS*p}Mv=C58*~LVUO52i_EGq?er0i3~m?|eo(hsV#N)Jk_fZA4eDY2x= z36>0j&$3Drqz%AMEBg%Liw?hcK3UcbKyB;_f`u|dB$MF#JaeM-Gr-WsK1ZaXj8Mr8 z*ugU=N$&%Yj4dR}&^}N3^}MKRq8e=ulgxn*o|!BC9tdt{O9&a-94=V`6SK`J(rG}^ z&aNSP&}Npzc3<>p^Q?{$A=w5yvV~6bRT5h1CSmy4(bEwT%J^45Nl@0pEK$5^w|wl; zN;rZr!#S<<&dQxS+zlMn0rSoIGiJwGaf7L9UK zTAjTydi+{%ntR?TZmLK~wpo@(WH;Sn=R7Zm9H_exMaU>DEK=mynqySbMJe9_zx<9~ zyb$#TmAz!-O_0pUP0FAg_GC_Ql?=}^Gt$z){;jj1>7uixP;?A#?G5#NuPf=)ZrEFwtj74q9jK;eS zA>X~o1UIx*NZLZWkc$uVp6xfkXRJd6AYPE1wnl70yrkmEk7Uc*8Yi~!IRXGUEZ0@= zR&5*-FZM+-R-xFgP5{A#ej;SYNUPBc`)LvI+eGO6yPq9P#t{vl`y5N+=Vs5|y~(TW zOhco7D0OlYj%%Drl7HH5ftta#UxNv%O~t5$F`CvY z-0eU~(;{eh>9?K-3M=yezOcJDGdon!S%MFH?yZ45&Ys}4*KH5VqBHLq+&nGK%|`oD nV9<;t2N#DsDT*X?3?$jx=p+L85*@z>00960RReZ0;0OQ!r)#{p literal 465 zcmV;?0WSU@iwFP!00000|Lm1PYui8&h420q!}ici5SC@hiGM|*y)`9XNuy|}yeno# z2`1#f7pX?Ltyi%_N>ZAO5Bp}}z3+`z4>JIBhb-isS%bNY%|(A?3nlNwtl{en0N`Qx z9ff|BoFMBkJ}AzYXx8H-fKkT&#Mnxa$H89MwSzzrKAX z{_-lx76%%-@<7SB^k+rr)@}QX&#`ei|I>yS+5`M4?xnxO*Qzq*o#K@J zt8?tXIf}`6C|$m{qTJyVa7%3P0Luj294pWGjO~@SAr<9t=roQ4q0{*4EcRiOr@)`^ zu{iQiI(>y-g0d)+yFE%czc%Y@Gm&c%TB@VD{!hMC-H2MnCn6+iAVM}@y%5U0@x}L` zg=`fsk6XBm({z&J>pc;tY)2MnA+%}yjy4pj@Y~ diff --git a/tests/testdata/py_requests_only_use/expected_ui.json.gz b/tests/testdata/py_requests_only_use/expected_ui.json.gz index 06531fd584e964bf25d75c3c2051f52d75269ee0..fbc233560f18033bc95f7e00a5fe2c3b0b6795f6 100644 GIT binary patch delta 1437 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 delta 316 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 diff --git a/tests/testdata/ruby_sinatra_fix_content_type_leak_in_muste_4/expected_actions.json.gz b/tests/testdata/ruby_sinatra_fix_content_type_leak_in_muste_4/expected_actions.json.gz index 929aca77b0f04c228c695cfc70e7a8591c9afc49..1e0d2e7c8151a7f2b0f354a49c8c276531c36236 100644 GIT binary patch literal 507 zcmVcVh5qhjDw3C@=Y>=YW zzI!zRrNAcHZ3`;WUUKkfMW27)*e@f1=s=#ev(W~k!!#O)66T_v^v=|1qts`IkJj7&%UYNS=%%d~T(2V$Du zpXuHjV&0Zc=|W$&T#d1eXT5K8k=};mKdi@kkYt-c#QW@IL;RlJ0bIHReFSeth4a)k zQI5t8Oq3>zzKPQL`oW=2+oCgSJLIjOk1js)_J%MmlQ$k4JMV|zmKCvVub=xexzsz! z+;ul|SC#>3*UkF^-$^DJGAZzGFWNqVv!(_uV4m8=aBQkkvOs=s`=nE65C)arrYeLo(!s(2fDQ x(G5LeUIQ94Ic^znjuw<2PHWw}S&NQq_TXua0Dg{Me+2*l|Nn7UIIvd>005_N^#cF^ literal 572 zcmV-C0>k|uiwFP!00000|Kyj?ZsI@;#_v3ZmA#f#NFe;V?j!7RwThgKDWeWE(byoN zs_(v z2&vjKd8yND#X3dNqR9k^#8ZewxD@hDVi0y!E$HRjC<}VYi=6~5O|x12MkK3VrCFRF zl$Yk`EA(XLLIZ_UyPO4u*5S*oW|DC-YBiH&AI&({2TpsZ2k8VxMTUevgR!8c^K_D< zA}e~S-yhOoK_alahA57a6G*XcZbnszIN(^(_<@Xc9E4=*zpularYhOQGo$WljJz-gq?eacvg*T0pyM~wC9v)eBvM-O~M@O2)txQiI>5iD5 zyI*@?y0M0sKXY?Ub=2b1}o zLv7ZE$QhO2(Oa{&bH4aZSP@Hp-0su#y?&C+O=q)o>*Lj}x%0lkPm*DQObWc)h_;X5 ztl5DU@+icxMk!Yz9Ax4LUccuY1cS+rs5-qW8X!^=&9-W5xdUtf%nCq?7EKVPYq5m$=^`}2 zEq#vpHEUQ)XNrckw#=JDS|;=6u-2M+en`7uesb+pPS?Sjfx91=n-y{?msFgT9wHS< z(xar}j5L*0q(});ktQWcg;Ls2DsrS|vjUA?La$0U?{m?JjqB)Y`s?9Z{g= zE44Dz996jvnD{TSWDPxAC42B+JgJiP(J#S_uFX!4Kt&LQ6DPNdptD3J%N>Mjg&(6SSTabA*D<}M;mELO!>7X` zthTcXkL^-@?RMsLXKs3mjLse+N|EaXg+#9r_h7LPMIx~Q=Nun;XXq0JP0~lMEuxu^ zH61NMHO}5c1BDzn@kA%?$V)RsY=wWJ>hj1wudg6N?{xwxqUvx?q*9~C{lyb{^$uPd zC3k|~CQH4`pv%62mwmZj`qy}_)H)#jc5)y>=WFl^F60Q5>wvhyPavCkGKgs6c_7a4 z9%WMjhbxZl#GQHj4QdCtjFRV*$NkD6LgOFEii@;R@;pwwvZ(_PgJP&>jGDLGC=yirKLw>t{*3OA@BcpVV#fz8c( zgb;R}v*-l3&(-k_>RY^L0b#?%= zjZ9@GzZ^_~(fLuvBI@PVfZ1)>6<|*8=6EE>@$8Jcz zVFa>20bM@>EcLnrm?~f)qYunP8ORH!@*w}<4$OAg{sT7B4N5&~C$I$xlgNHD0HjOr KWYh#hTmAvdO>ox$ delta 1723 zcmb7^eN2-_9LK4mMG8Ja+#U+j&f!aDHeO<@gMiOEH~GUcGM$0xpoL6e0fz{TZg#!Z zDw!h=@sS}f88uAz2NGE7bk6WR6t;nbhoYVb2TWGCz-oUj`$qrlBH zVyx>sDLYI;+YKYUj{#@D6tIqZ7Cy>=WB`rz$~ZVREM%<^UIcDxm%G3)unQI#1`X2% z;sJwu_`%*3d#B-pl(9}jW{SJhkd-ppX~;-1mN%B4wFP#|cZZ==H=*Ju^$-<&s)snu zPojwL`4mOy_({FQRX){AnE6S1!p5icq%(E~@ROUuS3ylZuowOZqzXH)W)7^>!mi(L zFUwa-o{q~#CX%u$?UzNQo3dVG#y6AQu;(T=k)w3f8qYX~@|9I1C8Sf9R%7&xlzjNO z_wHu$TjzY-0l5}wn22OXs^-Bpk|H9X0>(Pz(ca{gayVsp=3+6Y7(eCZ3cS}#G4AUt z;t+VOub4+{LyZj`=zXSk0*_w$vi6Mcg`iCs6W)IkXb)vEwajTnjah@^F!j~(TBO=@geQ% z<$?gSgo~8Y8Z~}8>@eOERy?cBkaV-o2l*G^1>xuMsPHMTwxB!Z^dati;2FXuyiNG_ z-xP;_P0J2(x67k->b3EwOu7|QM0v>b@|Gi9Ui?72dWj&< ztXqU!pk*pNCZZ94Euzk=qv%((OwCP{x9HRn@dGAZkRXpX`5~Kd+nRnnd2R8mR-(az zRkUe7@Qn2t`2O`f{-Fe5{Isu}Htj)NK?22?1Z!94C)`Vv(@k8DA3{uOgyTAWx-5`# zYSGlKg{)=C^}f1Cl@N{U(?1S$n6jfFk9d)uA7;~Qrt zJj;P6CtBtr3w5jJ5({;T)!8$fI@aZUy%*e4KU#5x{Yc#ngRUf3a5ol_}fu%_3Y@q@K zqS>?I$LBmgns2n);~T;`CpI*rMP|uj_ZH?gkXBo z0j7tWN!THU550f5M~!Xys1164AdW(&9!_4ADznH)<$i0CBi%9zZQVlP94pr=0R~uR z6MNU#$6lSbHv?C96kr=&uNW{z5nSm8iu2IcU`tjOvF3(c0!%enrR=?up;$*YfKyC1 z76)%9n#-!J*w0v1w4$ghaS{ntRP2Puujhj+`tm_5>wwFAd>~Bo$eh2%aD4s*XVRy6 diff --git a/tests/testdata/ruby_sinatra_fix_proc_template_memory_leak_9/expected_actions.json.gz b/tests/testdata/ruby_sinatra_fix_proc_template_memory_leak_9/expected_actions.json.gz index 2448c1fa59197603fcd421467dab11f8c858f9b3..25fd0d1da4f6d27d6ad22abe11deec85dea3f25e 100644 GIT binary patch literal 1349 zcmV-L1-kkliwFP!00000|Kwa%Vw^ zZ9LEOz8(MU7rIx=x|P}-Uq7zYs*wIm|EA~pM$7JrFLp-i{>5(Lqd6{=g{)1vE6-Oe zv6WS~-01RM7PotWg&NiguQq^9biTi zI{@Ev$|Jx!;OK}RC%KMgVZO)d}eRMqQr7DSk?pRe)qP|CU(l!lAv7h6ix@TM)T3|BIO z>p{KCDX4DcPH8!0ylC6wR-LK7z-ozmx_Q}jG^ z3TM%YVRTC3-XQ-~tG6aAi*859zyB8ci*qd(EfN7T7Qp8^0N7ed7C#TkpfC$1S@J90 zyCzu&&SOb7#XWM8g0RupQjlRIl1w>DwZH<^%wEj+{Tku6Jg$&oZ8f!h@$ zk^NY0#{zs~gbSfOoD&w?fp6>t;Vf;?gu9En_v>9FjFB4070d@nWJ&TY-weA!+UTK! z_0Xk)G{Pw&bR>1qa2dOdaHX0CYbQY1blxNOA>eb`C zlP2F|dkf(@k*&aEF?b!gV4+{%I(f{hvPH`w5$ubJrFz?9I6iLLp-?{tbg*qvSO5}B zDaT^SI+$`O)ZoQGe|!U`)YACgeMkFvVVyTUl0;x~Z>_$tD6-4P<&)+|7=dC=#!|;M zK*k6t?lI>mPc6jhBS{1UM$U1La>^$W$Y>FiK}tX{0_^*dF%Z(VfCwy!f`# z_rDtRF@KM^uN%M7a_mVbBmfTJHB#3?e@x@^A86nOw}k0H7`@Jec)U~>!U$|{@Hbt9 zd;8DAJb!A3e14I7KaO@A>aK-X)vXcdo}*{!pIYTJv#=ZM#m+LpRjEKNzhYZU;7OIl zR_yT9@aF1p8TIto{?Gd&W#gH>^vb$4rKr3{n7yZk*-P!2y{M0im1vEpYAo#w;ig1L zY&pHj<%WQRA!Ri5HLBAL(9wwm@JAgXar{dWcmPl4M0ARW+<4yKoA3Vw00960{FL_@ H^g{pua5NaHB(|ndRpUQ< ze?57g=lwYT+YPk07F8p)Io^I8sZ=ig=k89=^Np766<_R()ZLBkzNIh-XCJ0BOhIewa~IMR|dIJ`FqwFVdSCx zF&Io3k_ZYWP03|2swqCPjDx4%m>aAQ((F}^VM${sd>%%RgJtL*%UtdT343;ZI>3x3 zb^yL*l}CVGfTJUNuvLe;C}p-O)%IIv9EFBQ&CmIMTt0865UlPyM4SlXk3&9tYg-9=R%l@E*(#%pqz zFlL6AVWoubE~ zQ#gxG45L#LcLDh?TD{g;k+(BC{{Oeoch0q~Xpjt$u>fAz0l?NuviNaG2Bldj$&z2? z-X+OeaPCX8Dcd6_DF_>lEhQN?GRc&qR0}Ln&Fp1`Ar*nHO~L~gD%QtifMA?P2*IM2 z5R4KE63kXLy8yv#VH|t;f(6c(N0L+;xKAYJzyBjI-~Es0zYgTHt=R6dV|fH;8d|C|Eid(&aNbF? z-D7hLVV}rW;^7S51-4+JUtU{z%*vuc?T`rGi-{$_%^8mO>vqW1aBq~t=1E~ipq6^i za`m%uXkHliSA}`44@m@8rq=c}r^vcbDkn8RFajk^jHL@3Sd0-+nPSdeCz&G|Fayu^ zc|6ePVx#4OVFngs9P>tF_ugoMbcHe=z-wu%H)#Q4xj)spkyx{87M5a$LCpDmi8Ycv z5DM3#%u>VgWYe7{u-y})9-j@(+Nvr)K2M;4#T*2TU&d&|lIp=Sz_2f59;)jaS!v3x z`SEz(JfCdt@t$0NaQMtDSg1^%jUyztBk<<3l;+m$7Uy%TSf~boTOf(AWACjEMMxwA zYIFsOZJ_*X3Yn^<7Dnl;ER58r3fsZ{J33SN2r9nLxBXXRKDOT@+t-yJ7%jY$PAC8t zfY(S}3H?5e&wrqa7kr*c2h!+uF2wz%Iu}M@bAvxf8l2mI7UuaaC*<>U%G+_Ydm6m7 z@T#gY;&kWeSo)_{+nH5ZVvVJCE5TK%KqbFpQ%m4Bi^Nv$a5s1@cm(Qjp7V6b{?Gd+ zW$l^0^opu5g($sRn7yZk*-P!2y{L|ZrD%+&Dy--W;ggDxT({-j?llB(3qwSmdkt5F z38uZ#z~`QzQ+o6b<{XDFLyZ9bFd`(EhdV+O?;QMm^>rV2EpP1tzxKNMxNAA@d=-B6bsu*v_0G@XtFQaG zYkBMU@2ju-xNAA@97}%nbsu*vZ|$mo{<<~5dka7ATk5SJ#Lr%L*ulXM?UQ!tUSN5D z>$rCp?(QA_us`^oANNapwcv-|@@KC*U%2q&jw#+bhW+{L&KEBHxM%uG>%R04`V*D) z^Vgj(S_rps?03`~zluM7-N${*ePbW<)7O36SDb(9x{u%aRIRU5ZGZm$_kZ}}b8Yt4 zxf=VhuHHH$5g*pQb-41A&wYLTx~q48zO{DU{jznxp2Pa}9M)^yujjCSJ%{y+S@-KX ztbfuvdJgORKmFyqKmYX?axUuEb6CHOb-$j&`p2&O^&HkecHMv7b6D^A>8GzF_;~B{ zNzS#rw}<%Qm0xtypyqp zJLll;m%bwb-y6ZQvts=QXx~07_Wv(?ebdF4{sr%cm2dr8vW4&M4`AiqqW0FW7OeCy z+zG)GWE<5#Vx|6>z^~$K-8&yHo%8W5=6mZtp2f^}emTy^kKB8ofL-`wAD!QP`p^IQ RzX1RM|NoExUK1ET0RR?1Sh@fJ delta 565 zcmV-50?Pf)R=`$}Hv>6paj`m~C;>y0+$czYpSEt#{JppE6Y|MR;)e)rcOUAmW7-a6{tg}ZZq zhd=BOzURmN(q1e0p|||m>&_Q0{J3L^caC6x{<`yp3qS6ezS6oc{e%8QWBvSf=ZhA? zO&t3j^~SH_Pha$NcnlANLjKAG+@2cRn@i>qOh1zyJLozW7X=y>+I>KCG*^ z&PT+Db#EQ6{NyuVAHVMEoo}sOcfV|Z-LGe`em#TrTKDT2tY6Py{bJVrdIswswC>k4 zSpVF0zn;PRPhI!x8LVH=V152M{1-Wc^^Tr?`Z_|7w?3cbOv~;czW>u-zWeiEf6B@) zI%V?SZ~SYcBI|zePud@&eD5tkeu;vwe()`SaOFGixVOsK7rrC2;Cn0gp8P$3T6lNq z>w7%k{Gseg$S?i_f81yMlUIJ(X(@m6CrXxn;d|~o?d{h;^q%yj)<1XUJ15}om%by> z-W$QPQ)2ywX5T&~_Wv(?ebL32{sr%cm2dr4vW4&M4q)Zpo%YtR7OeCy+y}wKV;j|f z#!CG&fnUYfx_3T0=i@2N_tt$NJcXI>{BrC;%8z{le)H)+|L6Y(00960I?fi>+C2dP D2%%G| diff --git a/tests/testdata/rust_tokio_incorrect_confusing_asyncwrite/expected_actions.json.gz b/tests/testdata/rust_tokio_incorrect_confusing_asyncwrite/expected_actions.json.gz index 7cd0d451d5a2ad298145a8c3d81414390a6d2dcc..fedf845179d21fcdf666a8c58b636e2551514311 100644 GIT binary patch literal 536 zcmV+z0_Xi7iwFP!00000|Lm4AZ`(c)#dm*-2QB|4NFqz|-|^O=W48bu(mesk(G*=g@I8yi_d6Z+I02#+Ij^jV7Km1HbQYFG!O9vREpR&l zfXB`6UI^B-9B0d(!z1G~z8Yv`%4a2+?}Vp)(N>q)O6ZnO+AK2E zy=KQ3>lv*l=g}#xp$wA~1*20eG4SUIF?g_aw!N3beM<72jRz_!CijkczDLamAf{Kd z5fDi-`w3z)!0|$lm89u+^w_a;#PhL+is#n{4b=!2_W8vcy=`4VS*0|M7IHb(*6})W3-R&~$rv|Md9V|Tq3Xsu7KU|?nuG}rB^WFTdAIGenpoNr*61Fcbq^lO1jBJu z*CQcKXX!swr=u#YVOle61%ayN*3o|+Ed0YcZY04jzf-}eMUO@pRX|l?e3Y;)dsWi* zj~oBd5iv{0Mnw8I@KVN;<5PIOZKAUzPoOoE2^ab9-SKDWq$(sDXIB9VxqEADtqO=R z&{4H!d(FeQg@o|OSS88WI8WmjLOQ}~^sH}0_5VjewH#qWHIr(FJ*sx&0B42b1`5nZH}R^pO_-%BzxznMwi2SBzWAGEXC4B0Br?&6VCCkUU5eqWWFdPo? zq;vp#p&7beI?uwg>Cuv~0jvar6`@*t%~YW!R<4G#rpMa(w*YOU;rQ`^h3EOA=NLqu zPalsovh_h3O^UtnaY%D1d<^!Ji3ZnsN%KaVbRZ9jD9U_#A`BPwp2Wl8NIC&Z+d!T# z0VNtH|Hqu3t1qFq@_Xd)b;H%mJ-)fX=mPnGwKfLYGI=2xYt0Hr{tEF`5vOl9l{aJ?gqy7kg;6=BwF$bk!UJtw6HDU(m=>-{`0tk~|iBH9aoPxPuKTv0~}daM@T(L>BQEUSN9IAwj8j3u+E}g z9Ggc`TsJioG}Sc%|1pKVMG1hvS`3wdv(BT|)x+g{=kJatf%A93{EKs~qgLYj7Vg!7 zcY%}O@u%8u9rrF^o@!<(GOQmr8h6`k4O|R-Xr}ohu+cU^Rd_qnB*qKy&pK{9Ffi4e zqyTHV5leL>dzyh81n*epg8tR|Pnxnv)f|)`3Q2l>M=Ri-ph5G%sEh8T)7o zjKhry{>4JUbXC{*mpllIT#YzW8VmuEEIJxIiN&kt0WigVbSmU@V zF&4lYoka;uPGzzb>DGuw<1YJEgC!W=Ka+WO{{H8kI?JP>@n!L(wY9+*ZvWI^34}L8 zVJ`%N)dSq&#Lc*ojHY)iJ~^YC>|K%1?ue|{TW9l{P5Tx{U*>jSexh7IEZ;IzxaHPI zi7i2i=UUr%l(yLmxh6r*sI-awi>an8$ad4@okQp!{4@22+8ZDY4bG-MReOIy7#;LI zzD?u(C1HGUYo!MLZcM2_xcBMNyFqb3znLDh01Euylb=)K6Vy0ru{?xW$XLuzl6KJI za6M71Ta|Y7eDp$*|JDxtY|yplH*r)ZUr3ZED=*PE;AH$00mKxBI)9fWo4P8HNn&+X z%Fq%j^P({PaK&UGd3Dso61Lf-N+W->PjAwx=el?RFa0+L?fFE0m0(*$M@C6MU92fK&^0{2%ydSd z42nVoLr*-t+|Hg}Sywe=uFsx<66iDc_Em(}%ey;f-r(x1=G2X6AgAX>RPOFV#jYAI zv=tGC%86U!L&o_+Nr;UBS~llVN`o}MpI#?r}b?4lav}xS#@hbjfi08P|dRb7SU)6yG4L0Ww*K8?y&zI%3v7i zA63Lg|6>^n`Jz0Lr}Rsq{~cV1w6W#iyK`U`i9n>6c}&XO zIYYta7>6&j>%=JYW%dm*&1|kL#r)JuH@DL*0Q{*Io9MLJ#=hxW#74EXxn^zSB5*?w zCRx#~LTM?AoSdxBvt*Q;j{5>l9XOFUbY%bbW^g+1xqED(xXk4g7wO2(I_G>}q4Rd9 z3$C9ams?$Jfw_)5bMcEyb`!R8-^zpD?B`0u7;-lQr8X-kG}yQ CqG0C$ delta 1607 zcmYL^e^gRw8poXtrI}eXbXqZg?HQdkXIcjp3`m)30&T@vj69ubvI(vvbWKY^J8>(abwKXfysoWe|2uuVzC8G-MzKcwwnMXZQKzJwVsoM?4FE6|M~*T0T!Hne1BEF;fi{UeDU~PsO%VhuZdV_redhKQVU| zL%^#onEBMZdh*=~_n6xOS!!!*MMaL6D=U<`I+5_4d%wy8A=8aoRXnt|q&AhRJVM8s zea)(d=TlNr5I5Y|_$#th47)w6t0K_>P450q<3j}-FV##Mod*uF`R8wQJ9{bFg3nVT z{)KL-m1=#cQO1k!T4g1reZ1s;@%ng{#1DR3sHaT_2k(7!H zgTe?zjO=jAAlT_&>TNkn1@R6Z&u0 zGx8X5urIh5p4QDcVg?P7eUuQScr^wTy>K731>>ktT+Aa|xL zgF>xAa0L3=cE1hAI}hnBn~^`61$@`IYcvnl$0Zo%F2?umIoyjrTmbav2lu}q6g^A5 zuvp=omcJT2C|bF7ez_#s^k>1+yFBfU-yR0fx5dw0jlY>s@K2WSKl?*1;lV{!bWNx; z<6h5zs=g-FozdU()@1a}(BILAdv;FN-wgHB5LxS+r!o7|YHt@5|3t{!&^(VRPTM4{ z`czSXrzvXYLZzCO@o*q z8eW1WD$Xd!81kq~lDKdjpJ^&<2RY|H&$n)GribiM6eyoC#-pfGMFj3VbG2*{9HC{1 zA~mV3wI(OVN?Va)KT-TmiJDGLDZXErrfnGeqh_b~V}XJD(z^bE-L1H!49iN1_PZMQ zKCYY@RL-bZq>a6=*~7vs(QqMfWL1T(B$jyKa+oNfR2}QABBlJx4yn*Xc@<7g{1gi z;$NyW#av0HJ`t?heT(pbm|Zh7Y<-Zwsz%j{7 z{J8X#8sPdyyq86jgRqtIB<*XP9cAn7r8!lW99@em^6>UM z?$Pcm?v7E9wN<}j)!vBbt!WId;NK{=T_RCP4D@0)ug?_#d)E2*csxGeZJYEEe0=@` DeZ^r6 diff --git a/tests/testdata/rust_tokio_runtime_localruntime_doc/expected_actions.json.gz b/tests/testdata/rust_tokio_runtime_localruntime_doc/expected_actions.json.gz index a9ba40b3f7a3d24235f1a22e1573a1b5ece9ce98..8daea692a38b4627dee9e75c80e33b84f0d4a377 100644 GIT binary patch literal 395 zcmV;60d)Q!iwFP!00000|I}1ni{da8eebWhYdHH6Ml$!>QpMJgMgRcE_O}B9wcab~ zv8A^NS%qxfF#(u&7$$6sg>@HZKo0vBF`6*TZCN7uK5pa|O(4u>Gx&=LeutoJUI(HK z3P4jkBuhVy&7}cXlh-9eVI7p#A!sVBD_i!jf7Cy|^3wTid+1}!y=0>_!N@jHBN5yah=qGH0rLkwGNA|l8(TXrHOjRMdA+E&+wI?hV3;2TwZi^sI(RiZp z3P4deBtze|DTD^wkW&>xX)IL6A}A`2tvdFP;quxE>+;Rsc?n4z#sdsVo)Nx00muF$ zjh1;Ubb}uvjuHO9ygr+^f1Uk4{pn9SFPB)md^#mjI0Ee`JTi2vV3xxpQCjg8~-^O zTROAPifXiOPM;sMVwmniGLD(gMEgb9T!W-HB&6SfShJJ zefJ$HiJP=Jimgfx-sC2e5sZz#?|0yEz~8P2S?s|F+X@RqH#@Fd?bHg z5kknf{_mlo>uQ<+KK9-Fmd4ev_;~0^$Rc{^o-Fh_fsV?1(p`Jd@K%J(ulg zRayJbZO2F$8or#H+WDo-&oB*G7g`TTzDI%KnP<~zI=!>!omB7D+-a}35Wx?=2dZYK zCL(kSb6G*zpsa_7pSmIQ%5md=c;8e*+$h`_xr`0v2DiO4bJWm@f zo;X^31X=~pakL7-FA1$8NA}FL;E88gB5}0D7_=lCKuhJ9gjR`_V`wSLw9%4@qa{b6 zRmy=`OVNu$OHr(1l8K2bWOJcaB#u@w0xhNR44&njUJzQ0W(pCHip10SGI6xZ)6rrq z<2YK3Us4*+s6f(qMiosPEtNQ0Y7APU7(nZ_bFE|R4vZHVRU)70Xn3|7Y3il-d_?V? z35DnIOtMQ#w3wjS0kx3N+*3&kuH-B5BTDd0a{OS2$?}zpr6eid)Gl?4@5yHTZ zQe;^5Ua-@0vora9-s>xKDv#~usYrb<|B~?MV!qN%1@=yBvjtD?K91ZO-`QXyF->%R zmzxa?T{V;p*#J|iPTK&#*+`hy4=lf@#fdZ1n~jg?Z%K6b^7oqGIb@+G&~&ZGno$UB znJBZWeY_`nKnDibUJs$hHl!_hF;=Kvn<^`L~4@YO;3z!MDC(M?7rZUfXLDOj7~A3(l}R zjx0a%-q4$km>J#41y-Y=Q(YDRzsHV=f9|K+@9}aLS9pQ!GnrtCpB<$VD{*5& zUz;auZEWaQ_~5p1H+vBeI=E(FiRTPUjd}6DaXE_xf-~&>%gcy@D?JwyNiPB3$* literal 1324 zcmV+{1=IQ;iwFP!00000|LmJxj@vd6$KUr9grB#K#7`+V=oyN_p`~$5gceG6q$77$E|){lL%TbT-m9);>0&g*L^v@C-=Kf-?~3GcZo= z#Y&z|hNjW7kXp}w2|7$hI*yE!uIp7*RV7qjE!EpmEf=7h;k7A25BM@n6F!dAQ!V>d zRhIT^-7w<%rq8FQc6uq(D{KSWxZ1*n-yuSHrpY*(j=!?k-BkB#ZlslK@L+qtBdBJQ zk3{Ggi%SG1y|Nx3x_YsnlD9QXul75qFHMt>z<4BFuOje!yTICP;SwDeurwCBK0||_ zmr!VFr60DFVai96bm*d9j;Yb*yl-k@od$<{EI&WK+iAS-M#sk`I6wbQ44k|jezPJX zKMsDirryj|*?dI%|3A`ML{#yBZkXmHoz+uOl}1igI)th$3sc2XaVJzU5;|WQzs~h< zFjY8ms_+1+81JJh=l4RD2n7|KbgXGiRFTN3A_J)62@6xjPmsF_RUgZ1@H`8kCDJr* zv}ojL(E(@)nugI5jNTJkA`RS`v7nJhSS)h1*buZh=|L+`?+L9el#am}%i>0hM~)UB zfL6wPcC8%W6l!%+xcT@%Q!mNLX>exf|=@Tjqs*FeQeWNU(vbL)Fiu?+Y2iJ3-WJxG@ z&q(BvS?ovXZ`;*?W{xS>J(NeltRs)mRlCCB81iW2)=p8#ssO!{L#@H0ojJ5?v}u%5 z9;wQk_LY|v^mQU~61X2@o=1K^ez?l`G=wf6SafWhU1d7aQ~W*HxU~a$`-;5TE7Z!e z6H!BnplU`h)l0C@L6aqsSMna-GcF2QuwyP`7rD-ffpgb6*toUp$TNN1%GA1SkL$%@ z*MahK**Fczmg7gLb_X6bIuSVuIZ~co6vUkv=%|ckaRhOHc_g(nXk9zsO0|+(Kns8h z{aZr~C0ZJLkhV=3A`5G?mHHVuRTU7vhbN&fOOnRkx%6{rM3Aw|uP7HK7*51ag9jmnRjYxG>n5t}-uo3bZ8NUMiq8uP?%o@EY ztx;jt8!c5&%?pPbA_?J-An*>{Y9cPezo(=fo&6n7MSJd4M;o_xD!DNA?(V5UemjKG z&*){PiWMqMwX7XDRKgat*?@J;Mpa1HbIcPSYN(=Jzej&KRBR440TWaNZrX&A^Vp@! znM6>@WgG0@>AdmBHW5c=oo=YIhJ0RR78==G~+MF0RKoO=%d diff --git a/tests/testdata/rust_tokio_time_loom_test/expected_ui.json.gz b/tests/testdata/rust_tokio_time_loom_test/expected_ui.json.gz index c62020a52cd6053d787f1a7208c5bd5eeb7bc442..b0afe7b4f7dac54b01a2cd211fe6917f531c8cf2 100644 GIT binary patch literal 1974 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 PleM+9R19D|ZesFZwn+Lo diff --git a/tests/testdata/toml_poetry_add_support_for/expected_actions.json.gz b/tests/testdata/toml_poetry_add_support_for/expected_actions.json.gz index f5e65c5afe139abc26eea6109b78ee15547d01ab..f52323bd3847364e8f772bba5e4138863e08c27b 100644 GIT binary patch literal 431 zcmV;g0Z{%QiwFP!00000|Gbq?kJB&^#qa$TBXa=>q5SD4n@Suxa6sAvH;ST3JzH6u z+L7&KiB|jFk)tYP!A=tvdg)=_*nRW!oAzk~z&g@KD9Lufx|qFpB|KQ6q+vVwwgCWm z8a_wCwVqT*L-SCViWA$7eE`gAaurt5z0$urozgdhVyqVOI8|z_sCLqxefj)#&!(EO zsBKyG)}4)uZ8FhF@`;k4h3C;-gPNrE`@?%n+Gnppp=S(aQOH1k^QQr2#2H*X7FEs5 zIcH&V7p$c>E7%M!eD*jQTmE))9=()(bDyvFM5b*x+W#4v1`iK-6!Hjf_iYrV^fB3f zh~CWvDc`1kR(Y0sQFU0iwDjAUq{oXVk{2fitYI+0w65opyq3#_*XC5yYhSxUP2~gi z-nlIOuz$4$X|d`T;yQac*}>=vWQDASq|#zl)7%Jw7{tZ)N)VG(4wgd{(vY@GAO?5t zpiU<@urHi%;O^5MWN87WZ5pL5JfZ>QoHz&xZvVo|mu3E$Z=?9%{I{Xj*oUEKq2Q*s Z$pYpZfbW~|Nk_U{l8oY004Ic*@FN8 literal 405 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 delta 1057 zcmV++1m64P3ET;PABzY8000000RNoX%}yLw7lq+DSJCP*pHyqt-zne9r^vG84zz@E z1RW+(?mZ%Mt#we|Qhp}3JdZdk*y#I=$Od&$9s#pGndW^y!PH94EGn;cG9PEIFmC&v@k zlk*AtmHQR;EB7n@e#?>1Ed)QY`H_+VF9d(*<(HE)0Wg2Ak+%)(H@n}A{bu)@vES@| zGxnR^Z^nL$`z_dSalZxoE$+8qzs3C)?655U&DUQ{TlXb?$>ztbH9fDT9!lX*RmdBlMn(Mf7owx zzYY6s?zi#w?0y^e+p-@Hyg(1#hRrMVkR5yAC3?t~J@6VmWX~RWksh*X54=hb*|i5= zriX0X1FzFV_U(Ze>LDBVa6pnYJwi#E9&5? zl+G{*Na+;AOi||;hKeE?F;x`He~7W7>NLnr;~6nn6w!#uqL@aE7DY8;wkWO?z+#`mKrtai|o5nt3+$j1H^G5NH7&wZ6#KchyBu0*+e;_e)6bFf+ zqew_h9mPUo>?j%%b4PP`9>h%}A~AUs6N%BIs7TBn#YJNHC^8b$N3oF@KZ=gT{84-) z29P2oF@Y2#i4mlwJ7wdhagrE9ij>3@QmiD#kfJ3qhZHY~L8ORDOd`chViYMV60=Bg zkr+mbjKnn3+MQi;)96UdWh2E$Vjw9(5)(-=k{C&flEh3>oFs;lA|)}E6f23bq-aUZ zCB;i(FsXGX!rZiVXTsbxY7(W{rIT!)8*&e=f~^A-pRFxBqnAufKf#;;-nZ@$&xY|KaoKUfF;1Xz;oZkLKf*c}LEHs$cH&_4)Pka{HSL b^Wq;}`5xd9?)N_e00960`+yalmL32Avc4yZ diff --git a/tests/testdata/ts_trpc_patchclient_upgrade/expected_actions.json.gz b/tests/testdata/ts_trpc_patchclient_upgrade/expected_actions.json.gz index 148d2dcbe7be982bdb5dc8147f0abf451aa3fd18..f3d759b80d753000e2639476b4638246e5ed9dfb 100644 GIT binary patch literal 386 zcmV-|0e$`-iwFP!00000|ICv?Z`3dlh41+lBOh0&-O!@$?uj4332_6IPS$V1;Mmc4 zl2TRu@5oV_E^Ip4)#F_(ZcK|Cy`M>J~4by$YjjIZ953~(MHiKDJvQTJ@zDJ(W<`H?A&bEua7hY z`>1R-qi{b(X<72uUKXa6_(ix`%&=YzussbBlN&je7t?9#>M?~%hvMj!8N6LJIMLg+15sBYud>;MrF`?%BU{;rk+h^786poJ->(h0w&*;Nfmx#UNL^sZRszHJ#_ORpvF&#SX1k~`iC?xRUgtI*6e7Uz* g+r{3l%m2E!>*C=aKNt5u0{{U3|1OHzG$#cB0A%LGS^xk5 literal 583 zcmV-N0=WGjiwFP!00000|IC(8Q`EF zXC)_P7`}VQPHIAJ1p*X$$w9l3p8aVbYj0-&!G_pMqk|;`n<)6NTf)joqiwK+FEapu z+x~Y5bg5EXV%Mkl5p4to%OMjWa7^7wfGbBlBzA$DrVr51#;_}_Lq|1fcbH=xvMb6P z*JaKZVSErHE$$=p`95$rNNJF}-A)tJu=&nddo_e!0gJH!W96PxbUCcrw%n_5+|ume zFB5p%Mxdjo;4Nuon5IgSg0zz>`LJMxC8<4rV%dR5RVY)T`XKcWFMue?FQ*wq$s!#w zFiI2~R4qN>s6f;9KDpJ_VX0^;QIK`TGg|Et6i1Fc2}AT7!y~s_o6QUFwlejfmKmzK zxPXRfL)t;B*QkXe0ZiAlJKtAXoMh2-W${5}FLT-8^`ca!@>7nJB=u^^j~Om}(1FK9 z`r)3Sa^X>#hGSyAped!#?dreM1ZnOAKOckdm3ueXg{Ss-M{9hx1PI%;R0PVH2AqK% zA0TGK7EpJjDx)=3&U#U0dF=5^mgn)?`Xvjqx#xjOlL_y>k6*Gd_r2q3GW~?SrC(mL zGa`?PvOF8lD`OKKZZI;@u!rA7uP~e)Wp#G;Rl^zlFQ{Rv(2;iqO(|cg%%E004-_8ZH0; diff --git a/tests/testdata/ts_trpc_patchclient_upgrade/expected_ui.json.gz b/tests/testdata/ts_trpc_patchclient_upgrade/expected_ui.json.gz index 00918742c70cf8cd91550a2898b9f5ac8f74838f..689938acf1f0d4892c1a3b3cd9f50d03d5e81cae 100644 GIT binary patch literal 1519 zcmaiw4N%f|7{_s)R-`M4Eb{G4OI+BsVp^h^-U+@e5i4Y&rYtL`12fLd^lxgGW|E4_ zIzuxp6{pE%{V!1elOtPg&5FqX1fyoCAY?B}$&0M*mRohL-`#Wf+~+>e{l3rRRyq&y z_p_cIRI!}4FFpGFWn7VZIOks1gl>9(F?~c3aatNP4>vzBSV=?*2E^|Dq@U(*8*&8? zYNg|Tzd#T9QKOfts|Us@{iBqom$Cc_Ro=M9m@{owYmCp#!|G|hSu<%B%QTaEs7c1j zGhKJHTA$8Pnne8LQMtsg_`iX&Gf@hC=Uq((F@B8G&2Q(3hNArZhuBR-zAGr3le!JR zukDE>L69h63U*0$3-(IB6QoI4f^kT!nsuPwGt>4Q7X+6n8Rh(tF&My|inr_S4eZc;yn*X3H+JTOpt$>5+pQbEtM19QF zkSf2F1ko(Z-)k-yePDJAu)x3&s0u8nv|u9i2ASI{KnEST4YD=)$l1L>Fe%<-{9p_ z{Lk4Rxra(ltoq!0&IQibNlmzDRAgxVarldjV}Y#Y?Zw^a4~OC%i}1|LxV@;>(4 z2N@^LppLD$T3WDFn1Jaiwwy~bxN^d{8cN7aqebDhX{Y4@+BN8_HbbjYo^a z@+;`1K@o$eBy2#Bhdr)<$;fhPNKCP(Z)Jg}uoAPXgx|P19KW(Cg1Oq8j!q4KTnR@G zik*6tgk9*G@L(Q&3$jMaih1ODiWlM~%45EnZe#i&`uG-RdlMqNHJDu z8XGF(^zdBCXI#`9Zs~A0sJqD)an+nS);0vriM|5GKpZ>w7!fp!q8k+`)8$rwc`@iCyO#37MLzImk2W)q z>wUU258d-PPr=Mi~?bw~=RN?hOacoUuu# h$@O*dEem6_pH=7f1FsYlHVA~($}`)wbgV)k{si13DhmJr literal 1545 zcmai!eNfVO9LLe7*M60q!gTI5EA7P6tJ9q>$;vLpr!qv1MGuCvb6JpSW@bOshT#LI zrI|VL3Wc1Ra-}%S$U<#eS}>GJgbzak!AGEY_~BZ2*|lnY?>={*d)@1M-}mS9$JeD` zG3@P`e>~JrbQRiDW=_!`%(ga0CkgAw(AwSCg?7w%kE-C%M_Ae)(x&B#nMn)y2dg$Al- z2{a=*7qZECZaLXssE$rmit7}q_p16*hlniN&T_G08*4(HS}RbewLMdSD2YPTTD1bl zAmk;janMCs!R@hY;J(-(cq}#no`$8sFJWupE!a-@09FRqrD%QrE$)lioQL2|u2y1UeqIXm1xr^C5{pm|H z`4$N)ON)?;7^xwS$l7=S6_lNiTMNYSVoOk}WWli@)i+k21UB*~+sdH80-P6s=Mgc( zt1lI7b71d7+@)%-O$VtQtTqrj5+@fw*>Uz;HUZH^b!Kc0_H?9p6MB)CZIgmW3PnCZ zBJUa|#MPIU^BwyzVt~4jF(A1-%)Cky`2s{<8z$XVN3(QdA47~%X^fTV8%~ss1Ud4l zZ8-XBk;orN;|)FIOD0E{7UyxBfK$A2%v0Cc^AA?APa|GaWsIljBQ9232oTa_YeZWV z-8v&RNCIMcCv8)MSNtuBL1!z&((5^&tmKL_t6y z&znCWx$-x&qXdTr&hs`$Wx3g3*yhGALAd3W)och=xmkq~JUpW9@SzUOEeTsyD%u5HGSWuJi)@H{cX+b{b-+^birF##vrkxZ^uU)`Ph4>Xt|Sh zaeT7{?lu`_tzL0ISLw3hQH6_%w(F$SIfkyyTLTpwVT4KAIzRY)RFg|*+|pC#$k^2}G_DGL~Eetxug=bj7hFxWq^ Cf=f>T diff --git a/tests/testdata/ts_zod_improve_mini/new.ts b/tests/testdata/ts_zod_improve_mini/new.ts index 0e9cedfd..4e6bb7c2 100644 --- a/tests/testdata/ts_zod_improve_mini/new.ts +++ b/tests/testdata/ts_zod_improve_mini/new.ts @@ -5,9 +5,9 @@ import * as parse from "./parse.js"; type SomeType = core.SomeType; export interface ZodMiniType< - out Output = unknown, - out Input = unknown, - out Internals extends core.$ZodTypeInternals = core.$ZodTypeInternals, + Output = unknown, + Input = unknown, + Internals extends core.$ZodTypeInternals = core.$ZodTypeInternals, > extends core.$ZodType { type: Internals["def"]["type"]; check(...checks: (core.CheckFn> | core.$ZodCheck>)[]): this; @@ -37,7 +37,7 @@ export interface ZodMiniType< apply(fn: (schema: this) => T): T; } -interface _ZodMiniType +interface _ZodMiniType extends ZodMiniType {} export const ZodMiniType: core.$constructor = /*@__PURE__*/ core.$constructor( @@ -815,8 +815,8 @@ export function keyof(schema: T): ZodMiniEnum extends ZodMiniType>, core.$ZodObject { shape: Shape; diff --git a/tests/testdata/ts_zod_improve_mini/old.ts b/tests/testdata/ts_zod_improve_mini/old.ts index cc63e2d8..ab28d17f 100644 --- a/tests/testdata/ts_zod_improve_mini/old.ts +++ b/tests/testdata/ts_zod_improve_mini/old.ts @@ -5,9 +5,9 @@ import * as parse from "./parse.js"; type SomeType = core.SomeType; export interface ZodMiniType< - out Output = unknown, - out Input = unknown, - out Internals extends core.$ZodTypeInternals = core.$ZodTypeInternals, + Output = unknown, + Input = unknown, + Internals extends core.$ZodTypeInternals = core.$ZodTypeInternals, > extends core.$ZodType { type: Internals["def"]["type"]; check(...checks: (core.CheckFn> | core.$ZodCheck>)[]): this; @@ -37,7 +37,7 @@ export interface ZodMiniType< apply(fn: (schema: this) => T): T; } -interface _ZodMiniType +interface _ZodMiniType extends ZodMiniType {} export const ZodMiniType: core.$constructor = /*@__PURE__*/ core.$constructor( @@ -815,8 +815,8 @@ export function keyof(schema: T): ZodMiniEnum extends ZodMiniType>, core.$ZodObject { shape: Shape; diff --git a/tests/testdata/yaml_k8s_examples_cockroachdb_spec_update/expected_actions.json.gz b/tests/testdata/yaml_k8s_examples_cockroachdb_spec_update/expected_actions.json.gz index f108460a5eef1b67a567cf8dd53cc96dd06ee1f7..33ab552c9ec9d7f48298c81d0376926f0da2919c 100644 GIT binary patch delta 171 zcmV;c0960a0nq`F7&hGaQ>(91ibS23P@9Bg6hwUY5^GbTxay*CH(AU%fy1{70G!DO zZ4EYnv&4sZQax*H0ygk0kxm(ESL=VwNEY`+M%%x)AIdpx-dd-$KU;y7=eAoox|*LH ZukT`N0q`QW&j0`b|Np)tky!o$0034*Qhxvd delta 169 zcmV;a09OCe0nY)D7&e$%fACdGk*L!WYLk$Rf{5>4VkH$WuI}b?H(AU%fy1{70G!DO zZ4EYnv&5HpQax*H0ygk2kxm(CPwW59NEY`;M%#b4Kgv06zFMcWKU;y7=eAooxqr$tCX_NUvE=v(8p+5I)TQ|B^& Xim3&_huD4t0096044}1S{sI617?Dlc diff --git a/tests/testdata/yaml_k8s_examples_cockroachdb_spec_update/expected_ui.json.gz b/tests/testdata/yaml_k8s_examples_cockroachdb_spec_update/expected_ui.json.gz index 91a184d370c30f8d88b7b2ce9af3dd2836d28b24..f7cae15b0bb85e254e5e76a796d677cf6f84a3d2 100644 GIT binary patch delta 942 zcmV;f15y0u2rR^X>fUbpERIFtlp+xz*`>F0;j>Gb{A(`kF$|M1`MzdZhLs(mV&rhS@dn)hj@Y1yZRrgfiInznt~ zXxjH_r|HuZ3SjzZQNC z{aW}ne((Cli+(Nq8v3>HYv|X)uc2QLzm9%A{5tye@ayQ;!;`H63K9DC@aw#}cy&R) z9)2DDdiZsd$N?P=1N}z$4c`5{{Gs0nzk!qU0U>{helz?gZ_i$z5BBF}f#wZ*^9sH3 z4!wDa-gt}Nyhd-lM{i!FH{PT-uhJXu(wmp*jkoE|>-5I^^yY5%-K7G~%L>lSbS$a@2^cM$Q^>*QhKP z6Kv|V5x0#TH{!aH^G4h^a^Q#yM@}4ZEX(Vn-IgZ42Dd&;6FXccI7p9y@;>OfiE_n}bd2Py_DTk7{H04whx27CR z;@XsRN!*)qFo}y(P9|}4%F!gQPC1*z-6@BYxI8tNtMh}qbDMH~rlp>^KhsiAT%c*G zCvMQR)Du@|TIy-<(1-7*&aao>-#=bIzdSv^zC1m@f4TbarsehO%kcP`&c9t=FYlK# z0{OkWe75d;GF?6C9q-3a=Bp>~{c6kgznSlQvR(__`DFXBQ2(&d_^{BtTj<-z>*1e& Q0{{U3{{$WsxZ)fD0NiW#0ssI2 delta 960 zcmV;x13&!g2<8ZoH-9&>f3&9WSNi+mbUJ^%{PpGK&$siZ)A_5;kKg|4_2upI`PbK% zr?)>YZ|~<%r=K5Ar_=XePp9p1|HFU3|MK|1srIR8n)Yd;Y2K%qre&WNn$~?uZ3Sj zzZQOt-@AVCqF)QYhJG#l8v3>HYv|X*ucKcNzm9%A{5tye@Ehys*Tb))Uk|^Iem(p; zZ!TV4(65JIN539^9h1=k6&Cax;WyB4gx^5F5q^VrKQDjiH^OhAll%c0fBMbvo9H*g zZ=&A}zscLP*XM)%d0C)&gWkMCZ@fcqUZOYNqBpP68}HGZ7wL^R>CLP3#=G?9WqRXn zdh$8Y`R3rQI#xN!lp}@9F)nDCI@Y@#K}ROEO~O!Crh9l6v~n) z2aU2s%0ZdSHD!Fi-jxhUl%e-byP97W=)l(R_Om2wz~%Ti7waa+o9B(6(2kHmc`2a>ojO-ns-gQlgP_6mLYe%1N)V)Fa@=jWHF=hv5~=l3sH zKTKL)uRiLIuXz6L@_Ko{obkW!_wMrK+;^w0?(_!t<2%#Uo%jB0^Yz!v_uW~ph3>qw iepsk|Sg3zkXxuII?eTi}=idMT0RR7rg8NRu8~^|{zz5U- diff --git a/tests/testdata/yaml_k8s_examples_cockroachdb_spec_update/new.yaml b/tests/testdata/yaml_k8s_examples_cockroachdb_spec_update/new.yaml index 739d7710..13a5d2e1 100644 --- a/tests/testdata/yaml_k8s_examples_cockroachdb_spec_update/new.yaml +++ b/tests/testdata/yaml_k8s_examples_cockroachdb_spec_update/new.yaml @@ -104,34 +104,35 @@ spec: # has to decide what command-line flags to use when starting CockroachDB. # This only matters when a pod's persistent volume is empty - if it has # data from a previous execution, that data will always be used. - pod.alpha.kubernetes.io/init-containers: '[ + pod.alpha.kubernetes.io/init-containers: |- + [ { - "name": "bootstrap", - "image": "cockroachdb/cockroach-k8s-init:0.1", - "imagePullPolicy": "IfNotPresent", - "args": [ - "-on-start=/on-start.sh", - "-service=cockroachdb" - ], - "env": [ - { - "name": "POD_NAMESPACE", - "valueFrom": { - "fieldRef": { - "apiVersion": "v1", - "fieldPath": "metadata.namespace" - } - } - } - ], - "volumeMounts": [ - { - "name": "datadir", - "mountPath": "/cockroach/cockroach-data" + "name": "bootstrap", + "image": "cockroachdb/cockroach-k8s-init:0.1", + "imagePullPolicy": "IfNotPresent", + "args": [ + "-on-start=/on-start.sh", + "-service=cockroachdb" + ], + "env": [ + { + "name": "POD_NAMESPACE", + "valueFrom": { + "fieldRef": { + "apiVersion": "v1", + "fieldPath": "metadata.namespace" } - ] + } + } + ], + "volumeMounts": [ + { + "name": "datadir", + "mountPath": "/cockroach/cockroach-data" + } + ] } - ]' + ] spec: containers: - name: cockroachdb diff --git a/tests/testdata/yaml_k8s_examples_cockroachdb_spec_update/old.yaml b/tests/testdata/yaml_k8s_examples_cockroachdb_spec_update/old.yaml index 8115c6d7..b39046cb 100644 --- a/tests/testdata/yaml_k8s_examples_cockroachdb_spec_update/old.yaml +++ b/tests/testdata/yaml_k8s_examples_cockroachdb_spec_update/old.yaml @@ -104,34 +104,35 @@ spec: # has to decide what command-line flags to use when starting CockroachDB. # This only matters when a pod's persistent volume is empty - if it has # data from a previous execution, that data will always be used. - pod.alpha.kubernetes.io/init-containers: '[ + pod.alpha.kubernetes.io/init-containers: |- + [ { - "name": "bootstrap", - "image": "cockroachdb/cockroach-k8s-init:0.1", - "imagePullPolicy": "IfNotPresent", - "args": [ - "-on-start=/on-start.sh", - "-service=cockroachdb" - ], - "env": [ - { - "name": "POD_NAMESPACE", - "valueFrom": { - "fieldRef": { - "apiVersion": "v1", - "fieldPath": "metadata.namespace" - } - } - } - ], - "volumeMounts": [ - { - "name": "datadir", - "mountPath": "/cockroach/cockroach-data" + "name": "bootstrap", + "image": "cockroachdb/cockroach-k8s-init:0.1", + "imagePullPolicy": "IfNotPresent", + "args": [ + "-on-start=/on-start.sh", + "-service=cockroachdb" + ], + "env": [ + { + "name": "POD_NAMESPACE", + "valueFrom": { + "fieldRef": { + "apiVersion": "v1", + "fieldPath": "metadata.namespace" } - ] + } + } + ], + "volumeMounts": [ + { + "name": "datadir", + "mountPath": "/cockroach/cockroach-data" + } + ] } - ]' + ] spec: containers: - name: cockroachdb diff --git a/tests/testdata/yaml_microservices_cartservice_scalar_limits/expected_actions.json.gz b/tests/testdata/yaml_microservices_cartservice_scalar_limits/expected_actions.json.gz index 07bcb013f12ba90da56920111cd540a9c70ad594..b78dd252aae8612672a723e29a7c0c32a7578c4c 100644 GIT binary patch literal 498 zcmVjK>xw!UV>E-E zGSDSW3(6(2B^A_@E+_-h6u=KC!;;fH2}n-!>`bx}71>i!!`XwegxBBDqtPc&1=f)X zLo_JOYcoySzztnt6?Q_s{!$-iTEroy#S$AZu#jOoSseGRK|E~@p4EQl5{&RTi-V#T zNtvZQUU|#d$8*3g3okXuvUe2Q ze8;%FYZ8b&0Tu3vXrmZB;A@Sbm$f6>`3aoId3=Ke_S$p|Q0UEmGUNl7T7iJMmpU_o z^NZpkOyf%V(6M{-Gx$a}XGw4()*Z6`opk$u9Nw&gvhF_}{yWm9yF8RyQysp6m6ya_ oo~8jI_nTyi`0e`~U0*_F?9@gGeTzPR1^@v6|9FVec$NY>vQ3OGZ-z(#@gM!(_dg!bDkqv@B^4ZOx8soT(u?`A3J*wXUdxF-9}k zDFa>7w4huPTT($i>4Gv4O#%FZGAudGlYrzj&pt_3q9S`LYWVbEEaCMp^l0=6RDpHm zj3FA7=CwIb+Q1E6U=?;kz5Y=jW?IA{ro|E)FtCteI$0d|twDU=8a%80%q1A%aTW(f zEs`=zdA#zLv5)6~T^3$ykY(>!79oyl(U}b+X2DN|e;Z~#+~v!%aayUG2_P@Ea?lq& z5BQF8dDkQmc>*fj6VXO7c)*t$K`(1ZwDS`&M{o&k;j&ws`Yyp9NowqTtyI+~Mc%cB3gB_X{s+C_8nVMGWaulv_i zpi5ms1s?Y4`-nD6h~}qELLzUWTZsx-8GFv`BD>}gsf^q#YSA=Gmy1Rydzt0DuzpeO ze3#4Om|es`FV7K{90PBsY8qid`$6@frDXX8sU)3Fey+qgb<`|AExNWiR^x38qlc(i$-i_t1E<{BOEA+BY6BaX$;mNLu z@>k;d1qY=aSpPd5#L9zx5{3-LFue%_x`zV=2cKHd63|j6S%PAi4Z-kCJCw$h6;N53 zc1cYGRvey_IFBqxRABLKJc2FW1;-4-!Qx<#p*(7+jomr_!^eKlfW;_-G+5#>2pD#k zVp*`kUq=VmOFKXbnBnj)Y^4A<5I=gS*S0V*Mb=Z<}U><9}_OVYC-YgQcn# zB{=Fu&rBo9v6%)>!X@d^EUA*u1c?uBpVDivOhR;5PS6iT^Z6sZTsQjABHOLJPB;{Bexq2>x vL+;K4SK%M|Devw)&H(0r_RoUbzH2{Q=n)|wM{nN(00960!Br?V)gb@?KI|K@ literal 724 zcmV;_0xSI=iwFP!00000|LmGwZ<{a_hVSz$EOt9u%t!O_SEea)%t>kmY-XEmS=IkO zkxw=_)Jdg@AZ~iWabF$3ejjX^yiEx4cA$+=(pwO3N4>ArBgU;z(s&E8^ zLNzpn3@jXmA1YF%;4LmA3Gu9k>WR04wbIv-Rb^isE1BZkWzLF1$j!1~Lf1zb%d}mt z_O=>JgMij*Ak%AwhNr^&rJI6jkoHskpsgg+7o?MT_R{P`8FBI~xI8rF>eP+ZB}{7n z(c*NjcAxZ_t30plsFgCdf~=~2AwGF}dft}Cs$BerXRh)>Ns!h&^L@TznZMFZrd^KE zfJWHjBrTS7EDl>+(D>RI_)&u7fVT3Igy`bT-4;h>>9RlhIds$3W(vkG@id@D{)aFm zXc%UV`5mT#3LMLA8hzwtqtqq?pJ%E}eN}*F$JZ!sRWe1aqCwNDk()>4=8jOzu~5*! ziJz-Llb^FjANk24S9)*kKeB(%js~bb@yN_Dm~jgN#ZH7YapI&V(85X5Urr?0pGt52 zLS=#r=y;dV7=>jXjj#*?mK)NLpv24*Ct{K=Von-;B*uW=2@XEvT$R#xc{Gm^kHTo& zUWP%;Eos0e7{+dU%vGRC%vqzC#1u?Q=(vyxBW!C4r|}5NFhKb*1TnUwgwy7{TKK35 zwD57#=p!FoNy~%;?Tegk!1$JR+=+x!>`o*K$8*>)V7WCB*ws%II-SL80!?zx8jnJb zZ_4#r{KD;uLhM);Oho9NTimNS!ZxDTufHQg4~Wn` zslX@d^v$y-&_dAcqi>!<8qn5-p*zjGy0f_NHyV#}C2%x)Ldf^Y`=0;+0RR7_!(Rv= GBLDy!GH7=I diff --git a/tests/testdata/yaml_microservices_kustomization_scalar/expected_ui.json.gz b/tests/testdata/yaml_microservices_kustomization_scalar/expected_ui.json.gz index 262598985555f06d015b6272bff60e47e4d66dc3..b3f78d5ee6a427f1e78aff8961a8f3777f7cbe83 100644 GIT binary patch literal 420 zcmb2|=3oGW|8uT5W*>48VR=wpcXU%ackO#sslVDwJr+juF44^R5cKPQ_tCiu);8PX zZauJ2tC{&^H>YCUrI$7}zJ=nCTpzvqbEi`%7cr;ybO=)mjREOCS2ICI9Dd zeeB((lY$dhJ`0J=vNWBx%`!Lg*3&J?FRhkmPs=OXm6$pI^1P+D=j5$q+t8A&8*{~* zK`q3`LG6l9gIb910ktc>4C*0%4(eC@8q`Dl52#=9f4CfkYw}M&STX;Q|4N+r;Q1Bv zA^3;zZktV4&Ob=Uir;hEy*;~rXRUhQ%jA3V?S~6x_>TXK*`qc+dh;IU57{4Wdo%qm z?oYSKSi4HYb>nL5#bQTUkLgBLuFMVHSi9xM)akcEMXx`V{JrYYvXHgb$?;;Z-zD#y z<5ww|Z4>MMSBEEGO?s zkKa;Zll!A+_W5I$^_Kae#zqbGymuF#9uyo z{=4*}_S7j{-lj`W1$nRBxWzZ~^d-Hevfk4*V>gvdy(H@Wd&)PR*ySa@rVXkw+QotT zj57iZ8D|COZz@jyL{)od03+t#^;}?2p{7vl2g^a&J}*+k?D+wmgYk z|Gv$8xQKPLy^MbSl_e`mg90xvniiOMWlc;n`FegOx zEJ`K=;Mg@!c$kDfFt=X|jLxRMIBB?!3Y5Z)GqD?J6H{BTRXux-%a%26FK1ZUDT&O} z@++?5Z8X86G<7jmnLAPQ`4bBUSK1SF9i`R^+2u-&om*;T$v!}8tc%pff|QyA=WV67 zzo-c|Ca4u`oSa>0zI)Z=l8TxKH_mr)JH4pAL}o{6f^qIq8o!95b|hq%E44EhHNm2B zcd2zKYR(pVq&D#twY^fSi%i-R#a3vk@@bVyEnmT=wL9o)}S;T+yNy{@L005WHca_NkyLnF`e4y4d`$V^~)CsG7m|o*fu8`9OQ&h^1iWEMU)BK8W$p)8aqJloppAegx#k?s?>*ZukG_N#14?PeHXZ1GS@SuIWcoH)Oc#sm73Mc!QIw# z{13hdi*)uqfTA>Wr4gjoW>dkeRytGp0%V>+QCCa%*)9>(N-nVSSili!0h8VKdhkgK zXOv`l68qiK@J02^%uvHG&f@U^4y#L>Fp9nAY9A-Vr;Ewqt1%0W@Wtd-svJxB>=?lk zHp(tdZK1>;wJIGgnMoheC(eX=cEO|L%-BaymY#WuiE$a{e28Y`U8ai4D=W3e%#q^? zREBHRroa+bGF_@1@8A!!!8Mk*kQ<9&m(tQuaB}n|!sF`KM^BdCnc>u(g%9#T@m;1% zrScTv>zB`v8LS-akjiw44MELKzq$pK>GJ6Z*eI=OAVf%2Fwq9YHCfKY3!hK}ThaD{ z*)>&KDRBpZd1+QqrKPm#vN6MUiDmN}!O8~&3EDVotX6pENtBqXT_bkwSKf>jK{WAP zOs>7kVT90U8ZoNv7_qC9>IGs!J#gn@a n?fr*q7W4?cAYSHcm)Qji{s!Q$n_qti00960ApQ(&STq0t1n*Hm literal 1247 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 diff --git a/tests/testdata/zig_clap_more_than_2/expected_actions.json.gz b/tests/testdata/zig_clap_more_than_2/expected_actions.json.gz index fa518c5f53d80189a84b727ceea1bda5d649d71e..31ddb0e3736cdeadd049f9adee8af1264654d506 100644 GIT binary patch literal 1771 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 diff --git a/tests/testdata/zig_clap_more_than_2/expected_ui.json.gz b/tests/testdata/zig_clap_more_than_2/expected_ui.json.gz index 8f6184160af86619065694d744ab4c7558afc030..bc76dbac5ceca2566af45ab1ce9ab9be96c4a6c4 100644 GIT binary patch literal 11941 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 G5&!@ij2lh> literal 572 zcmV-C0>k|uiwFP!00000|J0Yyj+-zL#_xFwi*paL&EH6UlBz-mCaG1gjckJ&t@hn3 zXhhfzcE|?O&1I$aH;QI{9)B~uZV(Du(1t4+>`>6+;9GaZO3Rfr!4Cb{AcW9s|923& zP%aH<+lTjxR22lfArhg$YUoY^wzr^%z)m>Uz0fkvSs@^=pcG8A{-;NA#xia5;%K{Q zjBy%`M3B{4qL`eNw;`dLX^{5DlnSBB-<}+{nJWj1LwcEmGW-M#Z${EOJWC~w9SedL zASRXhXmPe(2JOnXeI~tKpER#PTE6G+)d4rtht^kGhTXKIC!_sZUaZ1bT2G(cIjNu3Q0@CKH2F1N}L5tnc((EF` zKAF)}aXiW4xB_GIix-f-*FSK1fO*#JC={zaTtea;MO>pia2d3BT<;a0E>~F}^SMzv)3VUHr>De- zP-lq|{_2?Vf5Uv=mjcb4)M>VmZ_F8;G$T&`ntEjOKgRA~n>5%)%bCWPIXBYDIzGem z#)lQVw~{!y+)5_BmT18-#vt-u?yv0RR8K K({2mQ5&!@#l_e|y diff --git a/tests/testdata/zig_zls_resolve_correct_build/expected_actions.json.gz b/tests/testdata/zig_zls_resolve_correct_build/expected_actions.json.gz index 6e8177f6897c8ea12695671c286c41b9745d8592..7405150a55df4af08a3d46c2d87963575a98f6c6 100644 GIT binary patch delta 255 zcmV`f2qs)6LR}as1Q&1}J(v|~ z)f#Mi?2IDiKfTF0R>VzvM*#29{VM?tl~N??Yza-rWikrOvhQ9@#VSRiQ0QKAnBSN1n~&Tg05u|e z+mot5jaofTBh!lQ$*T%pA^?C}I2SNQEqP=K@j$5WP*qD3KndeCQRXbjOK<|$O8}!` zYZ`}jhpjVg!qcmq7sFCFSDDf}eol%NMC!g#nHMv;FG3f?NObZ`rN;H``+-ARmOBn< zmgt`jy|;5==`!>~GkXXR7_DwRM9pQ9@6~)N;zzGJ`?s2Hha~oFx73*iU08XruB&+< z+6K0p>-d!HY_4^j{Z0FZ--Zt)@kbtcyzh}8e)O-ZBY@ZF{uuxO|Nn6J-Y;PU002E@ Bcg+9* diff --git a/tests/testdata/zig_zls_unused_argument_error/expected_actions.json.gz b/tests/testdata/zig_zls_unused_argument_error/expected_actions.json.gz index 7859f7e02149f026c66b97efbf6751317ed19d86..91cb1ca7aff3460d828bc1e1e3ada6c86969dba5 100644 GIT binary patch literal 607 zcmV-l0-*gLiwFP!00000|I}B(j@mE~z4H~LoOY#_gd_`rZ|I>?d+G*74jF5)1~rxNG9y)j)~G@PSfsItSZqqDD`1gW&dbDv2@&DjT%#!o)F6hKrYK%g0d(D= z*RLf}CbiVyWt-VlT;@!pqzl>b>3Lj&q1V90cO37Ki!ywxncJzQZX@ZGqe!mT^kvYF zrfrF<9ni0*-$hKEJ6-=gGrBi#iiv1i)c=sua9gqHG zX^P3Nf+=In0=vh55AZe29mhl1aY{MO^0+%uSwWAK62@K$WA93| zwT?|JwGY&a4A15Q#~XOc*b<~7z&CCPmPpU1d^UJ#@|ouzxxJ6-`rhsB&7_jcOy#Dq zcRrzrOHP~#zS_s{@5%GLpm|UI&!g}ix^+#^NN__ZRUJ0^wykb`rvtCG?mL*+7@o=u zC7tD$Ld-^;gO>V3JIDT!w*U7mW@>@w2p;29X>3FBq31SjaX4^4k>b57s6-N-;@K?T z1w;e4sk8ac;E-s^sn*>Z>`{diG!(rn={vps{JuQ?M~_m10_jS7J=V~5IB;DvY_&0H tJ;adJ{OG#<;G!#i;;LNzf6WVe{u$3x2VmUU{0RU6|Nna7SEDNr003?JFBkv- literal 631 zcmV--0*L(|iwFP!00000|J0XHbD~TT#_xWLE>20+`w9XE@H6aTt9DNtQq&+VnW|yN znrYmal;3>|R#}X}KM}3y!9({W^URN)p7w13U@cG^uB0^qYcaC^t3qr_TuEb1;Bf!| z@K%2}iAu_)K~1&1&PbJ^HEEOp7HO;^7Ml_3Mpz}5^ExqQLL~Sy*Jx@3Er}tfDM^=9 z30*hx9$HD1S(Eboaj?#;8ZUFEQPPQS`0O|@VdQmq@g2w8^`Z=4Gjj*6)Mb#)IEw6C zrf$?1)62c#e^i|&Xv%c$h;)gUhs|_e7AVQ=+t)bgq#TTIhw|w1IEzvc7hGauNOPID zHG-umDp4HA@ppmDAY|&d6pCd)&j@di1(&=ii)7u-o>rjouTah47te=q_e?Z56We~} zxnMFMDxKS#r`Y$ggm<56v5%uaS)OCIS;5pxeER`RBQRkUum$6Sr2>Z^{~qA~xO5y3 zVdE+1^jxOHsVXXaq?9oBt1$LviN2m=6U*%#T8ZJsT;S6R?h3X9sR;0e8-gX${l0<< z#$5&FxgRvc&y@Fh$LwJHxI&+hN-hgknyRqNDJ5KT;!N<@ZTxeF7@o_jN{+f@Dwv&|!=8FVKd=1|+s{oFg<9Y-z*C$l zjeQW0Jhy9$QQ+PX@lg|0B1`u9?1p!O(a`N0hkPg4HClUWjq@Gl(S$QJl)PKgcShU! zZ9M*=mYJbIIfTzLg RPXGV_|NkARK7(!$005P=IPm}g diff --git a/tests/testdata/zig_zls_unused_argument_error/expected_ui.json.gz b/tests/testdata/zig_zls_unused_argument_error/expected_ui.json.gz index b636cd135ab03a5a00faf8aefe7bfa72a1067dbd..ae9c0866a7507d389ab04ec26f46166d59d0b8d4 100644 GIT binary patch literal 2705 zcmb7^dsGv59>qZgE85jl3B^EUA8mnvYZ1aLVtP31(gQ+x1PDlpBo&Kd5Rr!w6N>_C zG_fj=!y6k3j{sq0c|#(&5S2>0)j%}h6axYw5H(DIBm+y=)&mthb^e<3yZ3wNe!gdB ztS)_E@c(NuYY=399o(4yQb%Kc!bgzV4zoDY=!x$#`ufvuZP?WwqaCuaNMJo4Y2wvW z34?&G`qJfpL6v8`2PFyzJ__u$phuB}Wh2DMRccqFTZyOk@&fD3Ko` z=%RPkXzQMej<7d;Zb47Y1{=uSh9 zLbCc=_woacT5&`AWc2-oXSJn&nXEm7U3ixkO+gcJx{2Lf7D z`^kGh87&jX6v<>^0)z#?7HyGK6#@GxlWXbL8f>U=yRL`_UWEH3s*whg8RJ*6hW@dp zEkw9k_Z1IJhifIOF8Y8XIZAj8YO4bqv|mY8;qc#;$xAkVaeb;F40pxIiC=0J=7~%B z5Wf3YZ6|NsE9bvkBfW69zN5eJ)?O`}IY02z6??8#dp`YZH~430=5L!78~GJhVS%{j zi7)OIc^msQPn^5QI$-QejoowNBDkHrFJQ2?Y-O03`G|TeAbF zx8)ZYJ9INEKj%sv5O+;|xSo0BUc%==)p;gIm>xlfzQ8x=o3_rrMwsrZ$~vwTBavU) zL`6O^m2uMw$U}sbAZ3Bc31)iGU;Kc0^j+H!zjU|mzREAkiS7u6>A~`}BJ$KDXTkI^ z*ANe+phs+-@kSoqipsijsRv@tw71-|gsdaH2&yhIVKCt!Lx12LdIQ?oe@gD-L`51S zuodfWkT(U}5MpnbWH2#=VSgYK{b#gUK>9zrKdUOOAnr$)A=)a|amYI)4ubp}gDg6@h3Bsn7PcxRhXDW|GaUA#?@;Ip_$qCa_4pnM6hIK@?P` zamkoqDM86KDP)ckZUg~E=oEB+P&&SwUS&{4^hbCiEUMBf$onN2!9RubJI|(G?E`O$ z0?1yr?2oYC@mbOUCg(rwK+8{)vYy!h98<50s4`b?rA_y57EGgcbIjWE>x5JFprdmt zH7T_xM?6$4md*@wDYCI>@JOtFP^rIMQ&P}T0?a4W>l_;yR1KrY_{Rr-`cb;>cP*}o zLXa-3ch_0bm=^1Q^5KfME9AF;Vk~5WL8m_m{!7#oQMCJeHDWt_f7@5S>LORKmav6> z;(ZV%ka8y%wG*W@!}{nmn|h9=R~~BA^}fUyAD{I&fX(@VebVx9QkMKT z3zFi!M82l{Rzkn|!ZYsbQLnv%yfTYBr(7PMq7+U?7gM)98uER_y6R4K&rndgiXP(7 zgNPyX>bAUU3r?a-eIliKI=Yp5c>q|Yv4=6DC1yq2x9Y3_YG=K~Q;~lV{Ff*dr6Q-G z=iLih@ko(*@bh=l|8Cc>+>CF(7eXov&=$049f;!VP&}cYe?Cs{jM9j-g89b8h&T(k+TVYF_wf@w@N2A zdZ;iMnVC)Xvt!Ap{(AjHyIM3JDji(wI7j3;=tTrrETVDCO zurt!}hP(9GXM~Ms9$Ziy;^+CJl$h;R=R2Z36YB;JRO}O-4qiZfsL9_Xd2Q7dGqQ;M z$3)a5#)8Mcn#B>(WGsN(G1Wr^o+eSMiE(Ez{h7j@kbYv+ibU7X%kemdcJ85=L}#dl z*UWd%#+TZ>IW&W8(^rbZ@7UBNp1^MJEOHTUVF)sC`bp5xz+iEaosckI=w)E=KZ)U#DF6Tf literal 2734 zcmb7@e>~Is9>?A8=_npKx5Lzpsm?u$Ar(VhR^5|zF*D{@Le@`-HAE#_DV23L=W&li ze(q@5uOy2QF=XxBkk-<^HGIRPYz!x6vGv`q$2kukxtDvd?_ZzC`~7@<-mmxT@%e7N zvC81LPyeU~q!x)DW`0PD6mA!}s2W~rp~<_aT(<+-VS)9T_YJ!t`_rM&G}Yll-q zZ7vntj-ZAW6<}zvM%%z<4>>w+L^bL({WI5Q&r_dzrIab%)Z_MS$~nD8axFT_>jGKV zuh92-dU`@?DVr@z{YaUXf_i-e#p15^gqSnNyoCeN7-ss$_zk^dObgoBM{%)twpPA} zIh3xtEgtbYA46Mvr!FKh=H7-DqZ{4(Lx6Jc>eiFU`>>QdYbz=b(vmYrPqx{WhyEox z21O&ck~ctYM$ys{GI`P`h_ri zctW;QwCU-K<%{+hnd4&d@SH&r% z%;>{{c$KUYbkW2EL<`78SxX~ZsAb*)ngBWR;1X0LCO#(1f$aUS#V7W`2QXM&d?x_G>qERv@l5*$`}RDwG+ zaA15rWD@o8h$7>&W|GQ-5AMTF_9XB9r;oL%Z=K?cA2a>76xg5I*?*+;$E>Z!48PsstB!v2wAIEm(A+2gW~)DU zcUc$$#xsj3bB@U_ylN+m;$AEZvxnU`D=f>%B|N|bfy!K?gVc9{rM~<~#97-{zL}0f zGS`3=w*6h!^B(8xwjq9*JA`!ZZdTY%*i*9zRz^Od6YmzJ%r`ng-50bO!;eL9Y(p@a zNMQxH#LDlqJ%wZ3W_FktOk*ZvXD|p5emY3WFuF)xiQgQ+zjTse zb&Dj~&H?toR>6EZdrJw%!Q1iWrAF7Np7=lD_}3BNB3y7Q_X!caN)E6OwjS2bp)17S zx~`#9&*1xU{A|Q-gn3}*exWyS6F2Pduq`kT?us&kZ7>Ias>~>t`T*Y_$j=)tvYJkm z{J;hLV9u~R+*TIBHTW&wo^4c29mTf<@k^qnpuR^gyGq6je z+EmQAEy5Adw)C$(d`LL}j>>GK2U=RExiaCY!mn4ZIpmzY@ zn_Qkisz`7Tt91)^h2M=Rx?5->b?}#BL?gf=rb|o^iIT;g&pBGK+_^$JWqAUIN%yh@ zGdJmoq~%zeDKfdZJV61y+woa9)^KFzNV;XWl0#<}z`IHKDyBRAWC~t{>!c66@m}NL zXru>kkaG-uW*$ODhQ4L}U*tR#SN}yTX5lUKy(LDelOJ52{a==_ah`;Yt>;wNah)TB z5A*~VY_oGnu)|1y3ifdf4U3Mw2N#vCx~^2}ZHSa*Dv+_VuR zZJvFl%Zfsq{E)u1$wdQA_X{VFbus!r;l7q+ zYm-ZDCem~x?b^I9$1eT5%ZKVEzXBbTogEiYx}kijEMNLJr^!n@!KU*khLdy8)SGy+ zbQ2?a+P1a2L1`a&(98Gzkn}4?lovVbyPvrbEr=aYH)OXGQ%~vMzEso$%p|ZWbl@o} z?!7EE{1t}s!tX3)EV~g-7IkDWvP6Ar1jl)O{=EXy`{Xkp3fT#udpA*+rfq4WG Date: Mon, 7 Sep 2026 19:24:16 +0530 Subject: [PATCH 2/3] fix(treesitter): remove unused dlfcn.h dependency to fix windows build --- internal/treesitter/bridge_cgo.go | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/internal/treesitter/bridge_cgo.go b/internal/treesitter/bridge_cgo.go index 8379d74c..ca30d1ff 100644 --- a/internal/treesitter/bridge_cgo.go +++ b/internal/treesitter/bridge_cgo.go @@ -5,23 +5,9 @@ package treesitter #cgo LDFLAGS: -L${SRCDIR}/../../native/bridge/lib -ldiffmantic_grammars -lstdc++ #include "bridge.h" #include "../../native/bridge/src/bridge.c" -#include extern const TSLanguage* diffmantic_get_native_language(const char* name); -typedef void* (*tree_sitter_lang_fn)(void); - -static void* get_ts_lang(const char* lib_path, const char* symbol_name) { - void* handle = dlopen(lib_path, RTLD_NOW); - if (!handle) return NULL; - tree_sitter_lang_fn fn = (tree_sitter_lang_fn)dlsym(handle, symbol_name); - if (!fn) { - dlclose(handle); - return NULL; - } - return fn(); -} - static uint32_t get_ts_lang_symbol_count(const void* ts_lang_ptr) { return ts_language_symbol_count((const TSLanguage*)ts_lang_ptr); } @@ -154,20 +140,6 @@ func GetNativeLanguage(langName string) (unsafe.Pointer, error) { return ptr, nil } -// LoadNativeLanguage dynamically loads a Tree-sitter grammar function pointer from a shared library. -func LoadNativeLanguage(libPath, symbolName string) (unsafe.Pointer, error) { - cPath := C.CString(libPath) - defer C.free(unsafe.Pointer(cPath)) - cSym := C.CString(symbolName) - defer C.free(unsafe.Pointer(cSym)) - - ptr := C.get_ts_lang(cPath, cSym) - if ptr == nil { - return nil, fmt.Errorf("failed to load symbol %s from %s", symbolName, libPath) - } - return ptr, nil -} - // NativeLanguageSymbols returns the slice of symbol names defined by the native Tree-sitter language. func NativeLanguageSymbols(tsLangPtr unsafe.Pointer) []string { if tsLangPtr == nil { From 5fec928ce279f95c626d3ecde0018d4868048c84 Mon Sep 17 00:00:00 2001 From: Harsh Kapse Date: Mon, 7 Sep 2026 19:34:25 +0530 Subject: [PATCH 3/3] build: set default make goal to build and track grammar sources --- Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b37352ff..f2797fb5 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,15 @@ +.DEFAULT_GOAL := build + .PHONY: build test test-unit test-integration test-e2e lint fmt coverage test-update bench bench-short grammars-native clean -native/bridge/lib/libdiffmantic_grammars.a: - @$(MAKE) grammars-native +GRAMMAR_SRCS := native/bridge/grammars.json native/bridge/build_grammars.go $(wildcard native/bridge/src/*.c) $(wildcard native/bridge/include/*.h) build: native/bridge/lib/libdiffmantic_grammars.a ## Build binary with native Tree-sitter flat-buffer bridge go build -ldflags="-s -w" -trimpath -o diffm ./cmd/diffm +native/bridge/lib/libdiffmantic_grammars.a: $(GRAMMAR_SRCS) + @$(MAKE) grammars-native + grammars-native: ## Fetch and compile 18 native Tree-sitter grammars go run ./native/bridge/build_grammars.go