ruby_tree_sitter 0.20.8.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +2 -1
  3. data/README.md +32 -18
  4. data/ext/tree_sitter/extconf.rb +1 -1
  5. data/ext/tree_sitter/input.c +1 -0
  6. data/ext/tree_sitter/language.c +131 -46
  7. data/ext/tree_sitter/logger.c +28 -12
  8. data/ext/tree_sitter/node.c +438 -130
  9. data/ext/tree_sitter/parser.c +232 -37
  10. data/ext/tree_sitter/query.c +197 -72
  11. data/ext/tree_sitter/query_cursor.c +140 -28
  12. data/ext/tree_sitter/repo.rb +1 -1
  13. data/ext/tree_sitter/tree.c +118 -34
  14. data/ext/tree_sitter/tree_cursor.c +205 -33
  15. data/ext/tree_sitter/tree_sitter.c +12 -0
  16. data/lib/tree_sitter/node.rb +23 -6
  17. data/lib/tree_sitter/version.rb +4 -2
  18. data/lib/tree_sitter.rb +1 -0
  19. data/lib/tree_stand/ast_modifier.rb +30 -0
  20. data/lib/tree_stand/breadth_first_visitor.rb +54 -0
  21. data/lib/tree_stand/config.rb +13 -0
  22. data/lib/tree_stand/node.rb +224 -0
  23. data/lib/tree_stand/parser.rb +67 -0
  24. data/lib/tree_stand/range.rb +55 -0
  25. data/lib/tree_stand/tree.rb +123 -0
  26. data/lib/tree_stand/utils/printer.rb +73 -0
  27. data/lib/tree_stand/version.rb +7 -0
  28. data/lib/tree_stand/visitor.rb +127 -0
  29. data/lib/tree_stand/visitors/tree_walker.rb +37 -0
  30. data/lib/tree_stand.rb +48 -0
  31. data/tree_sitter.gemspec +14 -11
  32. metadata +37 -108
  33. data/test/README.md +0 -15
  34. data/test/test_helper.rb +0 -9
  35. data/test/tree_sitter/js_test.rb +0 -48
  36. data/test/tree_sitter/language_test.rb +0 -73
  37. data/test/tree_sitter/logger_test.rb +0 -70
  38. data/test/tree_sitter/node_test.rb +0 -411
  39. data/test/tree_sitter/parser_test.rb +0 -140
  40. data/test/tree_sitter/query_test.rb +0 -153
  41. data/test/tree_sitter/tree_cursor_test.rb +0 -83
  42. data/test/tree_sitter/tree_test.rb +0 -51
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+ module TreeStand
5
+ # A collection of useful visitors for traversing trees.
6
+ module Visitors
7
+ # Walks the tree depth-first and yields each node to the provided block.
8
+ #
9
+ # @example Create a list of all the nodes in the tree.
10
+ # list = []
11
+ # TreeStand::Visitors::TreeWalker.new(root) do |node|
12
+ # list << node
13
+ # end.visit
14
+ #
15
+ # @see TreeStand::Node#walk
16
+ # @see TreeStand::Tree#walk
17
+ class TreeWalker < Visitor
18
+ extend T::Sig
19
+
20
+ # @param block [Proc] A block that will be called for
21
+ # each node in the tree.
22
+ sig do
23
+ params(
24
+ node: TreeStand::Node,
25
+ block: T.proc.params(node: TreeStand::Node).void,
26
+ ).void
27
+ end
28
+ def initialize(node, &block)
29
+ super(node)
30
+ @block = block
31
+ end
32
+
33
+ sig { override.params(node: TreeStand::Node).void }
34
+ def on(node) = @block.call(node)
35
+ end
36
+ end
37
+ end
data/lib/tree_stand.rb ADDED
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+ require 'forwardable'
5
+ require 'sorbet-runtime'
6
+ require 'stringio'
7
+ require 'tree_sitter'
8
+ require 'zeitwerk'
9
+
10
+ loader = Zeitwerk::Loader.for_gem
11
+ loader.ignore("#{__dir__}/tree_sitter")
12
+ loader.ignore("#{__dir__}/tree_sitter.rb")
13
+ loader.setup
14
+
15
+ # TreeStand is a high-level Ruby wrapper for {https://tree-sitter.github.io/tree-sitter tree-sitter} bindings. It makes
16
+ # it easier to configure the parsers, and work with the underlying syntax tree.
17
+ module TreeStand
18
+ # Common Ancestor for all TreeStand errors.
19
+ class Error < StandardError; end
20
+ # Raised when the parsed document contains errors.
21
+ class InvalidDocument < Error; end
22
+ # Raised when performing a search on a tree where a return value is expected,
23
+ # but no match is found.
24
+ class NodeNotFound < Error; end
25
+
26
+ class << self
27
+ extend T::Sig
28
+
29
+ # Easy configuration of the gem.
30
+ #
31
+ # @example
32
+ # TreeStand.configure do
33
+ # config.parser_path = "path/to/parser/folder/"
34
+ # end
35
+ #
36
+ # sql_parser = TreeStand::Parser.new("sql")
37
+ # ruby_parser = TreeStand::Parser.new("ruby")
38
+ sig { params(block: T.proc.void).void }
39
+ def configure(&block)
40
+ instance_eval(&block)
41
+ end
42
+
43
+ sig { returns(TreeStand::Config) }
44
+ def config
45
+ @config ||= Config.new
46
+ end
47
+ end
48
+ end
data/tree_sitter.gemspec CHANGED
@@ -6,27 +6,30 @@ $LOAD_PATH.unshift(lib) if !$LOAD_PATH.include?(lib)
6
6
  require 'tree_sitter/version'
7
7
 
8
8
  Gem::Specification.new do |spec|
9
- spec.required_ruby_version = '>= 2.7'
9
+ spec.required_ruby_version = '>= 3.0'
10
10
 
11
- spec.authors = ['Firas al-Khalil']
12
- spec.email = ['firasalkhalil@gmail.com']
11
+ spec.authors = ['Firas al-Khalil', 'Derek Stride']
12
+ spec.email = ['firasalkhalil@gmail.com', 'derek@stride.host']
13
13
  spec.homepage = 'https://www.github.com/Faveod/ruby-tree-sitter'
14
14
  spec.license = 'MIT'
15
15
  spec.name = 'ruby_tree_sitter'
16
16
  spec.summary = 'Ruby bindings for Tree-Sitter'
17
17
  spec.version = TreeSitter::VERSION
18
18
 
19
+ spec.metadata = {
20
+ 'allowed_push_host' => 'https://rubygems.org',
21
+ 'homepage_uri' => spec.homepage,
22
+ 'source_code_uri' => spec.homepage,
23
+ 'changelog_uri' => spec.homepage,
24
+ 'documentation_uri' => 'https://faveod.github.io/ruby-tree-sitter/',
25
+ }
26
+
19
27
  spec.extensions = %(ext/tree_sitter/extconf.rb)
20
28
  spec.files = %w[LICENSE README.md tree_sitter.gemspec]
21
29
  spec.files += Dir.glob('ext/**/*.{c,h,rb}')
22
30
  spec.files += Dir.glob('lib/**/*.rb')
23
- spec.test_files = Dir.glob('test/**/*')
31
+ spec.require_paths = ['lib']
24
32
 
25
- spec.add_development_dependency('minitest', '~> 5.16')
26
- spec.add_development_dependency('minitest-color', '~> 0.0.2')
27
- spec.add_development_dependency('pry', '~> 0.14')
28
- spec.add_development_dependency('rake', '~> 13.0')
29
- spec.add_development_dependency('rake-compiler', '~> 1.2')
30
- spec.add_development_dependency('rake-compiler-dock', '~> 1.2')
31
- spec.add_development_dependency('ruby_memcheck', '~> 1.0')
33
+ spec.add_dependency 'sorbet-runtime'
34
+ spec.add_dependency 'zeitwerk'
32
35
  end
metadata CHANGED
@@ -1,116 +1,48 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_tree_sitter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.8.3
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Firas al-Khalil
8
+ - Derek Stride
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2023-12-18 00:00:00.000000000 Z
12
+ date: 2024-02-26 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
- name: minitest
15
+ name: sorbet-runtime
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
- - - "~>"
18
+ - - ">="
18
19
  - !ruby/object:Gem::Version
19
- version: '5.16'
20
- type: :development
20
+ version: '0'
21
+ type: :runtime
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
- - - "~>"
25
+ - - ">="
25
26
  - !ruby/object:Gem::Version
26
- version: '5.16'
27
+ version: '0'
27
28
  - !ruby/object:Gem::Dependency
28
- name: minitest-color
29
+ name: zeitwerk
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
- - - "~>"
32
+ - - ">="
32
33
  - !ruby/object:Gem::Version
33
- version: 0.0.2
34
- type: :development
34
+ version: '0'
35
+ type: :runtime
35
36
  prerelease: false
36
37
  version_requirements: !ruby/object:Gem::Requirement
37
38
  requirements:
38
- - - "~>"
39
+ - - ">="
39
40
  - !ruby/object:Gem::Version
40
- version: 0.0.2
41
- - !ruby/object:Gem::Dependency
42
- name: pry
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '0.14'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '0.14'
55
- - !ruby/object:Gem::Dependency
56
- name: rake
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '13.0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '13.0'
69
- - !ruby/object:Gem::Dependency
70
- name: rake-compiler
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '1.2'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '1.2'
83
- - !ruby/object:Gem::Dependency
84
- name: rake-compiler-dock
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '1.2'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '1.2'
97
- - !ruby/object:Gem::Dependency
98
- name: ruby_memcheck
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '1.0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '1.0'
41
+ version: '0'
111
42
  description:
112
43
  email:
113
44
  - firasalkhalil@gmail.com
45
+ - derek@stride.host
114
46
  executables: []
115
47
  extensions:
116
48
  - ext/tree_sitter/extconf.rb
@@ -145,21 +77,28 @@ files:
145
77
  - lib/tree_sitter.rb
146
78
  - lib/tree_sitter/node.rb
147
79
  - lib/tree_sitter/version.rb
148
- - test/README.md
149
- - test/test_helper.rb
150
- - test/tree_sitter/js_test.rb
151
- - test/tree_sitter/language_test.rb
152
- - test/tree_sitter/logger_test.rb
153
- - test/tree_sitter/node_test.rb
154
- - test/tree_sitter/parser_test.rb
155
- - test/tree_sitter/query_test.rb
156
- - test/tree_sitter/tree_cursor_test.rb
157
- - test/tree_sitter/tree_test.rb
80
+ - lib/tree_stand.rb
81
+ - lib/tree_stand/ast_modifier.rb
82
+ - lib/tree_stand/breadth_first_visitor.rb
83
+ - lib/tree_stand/config.rb
84
+ - lib/tree_stand/node.rb
85
+ - lib/tree_stand/parser.rb
86
+ - lib/tree_stand/range.rb
87
+ - lib/tree_stand/tree.rb
88
+ - lib/tree_stand/utils/printer.rb
89
+ - lib/tree_stand/version.rb
90
+ - lib/tree_stand/visitor.rb
91
+ - lib/tree_stand/visitors/tree_walker.rb
158
92
  - tree_sitter.gemspec
159
93
  homepage: https://www.github.com/Faveod/ruby-tree-sitter
160
94
  licenses:
161
95
  - MIT
162
- metadata: {}
96
+ metadata:
97
+ allowed_push_host: https://rubygems.org
98
+ homepage_uri: https://www.github.com/Faveod/ruby-tree-sitter
99
+ source_code_uri: https://www.github.com/Faveod/ruby-tree-sitter
100
+ changelog_uri: https://www.github.com/Faveod/ruby-tree-sitter
101
+ documentation_uri: https://faveod.github.io/ruby-tree-sitter/
163
102
  post_install_message:
164
103
  rdoc_options: []
165
104
  require_paths:
@@ -168,25 +107,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
168
107
  requirements:
169
108
  - - ">="
170
109
  - !ruby/object:Gem::Version
171
- version: '2.7'
110
+ version: '3.0'
172
111
  required_rubygems_version: !ruby/object:Gem::Requirement
173
112
  requirements:
174
113
  - - ">="
175
114
  - !ruby/object:Gem::Version
176
115
  version: '0'
177
116
  requirements: []
178
- rubygems_version: 3.4.10
117
+ rubygems_version: 3.4.19
179
118
  signing_key:
180
119
  specification_version: 4
181
120
  summary: Ruby bindings for Tree-Sitter
182
- test_files:
183
- - test/README.md
184
- - test/test_helper.rb
185
- - test/tree_sitter/js_test.rb
186
- - test/tree_sitter/language_test.rb
187
- - test/tree_sitter/logger_test.rb
188
- - test/tree_sitter/node_test.rb
189
- - test/tree_sitter/parser_test.rb
190
- - test/tree_sitter/query_test.rb
191
- - test/tree_sitter/tree_cursor_test.rb
192
- - test/tree_sitter/tree_test.rb
121
+ test_files: []
data/test/README.md DELETED
@@ -1,15 +0,0 @@
1
- # Unit testing
2
-
3
- Since we don't have languages bundled in ruby gems, we have to load the dynamic
4
- libraries from disk.
5
-
6
- We're using the `bin/get` scripts to do so.
7
-
8
- Since not all languages have a Makefile in their root dir, and we don't want to
9
- mess with copying Makefiles, we're going to rely on languages that do have a
10
- Makefile in their root.
11
-
12
- So for the time being we're sticking with `ruby`.
13
-
14
- We might need to change this strategy in the future if we're to test some
15
- multilang parsing.
data/test/test_helper.rb DELETED
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- at_exit { GC.start }
4
-
5
- require 'minitest/autorun'
6
- require 'minitest/color'
7
- require 'tree_sitter'
8
-
9
- require_relative '../examples/helpers'
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../test_helper'
4
-
5
- js = TreeSitter.lang('javascript')
6
- parser = TreeSitter::Parser.new
7
- parser.language = js
8
-
9
- program = <<~JS
10
- let a = 42;
11
- JS
12
-
13
- describe 'loading a language' do
14
- before do
15
- parser.reset
16
- end
17
-
18
- it 'must set/get the same language' do
19
- parser.language = js
20
- assert_equal js, parser.language
21
- end
22
- end
23
-
24
- describe 'parse_string' do
25
- before do
26
- parser.reset
27
- end
28
-
29
- it 'must parse nil' do
30
- res = parser.parse_string(nil, nil)
31
- assert_nil res
32
- end
33
-
34
- [
35
- ['empty', '', 0],
36
- ['valid', program, 1],
37
- # ['invalid', margorp, 3]
38
- ].each do |q, p, c|
39
- it "must parse #{q} programs" do
40
- res = parser.parse_string(nil, p)
41
- assert_instance_of TreeSitter::Tree, res
42
-
43
- root = res.root_node
44
- assert_instance_of TreeSitter::Node, root
45
- assert_equal c, root.child_count
46
- end
47
- end
48
- end
@@ -1,73 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../test_helper'
4
-
5
- ruby = TreeSitter.lang('ruby')
6
- parser = TreeSitter::Parser.new
7
- parser.language = ruby
8
-
9
- program = <<~RUBY
10
- def mul(a, b)
11
- res = a * b
12
- puts res.inspect
13
- return res
14
- end
15
- RUBY
16
-
17
- tree = parser.parse_string(nil, program)
18
- root = tree.root_node
19
-
20
- # NOTE: one should be weary of testing with data structures that are owned by
21
- # parsers. They are not reliable and we should expect them to break when these
22
- # parsers evolve.
23
-
24
- describe 'language' do
25
- it 'must be able to load a library from `Pathname` (or any object that has `to_s`)' do
26
- path =
27
- if p = ENV.fetch('TREE_SITTER_PARSERS', nil)
28
- Pathname(p) / "libtree-sitter-ruby.#{TreeSitter.ext}"
29
- else
30
- downloaded = Pathname('tree-sitter-parsers') / "libtree-sitter-ruby.#{TreeSitter.ext}"
31
- if !downloaded.exist?
32
- Pathname('tree-sitter-parsers') / "ruby" / "libtree-sitter-ruby.#{TreeSitter.ext}"
33
- else
34
- downloaded
35
- end
36
- end
37
- ll = TreeSitter::Language.load('ruby', path)
38
- assert ll.field_count.positive?
39
- end
40
-
41
- it 'must return symbol count' do
42
- assert ruby.symbol_count.positive?
43
- end
44
-
45
- it 'must return symbol name' do
46
- assert_equal 'end', ruby.symbol_name(0)
47
- end
48
-
49
- it 'must return symbol id for string name' do
50
- assert ruby.symbol_for_name(root.type, root.named?).positive?
51
- end
52
-
53
- it 'must return field count' do
54
- assert ruby.field_count.positive?
55
- end
56
-
57
- it 'must return field name for id' do
58
- assert_equal 'alias', ruby.field_name_for_id(1)
59
- end
60
-
61
- it 'must return field name for id' do
62
- assert_equal 1, ruby.field_id_for_name('alias')
63
- end
64
-
65
- it 'must return field symbol type' do
66
- assert_equal TreeSitter::SymbolType::AUXILIARY, ruby.symbol_type(0)
67
- end
68
-
69
- it 'must be of correct version' do
70
- assert ruby.version <= TreeSitter::LANGUAGE_VERSION \
71
- && ruby.version >= TreeSitter::MIN_COMPATIBLE_LANGUAGE_VERSION
72
- end
73
- end
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../test_helper'
4
- require 'stringio'
5
-
6
- ruby = TreeSitter.lang('ruby')
7
- parser = TreeSitter::Parser.new
8
- parser.language = ruby
9
-
10
- program = <<~RUBY
11
- def mul(a, b)
12
- res = a * b
13
- puts res.inspect
14
- return res
15
- end
16
- RUBY
17
-
18
- # Use with fork.
19
- #
20
- # Minitest on ruby 2.7 was failing sometimes for no particular reason,
21
- # complaining about some random number not having a `write` method.
22
- #
23
- # My assumption is that the global var $stderr is not playing nice when
24
- # we try to replace it and other minitest stuff are going alongside.
25
- #
26
- # If this theory holds, then forking should solve any race conditions that
27
- # minitest could introduce. Let's wait and see.
28
- def capture_stderr
29
- # The output stream must be an IO-like object. In this case we capture it in
30
- # an in-memory IO object so we can return the string value. You can assign any
31
- # IO object here.
32
- previous_stderr = $stderr
33
- $stderr = StringIO.new
34
- yield
35
- $stderr.string
36
- ensure
37
- # Restore the previous value of stderr (typically equal to STDERR).
38
- $stderr = previous_stderr
39
- end
40
-
41
- describe 'logging' do
42
- it 'should log to stderr by default' do
43
- fork do
44
- captured_output = capture_stderr do
45
- # Does not output anything directly.
46
- parser.logger = TreeSitter::Logger.new
47
- parser.parse_string(nil, program)
48
- end
49
- refute_equal 0, captured_output.length
50
- end
51
- end
52
-
53
- it 'should log to IO objects' do
54
- backend = StringIO.new
55
- parser.logger = TreeSitter::Logger.new(backend)
56
- parser.parse_string(nil, program)
57
- refute_equal 0, backend.length
58
- end
59
-
60
- it 'should format output when a format string is passed' do
61
- delim = '~~~~~'
62
- backend = StringIO.new
63
- parser.logger = TreeSitter::Logger.new(backend, "%s#{delim}%s")
64
- parser.parse_string(nil, program)
65
- refute_empty backend.string, 'the backend should be filled with logs'
66
- backend.each_line do |l|
67
- assert (/#{delim}/ =~ l), 'delimiter must be in every single line'
68
- end
69
- end
70
- end