diff --git a/go.mod b/go.mod index f6d7f35a..e9e7692f 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/modelcontextprotocol/go-sdk v1.3.1 github.com/tree-sitter-grammars/tree-sitter-lua v0.4.1 github.com/tree-sitter/go-tree-sitter v0.25.0 + github.com/tree-sitter/tree-sitter-c-sharp v0.23.1 github.com/tree-sitter/tree-sitter-cpp v0.23.4 github.com/tree-sitter/tree-sitter-go v0.25.0 github.com/tree-sitter/tree-sitter-java v0.23.5 diff --git a/go.sum b/go.sum index 5ca7cd58..f43dec87 100644 --- a/go.sum +++ b/go.sum @@ -40,6 +40,8 @@ github.com/tree-sitter/go-tree-sitter v0.25.0 h1:sx6kcg8raRFCvc9BnXglke6axya12kr github.com/tree-sitter/go-tree-sitter v0.25.0/go.mod h1:r77ig7BikoZhHrrsjAnv8RqGti5rtSyvDHPzgTPsUuU= github.com/tree-sitter/tree-sitter-c v0.23.4 h1:nBPH3FV07DzAD7p0GfNvXM+Y7pNIoPenQWBpvM++t4c= github.com/tree-sitter/tree-sitter-c v0.23.4/go.mod h1:MkI5dOiIpeN94LNjeCp8ljXN/953JCwAby4bClMr6bw= +github.com/tree-sitter/tree-sitter-c-sharp v0.23.1 h1:ddG6osP34sMieVNN6lu5ZG/3N8Wn+67+43BmipqidyM= +github.com/tree-sitter/tree-sitter-c-sharp v0.23.1/go.mod h1:H7/aFm5vR1A8Yn5VIOfLWPdlKuJsMgZ5eDmaJdv8bY0= github.com/tree-sitter/tree-sitter-cpp v0.23.4 h1:LaWZsiqQKvR65yHgKmnaqA+uz6tlDJTJFCyFIeZU/8w= github.com/tree-sitter/tree-sitter-cpp v0.23.4/go.mod h1:doqNW64BriC7WBCQ1klf0KmJpdEvfxyXtoEybnBo6v8= github.com/tree-sitter/tree-sitter-embedded-template v0.23.2 h1:nFkkH6Sbe56EXLmZBqHHcamTpmz3TId97I16EnGy4rg= diff --git a/internal/parser/parser.go b/internal/parser/parser.go index e8a2529e..c5122f48 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -8,6 +8,7 @@ import ( tree_sitter_lua "github.com/tree-sitter-grammars/tree-sitter-lua/bindings/go" tree_sitter_cpp "github.com/tree-sitter/tree-sitter-cpp/bindings/go" + tree_sitter_c_sharp "github.com/tree-sitter/tree-sitter-c-sharp/bindings/go" tree_sitter_go "github.com/tree-sitter/tree-sitter-go/bindings/go" tree_sitter_java "github.com/tree-sitter/tree-sitter-java/bindings/go" tree_sitter_javascript "github.com/tree-sitter/tree-sitter-javascript/bindings/go" @@ -35,9 +36,9 @@ func initLanguages() { lang.Go: tree_sitter.NewLanguage(tree_sitter_go.Language()), lang.Rust: tree_sitter.NewLanguage(tree_sitter_rust.Language()), lang.Java: tree_sitter.NewLanguage(tree_sitter_java.Language()), - lang.CPP: tree_sitter.NewLanguage(tree_sitter_cpp.Language()), - // C# skipped: upstream module path mismatch (tree-sitter-c-sharp vs tree-sitter-c_sharp) - lang.PHP: tree_sitter.NewLanguage(tree_sitter_php.LanguagePHPOnly()), + lang.CPP: tree_sitter.NewLanguage(tree_sitter_cpp.Language()), + lang.CSharp: tree_sitter.NewLanguage(tree_sitter_c_sharp.Language()), + lang.PHP: tree_sitter.NewLanguage(tree_sitter_php.LanguagePHPOnly()), lang.Lua: tree_sitter.NewLanguage(tree_sitter_lua.Language()), lang.Scala: tree_sitter.NewLanguage(tree_sitter_scala.Language()), } diff --git a/internal/parser/parser_test.go b/internal/parser/parser_test.go index d085c406..f12d45af 100644 --- a/internal/parser/parser_test.go +++ b/internal/parser/parser_test.go @@ -77,9 +77,6 @@ class MyClass: func TestAllLanguagesLoad(t *testing.T) { for _, l := range lang.AllLanguages() { - if l == lang.CSharp { - continue // C# grammar has broken Go module path upstream - } _, err := GetLanguage(l) if err != nil { t.Errorf("GetLanguage(%s): %v", l, err) @@ -87,6 +84,50 @@ func TestAllLanguagesLoad(t *testing.T) { } } +func TestParseCSharp(t *testing.T) { + source := []byte(`using System; + +namespace MyApp { + public class Greeter { + public string Greet(string name) { + return $"Hello, {name}"; + } + + private void Helper() {} + } + + public enum Color { Red, Green, Blue } +} +`) + tree, err := Parse(lang.CSharp, source) + if err != nil { + t.Fatalf("Parse C#: %v", err) + } + defer tree.Close() + + root := tree.RootNode() + if root == nil { + t.Fatal("root node is nil") + } + + var classCount, methodCount int + Walk(root, func(n *tree_sitter.Node) bool { + switch n.Kind() { + case "class_declaration": + classCount++ + case "method_declaration": + methodCount++ + } + return true + }) + if classCount != 1 { + t.Errorf("expected 1 class_declaration, got %d", classCount) + } + if methodCount != 2 { + t.Errorf("expected 2 method_declarations, got %d", methodCount) + } +} + func TestNodeText(t *testing.T) { source := []byte(`package main