ruby_tree_sitter 0.20.8.1-x86_64-linux → 0.20.8.3-x86_64-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a6f2bbfd48e8ad005f6a1492fe5a77744d96ebbdefcfbb4444b4feb585793fa
4
- data.tar.gz: 27a035bbd5cc1ed84dd0ff0677022841f9f7a404d0bb28513fbb5ea8b1fc9626
3
+ metadata.gz: b3fcd4ccccb2f350cc4ce4bb0d29c8551a47c5f683d78c97e4654a630a8c1ffb
4
+ data.tar.gz: 8c07e7a2e6b943b234f69f426f41d194c31f44f612cb4b18ce23453ee8971259
5
5
  SHA512:
6
- metadata.gz: 27e3aed67258cfbc6684101d0e1c44ea2fdc852627001feb5c921353bc562a542f0c1c160d6e7f83fc7484842e69a3e1848fa55e58993b3a416832d8bfeca6aa
7
- data.tar.gz: 3ec4660b0996197367f76821fa1fc5bd4522658871eda1326a9470241fa144da3a5a4b976245147ee50bb9576dac385d043cd869e3e8cf47fd05cba584675083
6
+ metadata.gz: df6d2bd96e63e2a4113301fc3f03e9f96bc610ee9f295043eebdb21b9afdb5dd9e199e014c2d26b4ce4b47262f7f12d1e39b3e83468dfa51334200b302d58db1
7
+ data.tar.gz: 91b3014b446c489597ec8b029f7ebc6e7f9b6e7fb5e2e2fafb8ba2e091dcd6961770f5086b12c2725dfad7560ec05b7f4dcb186ac88e3443d0f3e7c1412ba4af
data/README.md CHANGED
@@ -85,24 +85,47 @@ brew install tree-sitter
85
85
 
86
86
  ## Install
87
87
 
88
- We haven't released the gem on `Rubygems` as of yet, but we'e planning on doing so.
88
+ From [rubygems](https://rubygems.org/gems/ruby_tree_sitter), in your `Gemfile`:
89
89
 
90
- Meanwhile, please install from `git` source, which will compile on installation.
90
+ ```ruby
91
+ gem 'ruby_tree_sitter', '~> 0.20.8.1'
92
+ ```
91
93
 
92
- If you don't want to install from `git`, or if you don't want to compile on
93
- install, download a native gem from this repository's
94
- [releases](https://github.com/Faveod/ruby-tree-sitter/releases), or you can
95
- compile it yourself (see [Build from
96
- source](docs/Development.md#build-from-source) .)
94
+ Or manually:
95
+
96
+ ```sh
97
+ gem install ruby_tree_sitter
98
+ ```
97
99
 
98
- ### Gemfile
100
+ Or from `git` sources, which will compile on installation:
99
101
 
100
102
  ```ruby
101
- gem 'tree_sitter', git: 'https://github.com/Faveod/ruby-tree-sitter'
103
+ gem 'ruby_tree_sitter', git: 'https://github.com/Faveod/ruby-tree-sitter'
104
+ ```
105
+
106
+ ### Disable system libraries
107
+
108
+ To install with `--disable-sys-lib`, you can either:
109
+
110
+ ```sh
111
+ gem install ruby_tree_sitter -- --disable-sys-libs
102
112
  ```
103
113
 
104
- If you chose to install a native gem, then you'd have to download it somewhere
105
- and then specify `path` as such:
114
+ Or via bundle:
115
+
116
+ ```sh
117
+ bundle config set build.ruby_tree_sitter --disable-sys-libs
118
+ ```
119
+
120
+ ### No compilation
121
+
122
+ If you don't want to install from `rubygems`, `git`, or if you don't want to
123
+ compile on install, then download a native gem from this repository's
124
+ [releases](https://github.com/Faveod/ruby-tree-sitter/releases), or you can
125
+ compile it yourself (see [Build from
126
+ source](docs/Development.md#build-from-source) .)
127
+
128
+ In that case, you'd have to point your `Gemfile` to the `gem` as such:
106
129
 
107
130
  ``` ruby
108
131
  gem 'tree_sitter', path: 'path/to/native/tree_sitter.gem'
@@ -118,6 +141,16 @@ You will have to install parsers yourself, either by:
118
141
  [Faveod/tree-sitter-parsers](https://github.com/Faveod/tree-sitter-parsers)
119
142
  which supports numerous architectures.
120
143
 
144
+ ### A note on static vs dynamic linking
145
+
146
+ This extension will statically link against a downloaded version of
147
+ `tree-sitter` when you use the `--disable-sys-lib`. So any installed version of
148
+ `tree-sitter` will not be loaded.
149
+
150
+ The native gems are also statically linked.
151
+
152
+ All other methods will dynamically link against the installed `tree-sitter`.
153
+
121
154
  ## Examples
122
155
 
123
156
  See `examples` directory.
@@ -1,6 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'mkmf'
2
4
  require 'pathname'
3
5
 
6
+ require_relative 'repo'
7
+
4
8
  # ################################## #
5
9
  # Some helpers #
6
10
  # ################################## #
@@ -14,63 +18,39 @@ def system_tree_sitter?
14
18
  enable_config('sys-libs', true)
15
19
  end
16
20
 
17
- def sh cmd
18
- if !system(cmd)
19
- abort <<~MSG
20
-
21
- Failed to run: #{cmd}
22
-
23
- exiting…
24
-
25
- MSG
26
- end
27
- end
28
-
29
21
  def env_var_on?(var)
30
22
  %w[1 on true t yes y].include?(ENV.fetch(var, '').downcase)
31
23
  end
32
24
 
33
25
  # ################################## #
34
- # System lib #
35
- # #
36
- # OR #
37
- # #
38
- # Downloaded libs #
26
+ # System lib vs Downloaded lib #
39
27
  # ################################## #
40
28
 
41
29
  dir_include, dir_lib =
42
30
  if system_tree_sitter?
43
- [['/opt/include', '/opt/local/include', '/usr/include', '/usr/local/include'],
44
- ['/opt/lib', '/opt/local/lib', '/usr/lib', '/usr/local/lib']]
31
+ [
32
+ %w[/opt/include /opt/local/include /usr/include /usr/local/include],
33
+ %w[/opt/lib /opt/local/lib /usr/lib /usr/local/lib]
34
+ ]
45
35
  else
46
- src = Pathname.pwd / "tree-sitter-#{TreeSitter::VERSION}"
47
- if !Dir.exist? src
48
- if find_executable('git')
49
- sh "git clone https://github.com/tree-sitter/tree-sitter #{src}"
50
- sh "cd #{src} && git checkout tags/v#{TreeSitter::VERSION}"
51
- elsif find_executable('curl')
52
- if find_executable('tar')
53
- sh "curl -L https://github.com/tree-sitter/tree-sitter/archive/refs/tags/v#{TreeSitter::VERSION}.tar.gz -o tree-sitter-v#{TreeSitter::VERSION}.tar.gz"
54
- sh "tar -xf tree-sitter-v#{TreeSitter::VERSION}.tar.gz"
55
- elsif find_executable('zip')
56
- sh "curl -L https://github.com/tree-sitter/tree-sitter/archive/refs/tags/v#{TreeSitter::VERSION}.zip -o tree-sitter-v#{TreeSitter::VERSION}.zip"
57
- sh "unzip -q tree-sitter-v#{TreeSitter::VERSION}.zip"
58
- else
59
- abort('Could not find `tar` or `zip` (and `git` was not found!)')
60
- end
61
- else
62
- abort('Could not find `git` or `curl` to download tree-sitter and build from sources.')
63
- end
36
+ repo = TreeSitter::Repo.new
37
+ if !repo.download
38
+ msg = <<~MSG
39
+
40
+ Could not fetch tree-sitter sources:
41
+
42
+ #{repo.exe.map { |k, v| "#{k}: #{v}" }.join("\n")}
43
+
44
+ MSG
45
+ abort(msg)
64
46
  end
65
47
 
66
48
  # We need to make sure we're selecting the proper toolchain.
67
49
  # Especially needed for corss-compilation.
68
50
  ENV.store('CC', RbConfig::CONFIG['CC'])
69
- # We need to clean because the same folder is used over and over
70
- # by rake-compiler-dock
71
- sh "cd #{src} && make clean && make"
72
-
73
- [[src / 'lib' / 'include'], [src.to_s]]
51
+ repo.compile
52
+ repo.keep_static_lib
53
+ repo.include_and_lib_dirs
74
54
  end
75
55
 
76
56
  # ################################## #
@@ -78,7 +58,6 @@ dir_include, dir_lib =
78
58
  # ################################## #
79
59
 
80
60
  header = find_header('tree_sitter/api.h', *dir_include)
81
-
82
61
  library = find_library('tree-sitter', # libtree-sitter
83
62
  'ts_parser_new', # a symbol
84
63
  *dir_lib)
@@ -100,9 +79,7 @@ if !header || !library
100
79
  MSG
101
80
  end
102
81
 
103
- if env_var_on?('TREE_SITTER_PEDANTIC')
104
- cflags << '-Werror'
105
- end
82
+ cflags << '-Werror' if env_var_on?('TREE_SITTER_PEDANTIC')
106
83
 
107
84
  if env_var_on?('DEBUG')
108
85
  cflags << '-fbounds-check'
@@ -61,12 +61,12 @@ static void logger_payload_set(logger_t *logger, VALUE value) {
61
61
  if (rb_respond_to(logger->payload, rb_intern("printf"))) {
62
62
  logger->data.log = logger_log_printf;
63
63
  } else if (rb_respond_to(logger->payload, rb_intern("puts"))) {
64
- logger->data.log = &logger_log_puts;
64
+ logger->data.log = logger_log_puts;
65
65
  } else {
66
- logger->data.log = &logger_log_write;
66
+ logger->data.log = logger_log_write;
67
67
  }
68
68
  } else if (!NIL_P(logger->payload)) {
69
- logger->data.log = &logger_log_write;
69
+ logger->data.log = logger_log_write;
70
70
  }
71
71
  }
72
72
 
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../lib/tree_sitter/version'
4
+
5
+ module TreeSitter
6
+ # Fetches tree-sitter sources.
7
+ class Repo
8
+ attr_reader :exe, :src, :url, :version
9
+
10
+ def initialize
11
+ @version = TREESITTER_VERSION
12
+
13
+ # `tree-sitter-@version` is the name produced by tagged releases of sources
14
+ # by git, so we use it everywhere, including when cloning from git.
15
+ @src = Pathname.pwd / "tree-sitter-#{@version}"
16
+
17
+ @url = {
18
+ git: 'https://github.com/tree-sitter/tree-sitter',
19
+ tar: "https://github.com/tree-sitter/tree-sitter/archive/refs/tags/v#{@version}.tar.gz",
20
+ zip: "https://github.com/tree-sitter/tree-sitter/archive/refs/tags/v#{@version}.zip"
21
+ }
22
+
23
+ @exe = {}
24
+ %i[curl git tar wget zip].each do |cmd|
25
+ @exe[cmd] = find_executable(cmd.to_s)
26
+ end
27
+ end
28
+
29
+ def compile
30
+ # We need to clean because the same folder is used over and over
31
+ # by rake-compiler-dock
32
+ sh "cd #{src} && make clean && make"
33
+ end
34
+
35
+ def exe?(name)
36
+ @exe[name]
37
+ end
38
+
39
+ def extract?
40
+ !exe.filter { |k, v| %i[tar zip].include?(k) && v }.empty?
41
+ end
42
+
43
+ def download
44
+ # TODO: should we force re-download? Maybe with a flag?
45
+ return true if Dir.exist? src
46
+
47
+ res = false
48
+ %w[git curl wget].each do |cmd|
49
+ res =
50
+ if find_executable(cmd)
51
+ send("sources_from_#{cmd}")
52
+ else
53
+ false
54
+ end
55
+ break if res
56
+ end
57
+
58
+ res
59
+ end
60
+
61
+ def include_and_lib_dirs
62
+ [[src / 'lib' / 'include'], [src.to_s]]
63
+ end
64
+
65
+ def keep_static_lib
66
+ src
67
+ .children
68
+ .filter { |f| /\.(dylib|so)/ =~ f.basename.to_s }
69
+ .each(&:unlink)
70
+ end
71
+
72
+ def sh(cmd)
73
+ return if system(cmd)
74
+
75
+ abort <<~MSG
76
+
77
+ Failed to run: #{cmd}
78
+
79
+ exiting …
80
+
81
+ MSG
82
+ end
83
+
84
+ def sources_from_curl
85
+ return false if !exe?(:curl) || !extract?
86
+
87
+ if exe?(:tar)
88
+ sh "curl -L #{url[:tar]} -o tree-sitter-v#{version}.tar.gz"
89
+ sh "tar -xf tree-sitter-v#{version}.tar.gz"
90
+ elsif exe?(:zip)
91
+ sh "curl -L #{url[:zip]} -o tree-sitter-v#{version}.zip"
92
+ sh "unzip -q tree-sitter-v#{version}.zip"
93
+ end
94
+
95
+ true
96
+ end
97
+
98
+ def sources_from_git
99
+ return false if !exe?(:git)
100
+
101
+ sh "git clone #{url[:git]} #{src}"
102
+ sh "cd #{src} && git checkout tags/v#{version}"
103
+
104
+ true
105
+ end
106
+
107
+ def sources_from_wget
108
+ return false if !exe?(:wget) || !extract?
109
+
110
+ if exe?(:tar)
111
+ sh "wget #{url[:tar]} -O tree-sitter-v#{version}.tar.gz"
112
+ sh "tar -xf tree-sitter-v#{version}.tar.gz"
113
+ elsif exe?(:zip)
114
+ sh "wget #{url[:zip]} -O tree-sitter-v#{version}.zip"
115
+ sh "unzip -q tree-sitter-v#{version}.zip"
116
+ end
117
+
118
+ true
119
+ end
120
+ end
121
+ end
@@ -76,7 +76,6 @@ module TreeSitter
76
76
  end
77
77
 
78
78
  def respond_to_missing?(*args)
79
- init_fields
80
79
  args.length == 1 && fields.include?(args[0])
81
80
  end
82
81
 
@@ -143,7 +142,12 @@ module TreeSitter
143
142
  # uses named_child | field_name_for_child
144
143
  # child_by_field_name | via each_node
145
144
  # ------------------------------+----------------------
146
- def fetch(*keys)
145
+ # @param all [Boolean] If `true`, return an array of nodes for all the
146
+ # demanded keys, putting `nil` for missing ones. If `false`, return the
147
+ # same array after calling `compact`. Defaults to `false`.
148
+ #
149
+ # See {#fetch_all}.
150
+ def fetch(*keys, all: false, **_kwargs)
147
151
  dict = {}
148
152
  keys.each.with_index do |k, i|
149
153
  dict[k.to_s] = i
@@ -152,13 +156,25 @@ module TreeSitter
152
156
  res = {}
153
157
  each_field do |f, c|
154
158
  if dict.key?(f)
155
- res[dict[f]] = c
159
+ res[f] = c
156
160
  dict.delete(f)
157
161
  end
158
162
  break if dict.empty?
159
163
  end
160
164
 
161
- res.sort.map { |_, v| v }
165
+ res = keys.uniq.map { |k| res[k.to_s] }
166
+ res = res.compact if !all
167
+ res
168
+ end
169
+
170
+ # Access all named children of a node, returning `nil` for missing ones.
171
+ #
172
+ # Equivalent to `fetch(…, all: true)`.
173
+ #
174
+ # See {#fetch}.
175
+ def fetch_all(*keys, **kwargs)
176
+ kwargs[:all] = true
177
+ fetch(*keys, **kwargs)
162
178
  end
163
179
  end
164
180
  end
Binary file
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TreeSitter
4
- VERSION = '0.20.8.1'
4
+ TREESITTER_VERSION = '0.20.8'
5
+ VERSION = "#{TREESITTER_VERSION}.3".freeze
5
6
  end
@@ -0,0 +1,48 @@
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
@@ -27,7 +27,12 @@ describe 'language' do
27
27
  if p = ENV.fetch('TREE_SITTER_PARSERS', nil)
28
28
  Pathname(p) / "libtree-sitter-ruby.#{TreeSitter.ext}"
29
29
  else
30
- Pathname('tree-sitter-parsers') / 'ruby' / "libtree-sitter-ruby.#{TreeSitter.ext}"
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
31
36
  end
32
37
  ll = TreeSitter::Language.load('ruby', path)
33
38
  assert ll.field_count.positive?
@@ -62,6 +62,7 @@ describe 'logging' do
62
62
  backend = StringIO.new
63
63
  parser.logger = TreeSitter::Logger.new(backend, "%s#{delim}%s")
64
64
  parser.parse_string(nil, program)
65
+ refute_empty backend.string, 'the backend should be filled with logs'
65
66
  backend.each_line do |l|
66
67
  assert (/#{delim}/ =~ l), 'delimiter must be in every single line'
67
68
  end
@@ -352,4 +352,60 @@ describe 'fetch' do
352
352
  assert_equal 1, m.length
353
353
  assert_equal method, m.first
354
354
  end
355
+
356
+ it 'should return an empty array when asked for non-existent fields' do
357
+ b = @child.fetch(:a)
358
+ assert_empty b
359
+
360
+ b = @child.fetch(:b, :focus)
361
+ assert_empty b
362
+ end
363
+
364
+ it 'should return an array of `nil` values when asked for non-existent fields with `all: true`' do
365
+ b = @child.fetch(:d, all: true)
366
+ refute_empty b
367
+ assert b.all?(&:nil?)
368
+
369
+ b = @child.fetch(:e, :f, all: true)
370
+ refute_empty b
371
+ assert b.all?(&:nil?)
372
+ end
373
+
374
+ it 'should return values, even if `nil`, for all keys when `all: true`' do
375
+ method = @child.child(0)
376
+ arguments = @child.child(1)
377
+
378
+ m, a, f = @child.fetch(:method, :arguments, :fake, all: true)
379
+
380
+ assert_equal method, m
381
+ assert_equal arguments, a
382
+ assert_nil f
383
+ end
384
+ end
385
+
386
+ describe 'fetch_all' do
387
+ before do
388
+ @child = root.child(0).child(4)
389
+ end
390
+
391
+ it 'should return an array of `nil` values when asked for non-existent fields' do
392
+ b = @child.fetch_all(:d)
393
+ refute_empty b
394
+ assert b.all?(&:nil?)
395
+
396
+ b = @child.fetch_all(:e, :f)
397
+ refute_empty b
398
+ assert b.all?(&:nil?)
399
+ end
400
+
401
+ it 'should return values, even if `nil`, for all keys' do
402
+ method = @child.child(0)
403
+ arguments = @child.child(1)
404
+
405
+ m, a, f = @child.fetch_all(:method, :arguments, :fake)
406
+
407
+ assert_equal method, m
408
+ assert_equal arguments, a
409
+ assert_nil f
410
+ end
355
411
  end
data/tree_sitter.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  lib = File.expand_path('lib', __dir__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ $LOAD_PATH.unshift(lib) if !$LOAD_PATH.include?(lib)
5
5
 
6
6
  require 'tree_sitter/version'
7
7
 
@@ -17,8 +17,8 @@ Gem::Specification.new do |spec|
17
17
  spec.version = TreeSitter::VERSION
18
18
 
19
19
  spec.extensions = %(ext/tree_sitter/extconf.rb)
20
- spec.files = %w(LICENSE README.md tree_sitter.gemspec)
21
- spec.files += Dir.glob('ext/**/*.[ch]')
20
+ spec.files = %w[LICENSE README.md tree_sitter.gemspec]
21
+ spec.files += Dir.glob('ext/**/*.{c,h,rb}')
22
22
  spec.files += Dir.glob('lib/**/*.rb')
23
23
  spec.test_files = Dir.glob('test/**/*')
24
24
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_tree_sitter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.8.1
4
+ version: 0.20.8.3
5
5
  platform: x86_64-linux
6
6
  authors:
7
7
  - Firas al-Khalil
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-20 00:00:00.000000000 Z
11
+ date: 2023-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -135,6 +135,7 @@ files:
135
135
  - ext/tree_sitter/query_match.c
136
136
  - ext/tree_sitter/query_predicate_step.c
137
137
  - ext/tree_sitter/range.c
138
+ - ext/tree_sitter/repo.rb
138
139
  - ext/tree_sitter/symbol_type.c
139
140
  - ext/tree_sitter/tree.c
140
141
  - ext/tree_sitter/tree_cursor.c
@@ -146,6 +147,7 @@ files:
146
147
  - lib/tree_sitter/version.rb
147
148
  - test/README.md
148
149
  - test/test_helper.rb
150
+ - test/tree_sitter/js_test.rb
149
151
  - test/tree_sitter/language_test.rb
150
152
  - test/tree_sitter/logger_test.rb
151
153
  - test/tree_sitter/node_test.rb
@@ -183,6 +185,7 @@ summary: Ruby bindings for Tree-Sitter
183
185
  test_files:
184
186
  - test/README.md
185
187
  - test/test_helper.rb
188
+ - test/tree_sitter/js_test.rb
186
189
  - test/tree_sitter/language_test.rb
187
190
  - test/tree_sitter/logger_test.rb
188
191
  - test/tree_sitter/node_test.rb