diff --git a/MODULE.bazel b/MODULE.bazel index 13636ddc..ca7a3bc6 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -101,6 +101,19 @@ visibility = ["//visibility:public"], urls = ["https://github.com/tree-sitter/tree-sitter-typescript/archive/v0.23.2.tar.gz"], ) +http_archive( + name = "tree-sitter-python", + build_file_content = """ +filegroup( + name = "srcs", + srcs = glob(["src/**/*.c", "src/**/*.h"]), + visibility = ["//visibility:public"], +) +""", + sha256 = "bc7c1c922b14cb0edd75c0400a63ff260e09bd02684351ed5d38586b5771cd69", + urls = ["https://github.com/tree-sitter/tree-sitter-python/releases/download/v0.23.6/tree-sitter-python.tar.xz"], +) + http_archive( name = "tree-sitter-ruby", build_file_content = """ diff --git a/common/treesitter/grammars/python/BUILD.bazel b/common/treesitter/grammars/python/BUILD.bazel new file mode 100644 index 00000000..c40a71ea --- /dev/null +++ b/common/treesitter/grammars/python/BUILD.bazel @@ -0,0 +1,14 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "python", + srcs = [ + "binding.go", + "@tree-sitter-python//:srcs", #keep + ], + cgo = True, + copts = ["-Iexternal/*tree-sitter-python"], #keep + importpath = "github.com/aspect-build/aspect-gazelle/common/treesitter/grammars/python", + visibility = ["//visibility:public"], + deps = ["//common/treesitter"], +) diff --git a/common/treesitter/grammars/python/binding.go b/common/treesitter/grammars/python/binding.go new file mode 100644 index 00000000..7e491eb7 --- /dev/null +++ b/common/treesitter/grammars/python/binding.go @@ -0,0 +1,17 @@ +package python + +//#include "tree_sitter/parser.h" +//TSLanguage *tree_sitter_python(); +import "C" +import ( + "unsafe" + + "github.com/aspect-build/aspect-gazelle/common/treesitter" +) + +func NewLanguage() treesitter.Language { + return treesitter.NewLanguage( + treesitter.Python, + unsafe.Pointer(C.tree_sitter_python()), + ) +} diff --git a/common/treesitter/parser.go b/common/treesitter/parser.go index 04ebce6d..2298f6de 100644 --- a/common/treesitter/parser.go +++ b/common/treesitter/parser.go @@ -54,6 +54,7 @@ const ( Go = "go" Rust = "rust" Ruby = "ruby" + Python = "python" ) type Language any @@ -154,6 +155,9 @@ var extLanguages = map[string]LanguageGrammar{ "thor": Ruby, "jbuilder": Ruby, "rabl": Ruby, + + "py": Python, + "pyi": Python, } // In theory, this is a mirror of diff --git a/language/orion/queries/BUILD.bazel b/language/orion/queries/BUILD.bazel index ff184ee4..9c493ddc 100644 --- a/language/orion/queries/BUILD.bazel +++ b/language/orion/queries/BUILD.bazel @@ -20,6 +20,7 @@ go_library( "@aspect_gazelle//common/treesitter/grammars/java", "@aspect_gazelle//common/treesitter/grammars/json", "@aspect_gazelle//common/treesitter/grammars/kotlin", + "@aspect_gazelle//common/treesitter/grammars/python", "@aspect_gazelle//common/treesitter/grammars/ruby", "@aspect_gazelle//common/treesitter/grammars/rust", "@aspect_gazelle//common/treesitter/grammars/starlark", diff --git a/language/orion/queries/ast.go b/language/orion/queries/ast.go index 92671f75..f218d2e9 100644 --- a/language/orion/queries/ast.go +++ b/language/orion/queries/ast.go @@ -10,6 +10,7 @@ import ( "github.com/aspect-build/aspect-gazelle/common/treesitter/grammars/java" "github.com/aspect-build/aspect-gazelle/common/treesitter/grammars/json" "github.com/aspect-build/aspect-gazelle/common/treesitter/grammars/kotlin" + "github.com/aspect-build/aspect-gazelle/common/treesitter/grammars/python" "github.com/aspect-build/aspect-gazelle/common/treesitter/grammars/ruby" "github.com/aspect-build/aspect-gazelle/common/treesitter/grammars/rust" "github.com/aspect-build/aspect-gazelle/common/treesitter/grammars/starlark" @@ -72,6 +73,8 @@ func toTreeLanguage(fileName string, queries plugin.NamedQueries) treesitter.Lan return json.NewLanguage() case treesitter.Kotlin: return kotlin.NewLanguage() + case treesitter.Python: + return python.NewLanguage() case treesitter.Ruby: return ruby.NewLanguage() case treesitter.Rust: diff --git a/language/orion/tests/starzelle/query-python/BUILD.in b/language/orion/tests/starzelle/query-python/BUILD.in new file mode 100644 index 00000000..8ec211d9 --- /dev/null +++ b/language/orion/tests/starzelle/query-python/BUILD.in @@ -0,0 +1 @@ +# gazelle:generation_mode update_only diff --git a/language/orion/tests/starzelle/query-python/BUILD.out b/language/orion/tests/starzelle/query-python/BUILD.out new file mode 100644 index 00000000..38b36217 --- /dev/null +++ b/language/orion/tests/starzelle/query-python/BUILD.out @@ -0,0 +1,24 @@ +load("@deps-test//my:rules.bzl", "x_lib") + +# gazelle:generation_mode update_only + +x_lib( + name = "a_lib", + srcs = ["a.py"], + deps = [ + ":b_lib", + ":s_lib", + ], +) + +x_lib( + name = "b_lib", + srcs = ["b.py"], + deps = ["//lib:l_lib"], +) + +x_lib( + name = "s_lib", + srcs = ["sub/s.py"], + deps = ["//lib:l_lib"], +) diff --git a/language/orion/tests/starzelle/query-python/WORKSPACE b/language/orion/tests/starzelle/query-python/WORKSPACE new file mode 100644 index 00000000..90b3a660 --- /dev/null +++ b/language/orion/tests/starzelle/query-python/WORKSPACE @@ -0,0 +1 @@ +workspace(name = "query-python") diff --git a/language/orion/tests/starzelle/query-python/a.py b/language/orion/tests/starzelle/query-python/a.py new file mode 100644 index 00000000..411d99f1 --- /dev/null +++ b/language/orion/tests/starzelle/query-python/a.py @@ -0,0 +1,2 @@ +import b +import sub.s diff --git a/language/orion/tests/starzelle/query-python/b.py b/language/orion/tests/starzelle/query-python/b.py new file mode 100644 index 00000000..af58f369 --- /dev/null +++ b/language/orion/tests/starzelle/query-python/b.py @@ -0,0 +1 @@ +import lib.l diff --git a/language/orion/tests/starzelle/query-python/imports.axl b/language/orion/tests/starzelle/query-python/imports.axl new file mode 100644 index 00000000..3a87f961 --- /dev/null +++ b/language/orion/tests/starzelle/query-python/imports.axl @@ -0,0 +1,46 @@ +aspect.gazelle_rule_kind("x_lib", { + "From": "@deps-test//my:rules.bzl", + "MergeableAttrs": ["srcs"], + "ResolveAttrs": ["deps"], +}) + +def prepare(_): + return aspect.PrepareResult( + sources = [aspect.SourceExtensions(".py")], + queries = { + "imports": aspect.AstQuery( + grammar = "python", + filter = "**/*.py", + query = "(import_statement name: (dotted_name) @imp)", + ), + }, + ) + +def declare(ctx): + for file in ctx.sources: + rel_modname = file.path[:file.path.rindex(".")].replace("/", ".") + ctx.targets.add( + name = path.base(file.path[:file.path.rindex(".")]) + "_lib", + kind = "x_lib", + attrs = { + "srcs": [file.path], + "deps": [ + aspect.Import( + id = i.captures["imp"], + provider = "x", + src = file.path, + ) + for i in file.query_results["imports"] + ], + }, + symbols = [aspect.Symbol( + id = ".".join([ctx.rel, rel_modname]) if ctx.rel else rel_modname, + provider = "x", + )], + ) + +aspect.orion_extension( + id = "python-test", + prepare = prepare, + declare = declare, +) diff --git a/language/orion/tests/starzelle/query-python/lib/BUILD.in b/language/orion/tests/starzelle/query-python/lib/BUILD.in new file mode 100644 index 00000000..e69de29b diff --git a/language/orion/tests/starzelle/query-python/lib/BUILD.out b/language/orion/tests/starzelle/query-python/lib/BUILD.out new file mode 100644 index 00000000..269b2d3c --- /dev/null +++ b/language/orion/tests/starzelle/query-python/lib/BUILD.out @@ -0,0 +1,6 @@ +load("@deps-test//my:rules.bzl", "x_lib") + +x_lib( + name = "l_lib", + srcs = ["l.py"], +) diff --git a/language/orion/tests/starzelle/query-python/lib/l.py b/language/orion/tests/starzelle/query-python/lib/l.py new file mode 100644 index 00000000..296d5492 --- /dev/null +++ b/language/orion/tests/starzelle/query-python/lib/l.py @@ -0,0 +1 @@ +console.log(1); diff --git a/language/orion/tests/starzelle/query-python/sub/s.py b/language/orion/tests/starzelle/query-python/sub/s.py new file mode 100644 index 00000000..fb5ba935 --- /dev/null +++ b/language/orion/tests/starzelle/query-python/sub/s.py @@ -0,0 +1,3 @@ +import lib.l + +print(1)