tree_stand 0.1.6 → 0.2.0

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: 7d9ecce5098c654a026b3f08bd8e5dc0a87b696d5e56102f11a40540a7b45d72
4
- data.tar.gz: 41b5bc8b68fb82183e1d641e735fa9083365c5077402193cbf2128c026b1140e
3
+ metadata.gz: 957ff5fd108366dc0b3c0ec05c821a8d207930a4ccf291e1092d26e373a0f4da
4
+ data.tar.gz: fce8cce29e6d558ee447f2afcdf9c83dd276521c0261ec99be93dea8c456b9b1
5
5
  SHA512:
6
- metadata.gz: e1a91dcfa898f9341ed7d8493204cec0ff1170b157e8598226a41858faa96de9f4df45b6e1e449c5c817b3edc7b44efa9bfb7bbfae6a1f4a031580ff0663a0e3
7
- data.tar.gz: 23cc338e725309b833f1b9200101f191772798e3a85d1610c41237522096a7454013fcf6252de8b161c62f7831a263f2ec94603aff4be47739b4a78cc4fdcedc
6
+ metadata.gz: 0f87824f3b009cb8d6993e25cd9b44c2ba645bcf253ef88771b12307a37190a8cb3e405836baea363344763c71cfd3be1bf5c53dd10c69bdfbd66fad1dfdd62d
7
+ data.tar.gz: 25b6b852ff81d122a61d8c74fa94e2e4cde20918ca1b0323b7dbda2e30666d534c8f4acaf736c5298b1de09a6491a819f44badeab3d2ec0a13c56a5e9e46c7ef
data/.gitattributes ADDED
@@ -0,0 +1 @@
1
+ sorbet/rbi/** linguist-generated
@@ -15,15 +15,11 @@ jobs:
15
15
  entry:
16
16
  - { ruby: 3.0 }
17
17
  - { ruby: 3.1 }
18
+ - { ruby: 3.2 }
18
19
  name: test (${{ matrix.entry.ruby }})
19
20
  steps:
20
21
  - uses: actions/checkout@v3
21
22
 
22
- - uses: actions/checkout@v3
23
- with:
24
- repository: DerekStride/tree-sitter-sql
25
- path: tmp/tree-sitter-sql
26
-
27
23
  - uses: ruby/setup-ruby@v1
28
24
  with:
29
25
  ruby-version: ${{ matrix.entry.ruby }}
@@ -33,12 +29,8 @@ jobs:
33
29
  key: ${{ runner.os }}-gems-${{ hashFiles('Gemfile') }}
34
30
  restore-keys: ${{ runner.os }}-gems-
35
31
 
36
- - uses: actions/setup-node@v3
37
- with:
38
- node-version: 16
39
- - run: npm install tree-sitter-cli
40
-
41
- - run: sudo apt-get install -y libtree-sitter-dev make gcc
32
+ - run: sudo apt-get install -y libtree-sitter-dev
42
33
  - run: bundle install --jobs=3 --retry=3 --path=vendor/bundle
43
34
  - run: bin/setup
35
+ - run: bundle exec srb tc
44
36
  - run: bundle exec rake
data/.yardopts ADDED
@@ -0,0 +1,6 @@
1
+ --plugin sorbet
2
+ -
3
+ README.md
4
+ CONTRIBUTING.md
5
+ CODE_OF_CONDUCT.md
6
+ LICENSE.txt
data/CONTRIBUTING.md CHANGED
@@ -19,6 +19,12 @@ bin/setup
19
19
  bundle exec rake test
20
20
  ```
21
21
 
22
+ ### Typechecking
23
+
24
+ ```
25
+ bundle exec srb tc
26
+ ```
27
+
22
28
  ### Documentation
23
29
 
24
30
  To run the documentation server, execute the following command and open [localhost:8808](http://localhost:8808).
data/Gemfile CHANGED
@@ -2,4 +2,16 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'tree_sitter', git: 'https://github.com/Faveod/ruby-tree-sitter'
5
+ group :development, :test do
6
+ gem "bundler", "~> 2.3"
7
+ gem "debug", "~> 1.7", require: false
8
+ gem "rake", "~> 13.0"
9
+ gem 'tapioca', "~> 0.11.1", require: false
10
+ gem "yard", "~> 0.9.28"
11
+ end
12
+
13
+ group :test do
14
+ gem "minitest", "~> 5.17"
15
+ gem "minitest-reporters", "~> 1.5"
16
+ gem "minitest-focus", "~> 1.3"
17
+ end
data/README.md CHANGED
@@ -20,7 +20,7 @@ See the [documentation](https://shopify.github.io/tree_stand) for supported feat
20
20
 
21
21
  ### Setting Up a Parser
22
22
 
23
- TreeStand do not help with compiling individual parsers. However, once you compile a parser and generate a shared
23
+ TreeStand does not help with compiling individual parsers. However, once you compile a parser and generate a shared
24
24
  object (`.so`) or a dynamic library (`.dylib`) you can tell TreeStand where to find them and pass the parser filename
25
25
  to `TreeStand::Parser::new`.
26
26
 
@@ -48,10 +48,12 @@ The underlying objects are accessible via a `ts_` prefixed attribute, e.g. `ts_p
48
48
 
49
49
  Bug reports and pull requests are welcome on GitHub at https://github.com/Shopify/tree_stand. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
50
50
 
51
+ See [CONTRIBUTING.md](https://github.com/Shopify/tree_stand/blob/main/CONTRIBUTING.md) for documentation on how to set up the project for development.
52
+
51
53
  ## License
52
54
 
53
55
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
54
56
 
55
57
  ## Code of Conduct
56
58
 
57
- Everyone interacting in the TreeStand project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/Shopify/tree_stand/blob/master/CODE_OF_CONDUCT.md).
59
+ Everyone interacting in the TreeStand project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/Shopify/tree_stand/blob/main/CODE_OF_CONDUCT.md).
data/bin/console CHANGED
@@ -11,12 +11,12 @@ end
11
11
 
12
12
  ivars_to_add = <<~RUBY
13
13
  @parser = TreeStand::Parser.new("math")
14
- @tree = @parser.parse_string(nil, "1 + x")
14
+ @tree = @parser.parse_string("1 + x")
15
15
  RUBY
16
16
 
17
17
  eval(ivars_to_add)
18
18
  puts("available ivars:")
19
19
  puts(ivars_to_add)
20
20
 
21
- require "pry"
22
- Pry.start
21
+ require "irb"
22
+ IRB.start(__FILE__)
data/bin/setup CHANGED
@@ -13,7 +13,6 @@ fi
13
13
 
14
14
  cd tmp/tree-sitter-math
15
15
 
16
- npm install
17
16
  mkdir -p target
18
17
  gcc -shared -o target/parser.so -fPIC src/parser.c -I./src
19
18
 
data/bin/tapioca ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'tapioca' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("tapioca", "tapioca")
@@ -1,10 +1,15 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
1
4
  module TreeStand
2
- # An experimental class to modify the AST. I re-runs the query on the
5
+ # An experimental class to modify the AST. It re-runs the query on the
3
6
  # modified document every loop to ensure that the match is still valid.
4
7
  # @see TreeStand::Tree
5
8
  # @api experimental
6
9
  class AstModifier
7
- # @param tree [TreeStand::Tree]
10
+ extend T::Sig
11
+
12
+ sig { params(tree: TreeStand::Tree).void }
8
13
  def initialize(tree)
9
14
  @tree = tree
10
15
  end
@@ -1,8 +1,13 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
1
4
  module TreeStand
2
5
  # Global configuration for the gem.
3
6
  # @api private
4
7
  class Config
5
- # @return [String]
8
+ extend T::Sig
9
+
10
+ sig { returns(String) }
6
11
  attr_accessor :parser_path
7
12
  end
8
13
  end
@@ -1,9 +1,13 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
1
4
  module TreeStand
2
5
  # Wrapper around a TreeSitter node and provides convient
3
6
  # methods that are missing on the original node. This class
4
7
  # overrides the `method_missing` method to delegate to a nodes
5
8
  # named children.
6
9
  class Node
10
+ extend T::Sig
7
11
  extend Forwardable
8
12
  include Enumerable
9
13
 
@@ -17,20 +21,13 @@ module TreeStand
17
21
  :error?,
18
22
  )
19
23
 
20
- # @return [TreeStand::Tree]
24
+ sig { returns(TreeStand::Tree) }
21
25
  attr_reader :tree
22
- # @return [TreeSitter::Node]
26
+ sig { returns(TreeSitter::Node) }
23
27
  attr_reader :ts_node
24
28
 
25
- # @!method to_a
26
- # @example
27
- # node.text # => "3 * 4"
28
- # node.to_a.map(&:text) # => ["3", "*", "4"]
29
- # node.children.map(&:text) # => ["3", "*", "4"]
30
- # @return [Array<TreeStand::Node>]
31
- alias_method :children, :to_a
32
-
33
29
  # @api private
30
+ sig { params(tree: TreeStand::Tree, ts_node: TreeSitter::Node).void }
34
31
  def initialize(tree, ts_node)
35
32
  @tree = tree
36
33
  @ts_node = ts_node
@@ -53,9 +50,7 @@ module TreeStand
53
50
  # tree.root_node.query(<<~QUERY)
54
51
  # (identifier) @identifier
55
52
  # QUERY
56
- #
57
- # @param query_string [String]
58
- # @return [Array<Hash<String, TreeStand::Node>>]
53
+ sig { params(query_string: String).returns(T::Array[T::Hash[String, TreeStand::Node]]) }
59
54
  def query(query_string)
60
55
  ts_query = TreeSitter::Query.new(@tree.parser.ts_language, query_string)
61
56
  ts_cursor = TreeSitter::QueryCursor.exec(ts_query, ts_node)
@@ -81,8 +76,7 @@ module TreeStand
81
76
  #
82
77
  # @see #find_node!
83
78
  # @see #query
84
- # @param query_string [String]
85
- # @return [TreeStand::Node, nil]
79
+ sig { params(query_string: String).returns(T.nilable(TreeStand::Node)) }
86
80
  def find_node(query_string)
87
81
  query(query_string).first&.values&.first
88
82
  end
@@ -91,14 +85,13 @@ module TreeStand
91
85
  # {TreeStand::NodeNotFound} error.
92
86
  #
93
87
  # @see #find_node
94
- # @param query_string [String]
95
- # @return [TreeStand::Node]
96
88
  # @raise [TreeStand::NodeNotFound]
89
+ sig { params(query_string: String).returns(TreeStand::Node) }
97
90
  def find_node!(query_string)
98
91
  find_node(query_string) || raise(TreeStand::NodeNotFound)
99
92
  end
100
93
 
101
- # @return [TreeStand::Range]
94
+ sig { returns(TreeStand::Range) }
102
95
  def range
103
96
  TreeStand::Range.new(
104
97
  start_byte: @ts_node.start_byte,
@@ -122,13 +115,19 @@ module TreeStand
122
115
  # node.map(&:text) # => ["3", "*", "4"]
123
116
  #
124
117
  # @yieldparam child [TreeStand::Node]
125
- # @return [Enumerator]
118
+ sig do
119
+ override
120
+ .params(block: T.nilable(T.proc.params(node: TreeStand::Node).returns(BasicObject)))
121
+ .returns(T::Enumerator[TreeStand::Node])
122
+ end
126
123
  def each(&block)
127
- Enumerator.new do |yielder|
124
+ enumerator = Enumerator.new do |yielder|
128
125
  @ts_node.each do |child|
129
126
  yielder << TreeStand::Node.new(@tree, child)
130
127
  end
131
- end.each(&block)
128
+ end
129
+ enumerator.each(&block) if block_given?
130
+ enumerator
132
131
  end
133
132
 
134
133
  # (see TreeStand::Visitors::TreeWalker)
@@ -137,32 +136,44 @@ module TreeStand
137
136
  # @example Check the subtree for error nodes
138
137
  # node.walk.any? { |node| node.type == :error }
139
138
  #
140
- # @yieldparam node [TreeStand::Node]
141
- # @return [Enumerator]
142
- #
143
139
  # @see TreeStand::Visitors::TreeWalker
140
+ #
141
+ # @yieldparam node [TreeStand::Node]
142
+ sig do
143
+ params(block: T.nilable(T.proc.params(node: TreeStand::Node).returns(BasicObject)))
144
+ .returns(T::Enumerator[TreeStand::Node])
145
+ end
144
146
  def walk(&block)
145
- Enumerator.new do |yielder|
147
+ enumerator = Enumerator.new do |yielder|
146
148
  Visitors::TreeWalker.new(self) do |child|
147
149
  yielder << child
148
150
  end.visit
149
- end.each(&block)
151
+ end
152
+ enumerator.each(&block) if block_given?
153
+ enumerator
150
154
  end
151
155
 
152
156
  # @example
153
157
  # node.text # => "4"
154
158
  # node.parent.text # => "3 * 4"
155
159
  # node.parent.parent.text # => "1 + 3 * 4"
156
- # @return [TreeStand::Node]
160
+ sig { returns(TreeStand::Node) }
157
161
  def parent
158
162
  TreeStand::Node.new(@tree, @ts_node.parent)
159
163
  end
160
164
 
161
- # A convience method for getting the text of the node. Each {TreeStand::Node}
165
+ # @example
166
+ # node.text # => "3 * 4"
167
+ # node.to_a.map(&:text) # => ["3", "*", "4"]
168
+ # node.children.map(&:text) # => ["3", "*", "4"]
169
+ sig { returns(T::Array[TreeStand::Node]) }
170
+ def children = to_a
171
+
172
+ # A convenience method for getting the text of the node. Each {TreeStand::Node}
162
173
  # wraps the parent {TreeStand::Tree #tree} and has access to the source document.
163
- # @return [String]
174
+ sig { returns(String) }
164
175
  def text
165
- @tree.document[@ts_node.start_byte...@ts_node.end_byte]
176
+ T.must(@tree.document[@ts_node.start_byte...@ts_node.end_byte])
166
177
  end
167
178
 
168
179
  # This class overrides the `method_missing` method to delegate to the
@@ -183,26 +194,21 @@ module TreeStand
183
194
  # @raise [NoMethodError]
184
195
  def method_missing(method, *args, &block)
185
196
  return super unless @fields.include?(method.to_s)
186
- TreeStand::Node.new(@tree, @ts_node.public_send(method, *args, &block))
197
+ TreeStand::Node.new(@tree, T.unsafe(@ts_node).public_send(method, *args, &block))
187
198
  end
188
199
 
189
- # @param other [Object]
190
- # @return [bool]
200
+ sig { params(other: Object).returns(T::Boolean) }
191
201
  def ==(other)
192
202
  return false unless other.is_a?(TreeStand::Node)
193
203
 
194
- range == other.range &&
195
- type == other.type &&
196
- text == other.text
204
+ T.must(range == other.range && type == other.type && text == other.text)
197
205
  end
198
206
 
199
207
  # (see TreeStand::Utils::Printer)
200
208
  # Backed by {TreeStand::Utils::Printer}.
201
209
  #
202
- # @param pp [PP]
203
- # @return [void]
204
- #
205
210
  # @see TreeStand::Utils::Printer
211
+ sig { params(pp: PP).void }
206
212
  def pretty_print(pp)
207
213
  Utils::Printer.new(ralign: 80).print(self, io: pp.output)
208
214
  end
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
1
4
  module TreeStand
2
5
  # Wrapper around the TreeSitter parser. It looks up the parser by filename in
3
6
  # the configured parsers directory.
@@ -12,12 +15,15 @@ module TreeStand
12
15
  # # Looks for a parser in `path/to/parser/folder/ruby.{so,dylib}`
13
16
  # ruby_parser = TreeStand::Parser.new("ruby")
14
17
  class Parser
15
- # @return [TreeSitter::Language]
18
+ extend T::Sig
19
+
20
+ sig { returns(TreeSitter::Language) }
16
21
  attr_reader :ts_language
17
- # @return [TreeSitter::Parser]
22
+ sig { returns(TreeSitter::Parser) }
18
23
  attr_reader :ts_parser
19
24
 
20
25
  # @param language [String]
26
+ sig { params(language: String).void }
21
27
  def initialize(language)
22
28
  @language_string = language
23
29
  @ts_language = TreeSitter::Language.load(
@@ -33,8 +39,7 @@ module TreeStand
33
39
  # @param tree [TreeStand::Tree, nil] providing the old tree will allow the
34
40
  # parser to take advantage of incremental parsing and improve performance
35
41
  # by re-useing nodes from the old tree.
36
- # @param document [String]
37
- # @return [TreeStand::Tree]
42
+ sig { params(document: String, tree: T.nilable(TreeStand::Tree)).returns(TreeStand::Tree) }
38
43
  def parse_string(document, tree: nil)
39
44
  # @todo There's a bug with passing a non-nil tree
40
45
  ts_tree = @ts_parser.parse_string(nil, document)
@@ -47,6 +52,7 @@ module TreeStand
47
52
  #
48
53
  # @see #parse_string
49
54
  # @raise [TreeStand::InvalidDocument]
55
+ sig { params(document: String, tree: T.nilable(TreeStand::Tree)).returns(TreeStand::Tree) }
50
56
  def parse_string!(document, tree: nil)
51
57
  tree = parse_string(document, tree: tree)
52
58
  return tree unless tree.any?(&:error?)
@@ -1,6 +1,11 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
1
4
  module TreeStand
2
5
  # Wrapper around a TreeSitter range. This is mainly used to compare ranges.
3
6
  class Range
7
+ extend T::Sig
8
+
4
9
  # Point is a Struct containing the row and column from a TreeSitter point.
5
10
  # TreeStand uses this to compare points.
6
11
  # @!attribute [rw] row
@@ -9,16 +14,24 @@ module TreeStand
9
14
  # @return [Integer]
10
15
  Point = Struct.new(:row, :column)
11
16
 
12
- # @return [Integer]
17
+ sig { returns(Integer) }
13
18
  attr_reader :start_byte
14
- # @return [Integer]
19
+ sig { returns(Integer) }
15
20
  attr_reader :end_byte
16
- # @return [TreeStand::Range::Point]
21
+ sig { returns(TreeStand::Range::Point) }
17
22
  attr_reader :start_point
18
- # @return [TreeStand::Range::Point]
23
+ sig { returns(TreeStand::Range::Point) }
19
24
  attr_reader :end_point
20
25
 
21
26
  # @api private
27
+ sig do
28
+ params(
29
+ start_byte: Integer,
30
+ end_byte: Integer,
31
+ start_point: T.any(TreeStand::Range::Point, TreeSitter::Point),
32
+ end_point: T.any(TreeStand::Range::Point, TreeSitter::Point),
33
+ ).void
34
+ end
22
35
  def initialize(start_byte:, end_byte:, start_point:, end_point:)
23
36
  @start_byte = start_byte
24
37
  @end_byte = end_byte
@@ -26,8 +39,7 @@ module TreeStand
26
39
  @end_point = Point.new(end_point.row, end_point.column)
27
40
  end
28
41
 
29
- # @param other [Object]
30
- # @return [bool]
42
+ sig { params(other: Object).returns(T::Boolean) }
31
43
  def ==(other)
32
44
  return false unless other.is_a?(TreeStand::Range)
33
45
 
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
1
4
  module TreeStand
2
5
  # Wrapper around a TreeSitter tree.
3
6
  #
@@ -22,25 +25,29 @@ module TreeStand
22
25
  # This is not always possible and depends on the edits you make, beware that
23
26
  # the tree will be different after each edit and this approach may cause bugs.
24
27
  class Tree
28
+ extend T::Sig
25
29
  extend Forwardable
26
30
  include Enumerable
27
31
 
28
- # @return [String]
32
+ sig { returns(String) }
29
33
  attr_reader :document
30
- # @return [TreeSitter::Tree]
34
+ sig { returns(TreeSitter::Tree) }
31
35
  attr_reader :ts_tree
32
- # @return [TreeStand::Parser]
36
+ sig { returns(TreeStand::Parser) }
33
37
  attr_reader :parser
34
38
 
35
39
  # @!method query(query_string)
40
+ # (see TreeStand::Node#query)
36
41
  # @note This is a convenience method that calls {TreeStand::Node#query} on
37
42
  # {#root_node}.
38
43
  #
39
44
  # @!method find_node(query_string)
45
+ # (see TreeStand::Node#find_node)
40
46
  # @note This is a convenience method that calls {TreeStand::Node#find_node} on
41
47
  # {#root_node}.
42
48
  #
43
49
  # @!method find_node!(query_string)
50
+ # (see TreeStand::Node#find_node!)
44
51
  # @note This is a convenience method that calls {TreeStand::Node#find_node!} on
45
52
  # {#root_node}.
46
53
  #
@@ -69,13 +76,14 @@ module TreeStand
69
76
  alias_method :each, :walk
70
77
 
71
78
  # @api private
79
+ sig { params(parser: TreeStand::Parser, tree: TreeSitter::Tree, document: String).void }
72
80
  def initialize(parser, tree, document)
73
81
  @parser = parser
74
82
  @ts_tree = tree
75
83
  @document = document
76
84
  end
77
85
 
78
- # @return [TreeStand::Node]
86
+ sig { returns(TreeStand::Node) }
79
87
  def root_node
80
88
  TreeStand::Node.new(self, @ts_tree.root_node)
81
89
  end
@@ -83,9 +91,7 @@ module TreeStand
83
91
  # This method replaces the section of the document specified by range and
84
92
  # replaces it with the provided text. Then it will reparse the document and
85
93
  # update the tree!
86
- # @param range [TreeStand::Range]
87
- # @param replacement [String]
88
- # @return [void]
94
+ sig { params(range: TreeStand::Range, replacement: String).void }
89
95
  def edit!(range, replacement)
90
96
  new_document = +""
91
97
  new_document << @document[0...range.start_byte]
@@ -96,8 +102,7 @@ module TreeStand
96
102
 
97
103
  # This method deletes the section of the document specified by range. Then
98
104
  # it will reparse the document and update the tree!
99
- # @param range [TreeStand::Range]
100
- # @return [void]
105
+ sig { params(range: TreeStand::Range).void }
101
106
  def delete!(range)
102
107
  new_document = +""
103
108
  new_document << @document[0...range.start_byte]
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
1
4
  module TreeStand
2
5
  # A collection of useful methods for working with syntax trees.
3
6
  module Utils
@@ -11,26 +14,26 @@ module TreeStand
11
14
  # # ("+") | +
12
15
  # # right: (variable))) | x
13
16
  class Printer
14
- # @param ralign [Integer] the right alignment for the text column.
17
+ extend T::Sig
18
+
19
+ # @param ralign the right alignment for the text column.
20
+ sig { params(ralign: Integer).void }
15
21
  def initialize(ralign:)
16
22
  @ralign = ralign
17
23
  end
18
24
 
19
25
  # (see TreeStand::Utils::Printer)
20
- #
21
- # @param node [TreeStand::Node]
22
- # @param io [IO]
23
- # @return [IO]
26
+ sig { params(node: TreeStand::Node, io: T.any(IO, StringIO, String)).returns(T.any(IO, StringIO, String)) }
24
27
  def print(node, io: StringIO.new)
25
28
  lines = pretty_output_lines(node)
26
29
 
27
30
  lines.each do |line|
28
31
  if line.text.empty?
29
- io.puts line.sexpr
32
+ io << line.sexpr << "\n"
30
33
  next
31
34
  end
32
35
 
33
- io.puts "#{line.sexpr}#{" " * (@ralign - line.sexpr.size)}| #{line.text}"
36
+ io << "#{line.sexpr}#{" " * (@ralign - line.sexpr.size)}| #{line.text}\n"
34
37
  end
35
38
 
36
39
  io
@@ -48,7 +51,7 @@ module TreeStand
48
51
  return [Line.new("#{indent}#{prefix}#{ts_node}", node.text)]
49
52
  end
50
53
 
51
- lines = [Line.new("#{indent}#{prefix}(#{ts_node.type}", "")]
54
+ lines = T.let([Line.new("#{indent}#{prefix}(#{ts_node.type}", "")], T::Array[Line])
52
55
 
53
56
  node.each.with_index do |child, index|
54
57
  lines += if field_name = ts_node.field_name_for_child(index)
@@ -62,7 +65,7 @@ module TreeStand
62
65
  end
63
66
  end
64
67
 
65
- lines.last.sexpr << ")"
68
+ T.must(lines.last).sexpr << ")"
66
69
  lines
67
70
  end
68
71
  end
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+ # typed: strong
3
+
1
4
  module TreeStand
2
5
  # The current version of the gem.
3
- VERSION = "0.1.6"
6
+ VERSION = "0.2.0"
4
7
  end