ruby_tree_sitter 1.3.0-x86_64-linux → 1.4.1-x86_64-linux

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a0f7c51b289e769ad5701be586b28d61f41f0979ee6fd3c08f87481ae307f146
4
- data.tar.gz: 988052e5b5b5c41e9a9d974398c6c6cae401f2068a2ad4013d80198f3437c029
3
+ metadata.gz: 70e2391699fd48cf5f18b50df59b7c5929c09e07f18a366a94c24ce381754fe0
4
+ data.tar.gz: b66813822fe232322d4e4e841975a68d42d6454dcaf47b3b814875bed4f009a9
5
5
  SHA512:
6
- metadata.gz: 9ef62c5ea3bd4451b03b43e6efc2c3501191ffcd9ea96dfe12d2e66b249d1f16f58e82d6127d833a6c8105e3f910dda2ba898a138d5e6d2756615bf69fcb2e05
7
- data.tar.gz: 5bd46cc66e845c9091005a5eadeccb3db2984e0bbc5bf6d12e9fc4e3fd126f9ab6f1d37970fbe6760eee096ec2c011d4d328d5610a9e873ed313df3842caceb3
6
+ metadata.gz: 37dcb03d0061b0a019167924f2ded1c0291463e3a08d7e6ff58c9e8e121fcafa484d8effe77907fde05b47a1c77f1d5f71bb234c2ce44bce29e5a3d9c6c4dac9
7
+ data.tar.gz: b099f9953c709cc9edf745309e9b8a155b668947bc59c2abfe13e4bee7d0ba7ac9211facf654b0123eb5750cd04aeefc261a6904cae596a9f466def182c9618e
data/README.md CHANGED
@@ -200,4 +200,8 @@ To See a full list of the ruby-specific APIs, see [here](lib/README.md).
200
200
 
201
201
  ## Sponsors
202
202
 
203
- <img src="img/faveod.jpg" width="75%">
203
+ - <a href="https://faveod.com">https://faveod.com</a>
204
+
205
+ <a href="https://faveod.com">
206
+ <img src="img/faveod.jpg" width="66%" />
207
+ </a>
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreeSitter
4
+ # A colon-separated list of paths pointing to directories that can contain parsers.
5
+ # Order matters.
6
+ # Takes precedence over default lookup paths.
7
+ ENV_PARSERS =
8
+ ENV['TREE_SITTER_PARSERS']
9
+ &.split(':')
10
+ &.map { |v| Pathname(v) }
11
+ .freeze
12
+
13
+ # The default paths we use to lookup parsers.
14
+ # Order matters.
15
+ LIBDIRS = [
16
+ '.vendor/parsers',
17
+ '.vendor/tree-sitter-parsers',
18
+ 'vendor/parsers',
19
+ 'vendor/tree-sitter-parsers',
20
+ 'parsers',
21
+ 'tree-sitter-parsers',
22
+ '/opt/local/lib',
23
+ '/opt/lib',
24
+ '/usr/local/lib',
25
+ '/usr/lib',
26
+ ].map { |p| Pathname(p) }.freeze
27
+
28
+ # Mixins.
29
+ module Mixins
30
+ # Language Mixin.
31
+ module Language
32
+ # Load a language from configuration or default lookup paths.
33
+ #
34
+ # @example Load java from default paths
35
+ # # This will look for:
36
+ # #
37
+ # # .vendor/tree-sitter-parsers/(java/)?(libtree-sitter-)?java.{ext}
38
+ # # .vendor/parsers/(java/)?(libtree-sitter-)?java.{ext}
39
+ # # vendor/tree-sitter-parsers/(java/)?(libtree-sitter-)?java.{ext}
40
+ # # vendor/parsers/(java/)?(libtree-sitter-)?java.{ext}
41
+ # # parsers/(java/)?(libtree-sitter-)?java.{ext}
42
+ # # tree-sitter-parsers/(java/)?(libtree-sitter-)?java.{ext}
43
+ # # /opt/local/lib/(java/)?(libtree-sitter-)?java.{ext}
44
+ # # /opt/lib/(java/)?(libtree-sitter-)?java.{ext}
45
+ # # /usr/local/lib/(java/)?(libtree-sitter-)?java.{ext}
46
+ # # /usr/lib/(java/)?(libtree-sitter-)?java.{ext}
47
+ # #
48
+ # java = TreeSitter.language('java')
49
+ #
50
+ # @example (TreeStand) Load java from a configured path
51
+ # # This will look for:
52
+ # #
53
+ # # /my/path/(java/)?(libtree-sitter-)?java.{ext}
54
+ # #
55
+ # TreeStand.config.parser_path = '/my/path'
56
+ # java = TreeStand::Parser.language('java')
57
+ #
58
+ # @example (TreeStand) Load java from environment variables
59
+ # # This will look for:
60
+ # #
61
+ # # /my/forced/env/path/(java/)?(libtree-sitter-)?java.{ext}
62
+ # # /my/path/(java/)?(libtree-sitter-)?java.{ext}
63
+ # #
64
+ # # … and the same works for the default paths if `TreeStand.config.parser_path`
65
+ # # was `nil`
66
+ # ENV['TREE_SITTER_PARSERS'] = '/my/forced/env/path'
67
+ # TreeStand.config.parser_path = '/my/path'
68
+ # java = TreeStand::Parser.language('java')
69
+ #
70
+ # @param name [String] the name of the parser.
71
+ # This name is used to load the symbol from the compiled parser, replacing `-` with `_`.
72
+ #
73
+ # @return [TreeSitter:language] a language object to use in your parsers.
74
+ #
75
+ # @raise [RuntimeError] if the parser was not found.
76
+ #
77
+ # @see search_for_lib
78
+ def language(name)
79
+ lib = search_for_lib(name)
80
+
81
+ if lib.nil?
82
+ raise <<~MSG.chomp
83
+ Failed to load a parser for #{name}.
84
+
85
+ #{search_lib_message}
86
+ MSG
87
+ end
88
+
89
+ # We know that the bindings will accept `lib`, but I don't know how to tell sorbet
90
+ # the types in ext/tree_sitter where `load` is defined.
91
+ TreeSitter::Language.load(name.tr('-', '_'), T.unsafe(lib))
92
+ end
93
+
94
+ # The platform-specific extension of the parser.
95
+ # @return [String] `dylib` or `so` for mac or linux.
96
+ def ext
97
+ case Gem::Platform.local.os
98
+ in /darwin/ then 'dylib'
99
+ else 'so'
100
+ end
101
+ end
102
+
103
+ private
104
+
105
+ # The library directories we need to look into.
106
+ #
107
+ # @return [Array<Pathname>] the list of candidate places to use when searching for parsers.
108
+ #
109
+ # @see ENV_PARSERS
110
+ # @see LIBDIRS
111
+ def lib_dirs = [*TreeSitter::ENV_PARSERS, *TreeSitter::LIBDIRS]
112
+
113
+ # Lookup a parser by name.
114
+ #
115
+ # Precedence:
116
+ # 1. `Env['TREE_SITTER_PARSERS]`.
117
+ # 2. {TreeStand::Config#parser_path} if using {TreeStand}.
118
+ # 3. {LIBDIRS}.
119
+ #
120
+ # If a {TreeStand::Config#parser_path} is `nil`, {LIBDIRS} is used.
121
+ # If a {TreeStand::Config#parser_path} is a {::Pathname}, {LIBDIRS} is ignored.
122
+ def search_for_lib(name)
123
+ files = [
124
+ name,
125
+ "tree-sitter-#{name}",
126
+ "libtree-sitter-#{name}",
127
+ ].map { |v| "#{v}.#{ext}" }
128
+
129
+ lib_dirs
130
+ .product(files)
131
+ .find do |dir, so|
132
+ path = dir / so
133
+ path = dir / name / so if !path.exist?
134
+ break path.expand_path if path.exist?
135
+ end
136
+ end
137
+
138
+ # Generates a string message on where parser lookup happens.
139
+ #
140
+ # @return [String] A pretty message.
141
+ def search_lib_message
142
+ indent = 2
143
+ pretty = ->(arr) {
144
+ if arr
145
+ arr
146
+ .compact
147
+ .map { |v| "#{' ' * indent}#{v.expand_path}" }
148
+ .join("\n")
149
+ end
150
+ }
151
+ <<~MSG.chomp
152
+ From ENV['TREE_SITTER_PARSERS']:
153
+ #{pretty.call(ENV_PARSERS)}
154
+
155
+ From Defaults:
156
+ #{pretty.call(lib_dirs)}
157
+ MSG
158
+ end
159
+ end
160
+ end
161
+ end
@@ -3,6 +3,8 @@
3
3
  module TreeSitter
4
4
  # Node is a wrapper around a tree-sitter node.
5
5
  class Node
6
+ include Enumerable
7
+
6
8
  # @return [Array<Symbol>] the node's named fields
7
9
  def fields
8
10
  return @fields if @fields
@@ -87,10 +89,10 @@ module TreeSitter
87
89
  # Iterate over a node's children.
88
90
  #
89
91
  # @yieldparam child [Node] the child
90
- def each
92
+ def each(&_block)
91
93
  return enum_for __method__ if !block_given?
92
94
 
93
- (0...(child_count)).each do |i|
95
+ (0...child_count).each do |i|
94
96
  yield child(i)
95
97
  end
96
98
  end
@@ -3,6 +3,8 @@
3
3
  module TreeSitter
4
4
  # A sequence of {TreeSitter::QueryCapture} associated with a given {TreeSitter::QueryCursor}.
5
5
  class QueryCaptures
6
+ include Enumerable
7
+
6
8
  def initialize(cursor, query, src)
7
9
  @cursor = cursor
8
10
  @query = query
@@ -13,7 +15,7 @@ module TreeSitter
13
15
  #
14
16
  # @yieldparam match [TreeSitter::QueryMatch]
15
17
  # @yieldparam capture_index [Integer]
16
- def each
18
+ def each(&_block)
17
19
  return enum_for __method__ if !block_given?
18
20
 
19
21
  while (capture_index, match = @cursor.next_capture)
@@ -3,6 +3,8 @@
3
3
  module TreeSitter
4
4
  # A sequence of {QueryMatch} associated with a given {QueryCursor}.
5
5
  class QueryMatches
6
+ include Enumerable
7
+
6
8
  def initialize(cursor, query, src)
7
9
  @cursor = cursor
8
10
  @query = query
@@ -12,7 +14,7 @@ module TreeSitter
12
14
  # Iterator over matches.
13
15
  #
14
16
  # @yieldparam match [TreeSitter::QueryMatch]
15
- def each
17
+ def each(&_block)
16
18
  return enum_for __method__ if !block_given?
17
19
 
18
20
  while match = @cursor.next_match
@@ -21,5 +23,17 @@ module TreeSitter
21
23
  end
22
24
  end
23
25
  end
26
+
27
+ # Iterate over all the results presented as hashes of `capture name => node`.
28
+ #
29
+ # @yieldparam match [Hash<String, TreeSitter::Node>]
30
+ def each_capture_hash(&_block)
31
+ # TODO: should we return [Array<Hash<Symbol, TreeSitter::Node]>>] instead?
32
+ return enum_for __method__ if !block_given?
33
+
34
+ each do |match|
35
+ yield match.captures.to_h { |cap| [@query.capture_name_for_id(cap.index), cap.node] }
36
+ end
37
+ end
24
38
  end
25
39
  end
Binary file
@@ -4,5 +4,5 @@ module TreeSitter
4
4
  # The version of the tree-sitter library.
5
5
  TREESITTER_VERSION = '0.22.6'
6
6
  # The current version of the gem.
7
- VERSION = '1.3.0'
7
+ VERSION = '1.4.1'
8
8
  end
data/lib/tree_sitter.rb CHANGED
@@ -1,14 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # TreeSitter is a Ruby interface to the tree-sitter parsing library.
4
- module TreeSitter
5
- end
6
-
7
3
  require 'set'
8
4
 
9
5
  require 'tree_sitter/tree_sitter'
10
6
  require 'tree_sitter/version'
11
7
 
8
+ require 'tree_sitter/mixins/language'
9
+
12
10
  require 'tree_sitter/node'
13
11
  require 'tree_sitter/query'
14
12
  require 'tree_sitter/query_captures'
@@ -18,4 +16,13 @@ require 'tree_sitter/query_matches'
18
16
  require 'tree_sitter/query_predicate'
19
17
  require 'tree_sitter/text_predicate_capture'
20
18
 
19
+ # TreeSitter is a Ruby interface to the tree-sitter parsing library.
20
+ module TreeSitter
21
+ extend Mixins::Language
22
+
23
+ class << self
24
+ alias_method :lang, :language
25
+ end
26
+ end
27
+
21
28
  ObjectSpace.define_finalizer(TreeSitter::Tree.class, proc { TreeSitter::Tree.finalizer })
@@ -97,19 +97,11 @@ module TreeStand
97
97
  sig { params(query_string: String).returns(T::Array[T::Hash[String, TreeStand::Node]]) }
98
98
  def query(query_string)
99
99
  ts_query = TreeSitter::Query.new(@tree.parser.ts_language, query_string)
100
- ts_cursor = TreeSitter::QueryCursor.exec(ts_query, ts_node)
101
- matches = []
102
- while ts_match = ts_cursor.next_match
103
- captures = {}
104
-
105
- ts_match.captures.each do |ts_capture|
106
- capture_name = ts_query.capture_name_for_id(ts_capture.index)
107
- captures[capture_name] = TreeStand::Node.new(@tree, ts_capture.node)
108
- end
109
-
110
- matches << captures
111
- end
112
- matches
100
+ TreeSitter::QueryCursor
101
+ .new
102
+ .matches(ts_query, @tree.ts_tree.root_node, @tree.document)
103
+ .each_capture_hash
104
+ .map { |h| h.transform_values! { |n| TreeStand::Node.new(@tree, n) } }
113
105
  end
114
106
 
115
107
  # Returns the first captured node that matches the query string or nil if
@@ -26,6 +26,7 @@ module TreeStand
26
26
  # @see LIBDIRS
27
27
  class Parser
28
28
  extend T::Sig
29
+ extend TreeSitter::Mixins::Language
29
30
 
30
31
  sig { returns(TreeSitter::Language) }
31
32
  attr_reader :ts_language
@@ -33,156 +34,6 @@ module TreeStand
33
34
  sig { returns(TreeSitter::Parser) }
34
35
  attr_reader :ts_parser
35
36
 
36
- # A colon-seprated list of paths pointing to directories that can contain parsers.
37
- # Order matters.
38
- # Takes precedence over default lookup paths.
39
- ENV_PARSERS =
40
- ENV['TREE_SITTER_PARSERS']
41
- &.split(':')
42
- &.map { |v| Pathname(v) }
43
- .freeze
44
-
45
- # The default paths we use to lookup parsers when no specific
46
- # {TreeStand::Config#parser_path} is `nil`.
47
- # Order matters.
48
- LIBDIRS = [
49
- 'tree-sitter-parsers',
50
- '/opt/local/lib',
51
- '/opt/lib',
52
- '/usr/local/lib',
53
- '/usr/lib',
54
- ].map { |p| Pathname(p) }.freeze
55
-
56
- # The library directories we need to look into.
57
- #
58
- # @return [Array<Pathname>] the list of candidate places to use when searching for parsers.
59
- #
60
- # @see ENV_PARSERS
61
- # @see LIBDIRS
62
- sig { returns(T::Array[Pathname]) }
63
- def self.lib_dirs = [
64
- *ENV_PARSERS,
65
- *(TreeStand.config.parser_path ? [TreeStand.config.parser_path] : LIBDIRS),
66
- ].compact
67
-
68
- # The platform-specific extension of the parser.
69
- # @return [String] `dylib` or `so` for mac or linux.
70
- sig { returns(String) }
71
- def self.ext
72
- case Gem::Platform.local.os
73
- in /darwin/ then 'dylib'
74
- else 'so'
75
- end
76
- end
77
-
78
- # Lookup a parser by name.
79
- #
80
- # Precedence:
81
- # 1. `Env['TREE_SITTER_PARSERS]`
82
- # 2. {TreeStand::Config#parser_path}
83
- # 3. {LIBDIRS}
84
- #
85
- # If a {TreeStand::Config#parser_path} is `nil`, {LIBDIRS} is used.
86
- # If a {TreeStand::Config#parser_path} is a {::Pathname}, {LIBDIRS} is ignored.
87
- sig { params(name: String).returns(T.nilable(Pathname)) }
88
- def self.search_for_lib(name)
89
- files = [
90
- name,
91
- "tree-sitter-#{name}",
92
- "libtree-sitter-#{name}",
93
- ].map { |v| "#{v}.#{ext}" }
94
-
95
- res = lib_dirs
96
- .product(files)
97
- .find do |dir, so|
98
- path = dir / so
99
- path = dir / name / so if !path.exist?
100
- break path.expand_path if path.exist?
101
- end
102
- res.is_a?(Array) ? nil : res
103
- end
104
-
105
- # Generates a string message on where parser lookup happens.
106
- #
107
- # @return [String] A pretty message.
108
- sig { returns(String) }
109
- def self.search_lib_message
110
- indent = 2
111
- pretty = ->(arr) {
112
- if arr
113
- arr
114
- .compact
115
- .map { |v| "#{' ' * indent}#{v.expand_path}" }
116
- .join("\n")
117
- end
118
- }
119
- <<~MSG
120
- From ENV['TREE_SITTER_PARSERS']:
121
- #{pretty.call(ENV_PARSERS)}
122
-
123
- From TreeStand.config.parser_path:
124
- #{pretty.call([TreeStand.config.parser_path])}
125
-
126
- From Defaults:
127
- #{pretty.call(LIBDIRS)}
128
- MSG
129
- end
130
-
131
- # Load a language from configuration or default lookup paths.
132
- #
133
- # @example Load java from default paths
134
- # # This will look for:
135
- # #
136
- # # tree-sitter-parsers/(java/)?(libtree-sitter-)?java.{ext}
137
- # # /opt/local/lib/(java/)?(libtree-sitter-)?java.{ext}
138
- # # /opt/lib/(java/)?(libtree-sitter-)?java.{ext}
139
- # # /usr/local/lib/(java/)?(libtree-sitter-)?java.{ext}
140
- # # /usr/lib/(java/)?(libtree-sitter-)?java.{ext}
141
- # #
142
- # java = TreeStand::Parser.language('java')
143
- #
144
- # @example Load java from a configured path
145
- # # This will look for:
146
- # #
147
- # # /my/path/(java/)?(libtree-sitter-)?java.{ext}
148
- # #
149
- # TreeStand.config.parser_path = '/my/path'
150
- # java = TreeStand::Parser.language('java')
151
- #
152
- # @example Load java from environment variables
153
- # # This will look for:
154
- # #
155
- # # /my/forced/env/path/(java/)?(libtree-sitter-)?java.{ext}
156
- # # /my/path/(java/)?(libtree-sitter-)?java.{ext}
157
- # #
158
- # # … and the same works for the default paths if `TreeStand.config.parser_path`
159
- # # was `nil`
160
- # ENV['TREE_SITTER_PARSERS'] = '/my/forced/env/path'
161
- # TreeStand.config.parser_path = '/my/path'
162
- # java = TreeStand::Parser.language('java')
163
- #
164
- # @param name [String] the name of the parser.
165
- # This name is used to load the symbol from the compiled parser, replacing `-` with `_`.
166
- # @return [TreeSitter:language] a language object to use in your parsers.
167
- # @raise [RuntimeError] if the parser was not found.
168
- # @see search_for_lib
169
- sig { params(name: String).returns(TreeSitter::Language) }
170
- def self.language(name)
171
- lib = search_for_lib(name)
172
-
173
- if lib.nil?
174
- raise <<~MSG
175
- Failed to load a parser for #{name}.
176
-
177
- #{search_lib_message}
178
- MSG
179
- end
180
-
181
- # We know that the bindings will accept `lib`, but I don't know how to tell sorbet
182
- # the types in ext/tree_sitter where `load` is defined.
183
- TreeSitter::Language.load(name.tr('-', '_'), T.unsafe(lib))
184
- end
185
-
186
37
  # @param language [String]
187
38
  sig { params(language: String).void }
188
39
  def initialize(language)
@@ -192,6 +43,19 @@ module TreeStand
192
43
  end
193
44
  end
194
45
 
46
+ # The library directories we need to look into.
47
+ #
48
+ # @return [Array<Pathname>] the list of candidate places to use when searching for parsers.
49
+ #
50
+ # @see ENV_PARSERS
51
+ # @see LIBDIRS
52
+ def self.lib_dirs
53
+ [
54
+ *TreeSitter::ENV_PARSERS,
55
+ *(TreeStand.config.parser_path ? [TreeStand.config.parser_path] : TreeSitter::LIBDIRS),
56
+ ]
57
+ end
58
+
195
59
  # Parse the provided document with the TreeSitter parser.
196
60
  # @param tree [TreeStand::Tree, nil] providing the old tree will allow the
197
61
  # parser to take advantage of incremental parsing and improve performance
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_tree_sitter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.1
5
5
  platform: x86_64-linux
6
6
  authors:
7
7
  - Firas al-Khalil
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-06-26 00:00:00.000000000 Z
12
+ date: 2024-07-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sorbet-runtime
@@ -75,6 +75,7 @@ files:
75
75
  - ext/tree_sitter/tree_sitter.h
76
76
  - lib/tree_sitter.rb
77
77
  - lib/tree_sitter/helpers.rb
78
+ - lib/tree_sitter/mixins/language.rb
78
79
  - lib/tree_sitter/node.rb
79
80
  - lib/tree_sitter/query.rb
80
81
  - lib/tree_sitter/query_captures.rb
@@ -115,17 +116,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
115
116
  requirements:
116
117
  - - ">="
117
118
  - !ruby/object:Gem::Version
118
- version: '3.2'
119
+ version: '3.3'
119
120
  - - "<"
120
121
  - !ruby/object:Gem::Version
121
- version: 3.3.dev
122
+ version: 3.4.dev
122
123
  required_rubygems_version: !ruby/object:Gem::Requirement
123
124
  requirements:
124
125
  - - ">="
125
126
  - !ruby/object:Gem::Version
126
127
  version: '0'
127
128
  requirements: []
128
- rubygems_version: 3.4.19
129
+ rubygems_version: 3.5.11
129
130
  signing_key:
130
131
  specification_version: 4
131
132
  summary: Ruby bindings for Tree-Sitter