syntax_tree 3.2.0 → 3.4.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: a048616da9a9591130add971fae818025454369630a12bd4bb6386b3734de556
4
- data.tar.gz: 16ea5138a4097551063ef9eeb6be7413c1f69e41c49f2b7e8a20e3dd4ab7f0a1
3
+ metadata.gz: 52707e3169fedfce017259222e4740b2e1032d210dfb628d454134eef578a7b6
4
+ data.tar.gz: aed3d5b3e6de7ed1e156c5b104007db6a01dab65e0ee80913afa2c1b5c63a5c0
5
5
  SHA512:
6
- metadata.gz: 680d5745acbcdcfeb9cbb92fb99927b142e9c5f4f7df65f909dc812baca22d14ede3beae973f3db05d6a81953af9f8c53113fe5ccdf86ae2592932079d82cc59
7
- data.tar.gz: f6ac53a377cfd0150d6480611b9cc63714d3e893ef453d2b0881f4e54a8ba5e1450b5f88a38e9e7c7ed3e8eb18f45e6006fff2c5c714fd40db01cb99a615bc15
6
+ metadata.gz: b81b4753a5e765712bd31081dedca6e50c67d04a7935a717fc56d278424154e6ed95b648ac1cbdd59b500ee44c2d8d89f57f52e3851f9615e378d8c9c2c6abe1
7
+ data.tar.gz: 32c95446f19190b8e73d9c3ce83ff4bd5573f5787f844cf695551a2d32c0c159af8c514714c4648a99be4e66189910bde7f01557ea973f6e17aaba66ace7fce2
data/.rubocop.yml CHANGED
@@ -44,7 +44,7 @@ Style/ExplicitBlockArgument:
44
44
  Enabled: false
45
45
 
46
46
  Style/FormatString:
47
- EnforcedStyle: percent
47
+ Enabled: false
48
48
 
49
49
  Style/GuardClause:
50
50
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -6,6 +6,32 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [3.4.0] - 2022-08-19
10
+
11
+ ### Added
12
+
13
+ - [#127](https://github.com/ruby-syntax-tree/syntax_tree/pull/127) - Allow the language server to handle other file extensions if it is activated for those extensions.
14
+ - [#133](https://github.com/ruby-syntax-tree/syntax_tree/pull/133) - Add documentation on supporting vim and neovim.
15
+
16
+ ### Changed
17
+
18
+ - [#132](https://github.com/ruby-syntax-tree/syntax_tree/pull/132) - Provide better error messages when end quotes and end keywords are missing from tokens.
19
+ - [#134](https://github.com/ruby-syntax-tree/syntax_tree/pull/134) - Ensure the correct `end` keyword is getting removed by `begin..rescue` clauses.
20
+ - [#137](https://github.com/ruby-syntax-tree/syntax_tree/pull/137) - Better support regular expressions with no ending token.
21
+
22
+ ## [3.3.0] - 2022-08-02
23
+
24
+ ### Added
25
+
26
+ - [#123](https://github.com/ruby-syntax-tree/syntax_tree/pull/123) - Allow the rake tasks to configure print width.
27
+ - [#125](https://github.com/ruby-syntax-tree/syntax_tree/pull/125) - Add support for an `.streerc` file in the current working directory to configure the CLI.
28
+
29
+ ## [3.2.1] - 2022-07-22
30
+
31
+ ### Changed
32
+
33
+ - [#119](https://github.com/ruby-syntax-tree/syntax_tree/pull/119) - If there are conditionals in the assignment we cannot convert it to the modifier form. There was a bug where it would stop checking for assignment nodes if there were any optional child nodes.
34
+
9
35
  ## [3.2.0] - 2022-07-19
10
36
 
11
37
  ### Added
@@ -306,7 +332,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
306
332
 
307
333
  - 🎉 Initial release! 🎉
308
334
 
309
- [unreleased]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.2.0...HEAD
335
+ [unreleased]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.4.0...HEAD
336
+ [3.4.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.3.0...v3.4.0
337
+ [3.3.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.2.1...v3.3.0
338
+ [3.2.1]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.2.0...v3.2.1
310
339
  [3.2.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.1.0...v3.2.0
311
340
  [3.1.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.0.1...v3.1.0
312
341
  [3.0.1]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.0.0...v3.0.1
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- syntax_tree (3.2.0)
4
+ syntax_tree (3.4.0)
5
5
  prettier_print
6
6
 
7
7
  GEM
@@ -12,24 +12,24 @@ GEM
12
12
  json (2.6.2)
13
13
  minitest (5.16.2)
14
14
  parallel (1.22.1)
15
- parser (3.1.2.0)
15
+ parser (3.1.2.1)
16
16
  ast (~> 2.4.1)
17
17
  prettier_print (0.1.0)
18
18
  rainbow (3.1.1)
19
19
  rake (13.0.6)
20
20
  regexp_parser (2.5.0)
21
21
  rexml (3.2.5)
22
- rubocop (1.31.2)
22
+ rubocop (1.35.0)
23
23
  json (~> 2.3)
24
24
  parallel (~> 1.10)
25
- parser (>= 3.1.0.0)
25
+ parser (>= 3.1.2.1)
26
26
  rainbow (>= 2.2.2, < 4.0)
27
27
  regexp_parser (>= 1.8, < 3.0)
28
28
  rexml (>= 3.2.5, < 4.0)
29
- rubocop-ast (>= 1.18.0, < 2.0)
29
+ rubocop-ast (>= 1.20.1, < 2.0)
30
30
  ruby-progressbar (~> 1.7)
31
31
  unicode-display_width (>= 1.4.0, < 3.0)
32
- rubocop-ast (1.18.0)
32
+ rubocop-ast (1.21.0)
33
33
  parser (>= 3.1.1.0)
34
34
  ruby-progressbar (1.11.0)
35
35
  simplecov (0.21.2)
data/README.md CHANGED
@@ -19,6 +19,8 @@ It is built with only standard library dependencies. It additionally ships with
19
19
  - [json](#json)
20
20
  - [match](#match)
21
21
  - [write](#write)
22
+ - [Configuration](#configuration)
23
+ - [Globbing](#globbing)
22
24
  - [Library](#library)
23
25
  - [SyntaxTree.read(filepath)](#syntaxtreereadfilepath)
24
26
  - [SyntaxTree.parse(source)](#syntaxtreeparsesource)
@@ -43,7 +45,7 @@ It is built with only standard library dependencies. It additionally ships with
43
45
  - [Integration](#integration)
44
46
  - [Rake](#rake)
45
47
  - [RuboCop](#rubocop)
46
- - [VSCode](#vscode)
48
+ - [Editors](#editors)
47
49
  - [Contributing](#contributing)
48
50
  - [License](#license)
49
51
 
@@ -231,6 +233,37 @@ To change the print width that you are writing with, specify the `--print-width`
231
233
  stree write --print-width=100 path/to/file.rb
232
234
  ```
233
235
 
236
+ ### Configuration
237
+
238
+ Any of the above CLI commands can also read configuration options from a `.streerc` file in the directory where the commands are executed.
239
+
240
+ This should be a text file with each argument on a separate line.
241
+
242
+ ```txt
243
+ --print-width=100
244
+ --plugins=plugin/trailing_comma
245
+ ```
246
+
247
+ If this file is present, it will _always_ be used for CLI commands. You can also pass options from the command line as in the examples above. The options in the `.streerc` file are passed to the CLI first, then the arguments from the command line. In the case of exclusive options (e.g. `--print-width`), this means that the command line options override what's in the config file. In the case of options that can take multiple inputs (e.g. `--plugins`), the effect is additive. That is, the plugins passed from the command line will be loaded _in addition to_ the plugins in the config file.
248
+
249
+ ### Globbing
250
+
251
+ When running commands with `stree`, it's common to pass in lists of files. For example:
252
+
253
+ ```sh
254
+ stree write 'lib/*.rb' 'test/*.rb'
255
+ ```
256
+
257
+ The commands in the CLI accept any number of arguments. This means you _could_ pass `**/*.rb` (note the lack of quotes). This would make your shell expand out the file paths listed according to its own rules. (For example, [here](https://www.gnu.org/software/bash/manual/html_node/Filename-Expansion.html) are the rules for GNU bash.)
258
+
259
+ However, it's recommended to instead use quotes, which means that Ruby is responsible for performing the file path expansion instead. This ensures a consistent experience across different environments and shells. The globs must follow the Ruby-specific globbing syntax as specified in the documentation for [Dir](https://ruby-doc.org/core-3.1.1/Dir.html#method-c-glob).
260
+
261
+ Baked into this syntax is the ability to provide exceptions to file name patterns as well. For example, if you are in a Rails app and want to exclude files named `schema.rb` but write all other Ruby files, you can use the following syntax:
262
+
263
+ ```shell
264
+ stree write "**/{[!schema]*,*}.rb"
265
+ ```
266
+
234
267
  ## Library
235
268
 
236
269
  Syntax Tree can be used as a library to access the syntax tree underlying Ruby source code.
@@ -505,6 +538,16 @@ SyntaxTree::Rake::WriteTask.new do |t|
505
538
  end
506
539
  ```
507
540
 
541
+ #### `print_width`
542
+
543
+ If you want to use a different print width from the default (80), you can pass that to the `print_width` field, as in:
544
+
545
+ ```ruby
546
+ SyntaxTree::Rake::WriteTask.new do |t|
547
+ t.print_width = 100
548
+ end
549
+ ```
550
+
508
551
  #### `plugins`
509
552
 
510
553
  If you're running Syntax Tree with plugins (either your own or the pre-built ones), you can pass that to the `plugins` field, as in:
@@ -524,9 +567,11 @@ inherit_gem:
524
567
  syntax_tree: config/rubocop.yml
525
568
  ```
526
569
 
527
- ### VSCode
570
+ ### Editors
528
571
 
529
- To integrate Syntax Tree into VSCode, you should use the official VSCode extension [ruby-syntax-tree/vscode-syntax-tree](https://github.com/ruby-syntax-tree/vscode-syntax-tree).
572
+ * [Neovim](https://neovim.io/) - [neovim/nvim-lspconfig](https://github.com/neovim/nvim-lspconfig).
573
+ * [Vim](https://www.vim.org/) - [dense-analysis/ale](https://github.com/dense-analysis/ale).
574
+ * [VSCode](https://code.visualstudio.com/) - [ruby-syntax-tree/vscode-syntax-tree](https://github.com/ruby-syntax-tree/vscode-syntax-tree).
530
575
 
531
576
  ## Contributing
532
577
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "optparse"
4
+
3
5
  module SyntaxTree
4
6
  # Syntax Tree ships with the `stree` CLI, which can be used to inspect and
5
7
  # manipulate Ruby code. This module is responsible for powering that CLI.
@@ -68,6 +70,12 @@ module SyntaxTree
68
70
 
69
71
  # The parent action class for the CLI that implements the basics.
70
72
  class Action
73
+ attr_reader :options
74
+
75
+ def initialize(options)
76
+ @options = options
77
+ end
78
+
71
79
  def run(item)
72
80
  end
73
81
 
@@ -91,15 +99,9 @@ module SyntaxTree
91
99
  class UnformattedError < StandardError
92
100
  end
93
101
 
94
- attr_reader :print_width
95
-
96
- def initialize(print_width:)
97
- @print_width = print_width
98
- end
99
-
100
102
  def run(item)
101
103
  source = item.source
102
- if source != item.handler.format(source, print_width)
104
+ if source != item.handler.format(source, options.print_width)
103
105
  raise UnformattedError
104
106
  end
105
107
  rescue StandardError
@@ -122,19 +124,13 @@ module SyntaxTree
122
124
  class NonIdempotentFormatError < StandardError
123
125
  end
124
126
 
125
- attr_reader :print_width
126
-
127
- def initialize(print_width:)
128
- @print_width = print_width
129
- end
130
-
131
127
  def run(item)
132
128
  handler = item.handler
133
129
 
134
130
  warning = "[#{Color.yellow("warn")}] #{item.filepath}"
135
- formatted = handler.format(item.source, print_width)
131
+ formatted = handler.format(item.source, options.print_width)
136
132
 
137
- if formatted != handler.format(formatted, print_width)
133
+ if formatted != handler.format(formatted, options.print_width)
138
134
  raise NonIdempotentFormatError
139
135
  end
140
136
  rescue StandardError
@@ -164,14 +160,8 @@ module SyntaxTree
164
160
 
165
161
  # An action of the CLI that formats the input source and prints it out.
166
162
  class Format < Action
167
- attr_reader :print_width
168
-
169
- def initialize(print_width:)
170
- @print_width = print_width
171
- end
172
-
173
163
  def run(item)
174
- puts item.handler.format(item.source, print_width)
164
+ puts item.handler.format(item.source, options.print_width)
175
165
  end
176
166
  end
177
167
 
@@ -195,18 +185,12 @@ module SyntaxTree
195
185
  # An action of the CLI that formats the input source and writes the
196
186
  # formatted output back to the file.
197
187
  class Write < Action
198
- attr_reader :print_width
199
-
200
- def initialize(print_width:)
201
- @print_width = print_width
202
- end
203
-
204
188
  def run(item)
205
189
  filepath = item.filepath
206
190
  start = Time.now
207
191
 
208
192
  source = item.source
209
- formatted = item.handler.format(source, print_width)
193
+ formatted = item.handler.format(source, options.print_width)
210
194
  File.write(filepath, formatted) if filepath != :stdin
211
195
 
212
196
  color = source == formatted ? Color.gray(filepath) : filepath
@@ -262,69 +246,114 @@ module SyntaxTree
262
246
  The maximum line width to use when formatting.
263
247
  HELP
264
248
 
249
+ # This represents all of the options that can be passed to the CLI. It is
250
+ # responsible for parsing the list and then returning the file paths at the
251
+ # end.
252
+ class Options
253
+ attr_reader :print_width
254
+
255
+ def initialize(print_width: DEFAULT_PRINT_WIDTH)
256
+ @print_width = print_width
257
+ end
258
+
259
+ def parse(arguments)
260
+ parser.parse(arguments)
261
+ end
262
+
263
+ private
264
+
265
+ def parser
266
+ OptionParser.new do |opts|
267
+ # If there are any plugins specified on the command line, then load
268
+ # them by requiring them here. We do this by transforming something
269
+ # like
270
+ #
271
+ # stree format --plugins=haml template.haml
272
+ #
273
+ # into
274
+ #
275
+ # require "syntax_tree/haml"
276
+ #
277
+ opts.on("--plugins=PLUGINS") do |plugins|
278
+ plugins.split(",").each { |plugin| require "syntax_tree/#{plugin}" }
279
+ end
280
+
281
+ # If there is a print width specified on the command line, then
282
+ # parse that out here and use it when formatting.
283
+ opts.on("--print-width=NUMBER", Integer) do |print_width|
284
+ @print_width = print_width
285
+ end
286
+ end
287
+ end
288
+ end
289
+
290
+ # We allow a minimal configuration file to act as additional command line
291
+ # arguments to the CLI. Each line of the config file should be a new
292
+ # argument, as in:
293
+ #
294
+ # --plugins=plugin/single_quote
295
+ # --print-width=100
296
+ #
297
+ # When invoking the CLI, we will read this config file and then parse it if
298
+ # it exists in the current working directory.
299
+ class ConfigFile
300
+ FILENAME = ".streerc"
301
+
302
+ attr_reader :filepath
303
+
304
+ def initialize
305
+ @filepath = File.join(Dir.pwd, FILENAME)
306
+ end
307
+
308
+ def exists?
309
+ File.readable?(filepath)
310
+ end
311
+
312
+ def arguments
313
+ exists? ? File.readlines(filepath, chomp: true) : []
314
+ end
315
+ end
316
+
265
317
  class << self
266
318
  # Run the CLI over the given array of strings that make up the arguments
267
319
  # passed to the invocation.
268
320
  def run(argv)
269
321
  name, *arguments = argv
270
- print_width = DEFAULT_PRINT_WIDTH
271
-
272
- while arguments.first&.start_with?("--")
273
- case (argument = arguments.shift)
274
- when /^--plugins=(.+)$/
275
- # If there are any plugins specified on the command line, then load
276
- # them by requiring them here. We do this by transforming something
277
- # like
278
- #
279
- # stree format --plugins=haml template.haml
280
- #
281
- # into
282
- #
283
- # require "syntax_tree/haml"
284
- #
285
- $1.split(",").each { |plugin| require "syntax_tree/#{plugin}" }
286
- when /^--print-width=(\d+)$/
287
- # If there is a print width specified on the command line, then
288
- # parse that out here and use it when formatting.
289
- print_width = Integer($1)
290
- else
291
- warn("Unknown CLI option: #{argument}")
292
- warn(HELP)
293
- return 1
294
- end
295
- end
296
322
 
297
- case name
298
- when "help"
299
- puts HELP
300
- return 0
301
- when "lsp"
302
- require "syntax_tree/language_server"
303
- LanguageServer.new(print_width: print_width).run
304
- return 0
305
- when "version"
306
- puts SyntaxTree::VERSION
307
- return 0
308
- end
323
+ config_file = ConfigFile.new
324
+ arguments.unshift(*config_file.arguments)
325
+
326
+ options = Options.new
327
+ options.parse(arguments)
309
328
 
310
329
  action =
311
330
  case name
312
331
  when "a", "ast"
313
- AST.new
332
+ AST.new(options)
314
333
  when "c", "check"
315
- Check.new(print_width: print_width)
334
+ Check.new(options)
316
335
  when "debug"
317
- Debug.new(print_width: print_width)
336
+ Debug.new(options)
318
337
  when "doc"
319
- Doc.new
338
+ Doc.new(options)
339
+ when "help"
340
+ puts HELP
341
+ return 0
320
342
  when "j", "json"
321
- Json.new
343
+ Json.new(options)
344
+ when "lsp"
345
+ require "syntax_tree/language_server"
346
+ LanguageServer.new(print_width: options.print_width).run
347
+ return 0
322
348
  when "m", "match"
323
- Match.new
349
+ Match.new(options)
324
350
  when "f", "format"
325
- Format.new(print_width: print_width)
351
+ Format.new(options)
352
+ when "version"
353
+ puts SyntaxTree::VERSION
354
+ return 0
326
355
  when "w", "write"
327
- Write.new(print_width: print_width)
356
+ Write.new(options)
328
357
  else
329
358
  warn(HELP)
330
359
  return 1
@@ -56,7 +56,7 @@ module SyntaxTree
56
56
  store.delete(uri)
57
57
  in { method: "textDocument/formatting", id:, params: { textDocument: { uri: } } }
58
58
  contents = store[uri]
59
- write(id: id, result: contents ? [format(store[uri])] : nil)
59
+ write(id: id, result: contents ? [format(store[uri], uri.split(".").last)] : nil)
60
60
  in { method: "textDocument/inlayHint", id:, params: { textDocument: { uri: } } }
61
61
  contents = store[uri]
62
62
  write(id: id, result: contents ? inlay_hints(store[uri]) : nil)
@@ -86,7 +86,9 @@ module SyntaxTree
86
86
  }
87
87
  end
88
88
 
89
- def format(source)
89
+ def format(source, extension)
90
+ text = SyntaxTree::HANDLERS[".#{extension}"].format(source, print_width)
91
+
90
92
  {
91
93
  range: {
92
94
  start: {
@@ -98,7 +100,7 @@ module SyntaxTree
98
100
  character: 0
99
101
  }
100
102
  },
101
- newText: SyntaxTree.format(source, print_width)
103
+ newText: text
102
104
  }
103
105
  end
104
106
 
@@ -117,5 +119,9 @@ module SyntaxTree
117
119
  output.print("Content-Length: #{response.bytesize}\r\n\r\n#{response}")
118
120
  output.flush
119
121
  end
122
+
123
+ def log(message)
124
+ write(method: "window/logMessage", params: { type: 4, message: message })
125
+ end
120
126
  end
121
127
  end
@@ -1978,7 +1978,7 @@ module SyntaxTree
1978
1978
  # If we hit a statements, then we're safe to use whatever since we
1979
1979
  # know for certain we're going to get split over multiple lines
1980
1980
  # anyway.
1981
- break false if parent.is_a?(Statements)
1981
+ break false if parent.is_a?(Statements) || parent.is_a?(ArgParen)
1982
1982
 
1983
1983
  [Command, CommandCall].include?(parent.class)
1984
1984
  end
@@ -5173,7 +5173,7 @@ module SyntaxTree
5173
5173
 
5174
5174
  while (node = queue.shift)
5175
5175
  return true if [Assign, MAssign, OpAssign].include?(node.class)
5176
- queue += node.child_nodes
5176
+ queue += node.child_nodes.compact
5177
5177
  end
5178
5178
 
5179
5179
  false
@@ -57,6 +57,26 @@ module SyntaxTree
57
57
  end
58
58
  end
59
59
 
60
+ # This represents all of the tokens coming back from the lexer. It is
61
+ # replacing a simple array because it keeps track of the last deleted token
62
+ # from the list for better error messages.
63
+ class TokenList < SimpleDelegator
64
+ attr_reader :last_deleted
65
+
66
+ def initialize(object)
67
+ super
68
+ @last_deleted = nil
69
+ end
70
+
71
+ def delete(value)
72
+ @last_deleted = super || @last_deleted
73
+ end
74
+
75
+ def delete_at(index)
76
+ @last_deleted = super
77
+ end
78
+ end
79
+
60
80
  # [String] the source being parsed
61
81
  attr_reader :source
62
82
 
@@ -124,7 +144,7 @@ module SyntaxTree
124
144
  # Most of the time, when a parser event consumes one of these events, it
125
145
  # will be deleted from the list. So ideally, this list stays pretty short
126
146
  # over the course of parsing a source string.
127
- @tokens = []
147
+ @tokens = TokenList.new([])
128
148
 
129
149
  # Here we're going to build up a list of SingleByteString or
130
150
  # MultiByteString objects. They're each going to represent a string in the
@@ -174,6 +194,33 @@ module SyntaxTree
174
194
  line[column].to_i - line.start
175
195
  end
176
196
 
197
+ # Returns the current location that is being looked at for the parser for
198
+ # the purpose of locating the error.
199
+ def find_token_error(location)
200
+ if location
201
+ # If we explicitly passed a location into this find_token_error method,
202
+ # that means that's the source of the error, so we'll use that
203
+ # information for our error object.
204
+ lineno = location.start_line
205
+ [lineno, location.start_char - line_counts[lineno - 1].start]
206
+ elsif lineno && column
207
+ # If there is a line number associated with the current ripper state,
208
+ # then we'll use that information to generate the error.
209
+ [lineno, column]
210
+ elsif (location = tokens.last_deleted&.location)
211
+ # If we've already deleted a token from the list of tokens that we are
212
+ # consuming, then we'll fall back to that token's location.
213
+ lineno = location.start_line
214
+ [lineno, location.start_char - line_counts[lineno - 1].start]
215
+ else
216
+ # Finally, it's possible that when we hit this error the parsing thread
217
+ # for ripper has died. In that case, lineno and column both return nil.
218
+ # So we're just going to set it to line 1, column 0 in the hopes that
219
+ # that makes any sense.
220
+ [1, 0]
221
+ end
222
+ end
223
+
177
224
  # As we build up a list of tokens, we'll periodically need to go backwards
178
225
  # and find the ones that we've already hit in order to determine the
179
226
  # location information for nodes that use them. For example, if you have a
@@ -201,14 +248,7 @@ module SyntaxTree
201
248
  unless index
202
249
  token = value == :any ? type.name.split("::", 2).last : value
203
250
  message = "Cannot find expected #{token}"
204
-
205
- if location
206
- lineno = location.start_line
207
- column = location.start_char - line_counts[lineno - 1].start
208
- raise ParseError.new(message, lineno, column)
209
- else
210
- raise ParseError.new(message, lineno, column)
211
- end
251
+ raise ParseError.new(message, *find_token_error(location))
212
252
  end
213
253
 
214
254
  tokens.delete_at(index)
@@ -677,8 +717,7 @@ module SyntaxTree
677
717
  else
678
718
  keyword = find_token(Kw, "begin")
679
719
  end_location =
680
- if bodystmt.rescue_clause || bodystmt.ensure_clause ||
681
- bodystmt.else_clause
720
+ if bodystmt.else_clause
682
721
  bodystmt.location
683
722
  else
684
723
  find_token(Kw, "end").location
@@ -2798,14 +2837,21 @@ module SyntaxTree
2798
2837
  # :call-seq:
2799
2838
  # on_regexp_literal: (
2800
2839
  # RegexpContent regexp_content,
2801
- # RegexpEnd ending
2840
+ # (nil | RegexpEnd) ending
2802
2841
  # ) -> RegexpLiteral
2803
2842
  def on_regexp_literal(regexp_content, ending)
2843
+ location = regexp_content.location
2844
+
2845
+ if ending.nil?
2846
+ message = "Cannot find expected regular expression ending"
2847
+ raise ParseError.new(message, *find_token_error(location))
2848
+ end
2849
+
2804
2850
  RegexpLiteral.new(
2805
2851
  beginning: regexp_content.beginning,
2806
2852
  ending: ending.value,
2807
2853
  parts: regexp_content.parts,
2808
- location: regexp_content.location.to(ending.location)
2854
+ location: location.to(ending.location)
2809
2855
  )
2810
2856
  end
2811
2857
 
@@ -35,14 +35,20 @@ module SyntaxTree
35
35
  # Defaults to [].
36
36
  attr_accessor :plugins
37
37
 
38
+ # Max line length.
39
+ # Defaults to 80.
40
+ attr_accessor :print_width
41
+
38
42
  def initialize(
39
43
  name = :"stree:check",
40
44
  source_files = ::Rake::FileList["lib/**/*.rb"],
41
- plugins = []
45
+ plugins = [],
46
+ print_width = DEFAULT_PRINT_WIDTH
42
47
  )
43
48
  @name = name
44
49
  @source_files = source_files
45
50
  @plugins = plugins
51
+ @print_width = print_width
46
52
 
47
53
  yield self if block_given?
48
54
  define_task
@@ -58,6 +64,9 @@ module SyntaxTree
58
64
  def run_task
59
65
  arguments = ["check"]
60
66
  arguments << "--plugins=#{plugins.join(",")}" if plugins.any?
67
+ if print_width != DEFAULT_PRINT_WIDTH
68
+ arguments << "--print-width=#{print_width}"
69
+ end
61
70
 
62
71
  SyntaxTree::CLI.run(arguments + Array(source_files))
63
72
  end
@@ -35,14 +35,20 @@ module SyntaxTree
35
35
  # Defaults to [].
36
36
  attr_accessor :plugins
37
37
 
38
+ # Max line length.
39
+ # Defaults to 80.
40
+ attr_accessor :print_width
41
+
38
42
  def initialize(
39
43
  name = :"stree:write",
40
44
  source_files = ::Rake::FileList["lib/**/*.rb"],
41
- plugins = []
45
+ plugins = [],
46
+ print_width = DEFAULT_PRINT_WIDTH
42
47
  )
43
48
  @name = name
44
49
  @source_files = source_files
45
50
  @plugins = plugins
51
+ @print_width = print_width
46
52
 
47
53
  yield self if block_given?
48
54
  define_task
@@ -58,6 +64,9 @@ module SyntaxTree
58
64
  def run_task
59
65
  arguments = ["write"]
60
66
  arguments << "--plugins=#{plugins.join(",")}" if plugins.any?
67
+ if print_width != DEFAULT_PRINT_WIDTH
68
+ arguments << "--print-width=#{print_width}"
69
+ end
61
70
 
62
71
  SyntaxTree::CLI.run(arguments + Array(source_files))
63
72
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SyntaxTree
4
- VERSION = "3.2.0"
4
+ VERSION = "3.4.0"
5
5
  end
data/lib/syntax_tree.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "delegate"
3
4
  require "etc"
4
5
  require "json"
5
6
  require "pp"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: syntax_tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 3.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Newton
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-07-19 00:00:00.000000000 Z
11
+ date: 2022-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: prettier_print