syntax_tree 3.3.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: 92ff69f19d5433566404bce6888eae08a442861821612c986489db05679ecd22
4
- data.tar.gz: e05511cf866fa1e0cfde540f0a0bc84a88414b128583a37a68c73658ff667b16
3
+ metadata.gz: 52707e3169fedfce017259222e4740b2e1032d210dfb628d454134eef578a7b6
4
+ data.tar.gz: aed3d5b3e6de7ed1e156c5b104007db6a01dab65e0ee80913afa2c1b5c63a5c0
5
5
  SHA512:
6
- metadata.gz: 3d98f8b9a997ef9278ad2ea9c1600ee5abc52c646d157b0180f6cf6956ebde2ccc6d9ea917436231645a7d4bf58ce1627fbae393b89e81b683157bc5263d65e0
7
- data.tar.gz: 924ccb54dec3055dca88aef5efe839d2c979abedfdf96f5e0996e18390b3e246b676cdb1c8aba6d51edfed42219bff3c80b4bfcead0eb3f6b926e585c96f0a1b
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,19 @@ 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
+
9
22
  ## [3.3.0] - 2022-08-02
10
23
 
11
24
  ### Added
@@ -319,7 +332,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
319
332
 
320
333
  - 🎉 Initial release! 🎉
321
334
 
322
- [unreleased]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.3.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
323
337
  [3.3.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.2.1...v3.3.0
324
338
  [3.2.1]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.2.0...v3.2.1
325
339
  [3.2.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.1.0...v3.2.0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- syntax_tree (3.3.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.32.0)
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.19.1, < 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.19.1)
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
@@ -20,6 +20,7 @@ It is built with only standard library dependencies. It additionally ships with
20
20
  - [match](#match)
21
21
  - [write](#write)
22
22
  - [Configuration](#configuration)
23
+ - [Globbing](#globbing)
23
24
  - [Library](#library)
24
25
  - [SyntaxTree.read(filepath)](#syntaxtreereadfilepath)
25
26
  - [SyntaxTree.parse(source)](#syntaxtreeparsesource)
@@ -44,7 +45,7 @@ It is built with only standard library dependencies. It additionally ships with
44
45
  - [Integration](#integration)
45
46
  - [Rake](#rake)
46
47
  - [RuboCop](#rubocop)
47
- - [VSCode](#vscode)
48
+ - [Editors](#editors)
48
49
  - [Contributing](#contributing)
49
50
  - [License](#license)
50
51
 
@@ -245,6 +246,24 @@ This should be a text file with each argument on a separate line.
245
246
 
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.
247
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
+
248
267
  ## Library
249
268
 
250
269
  Syntax Tree can be used as a library to access the syntax tree underlying Ruby source code.
@@ -548,9 +567,11 @@ inherit_gem:
548
567
  syntax_tree: config/rubocop.yml
549
568
  ```
550
569
 
551
- ### VSCode
570
+ ### Editors
552
571
 
553
- 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).
554
575
 
555
576
  ## Contributing
556
577
 
@@ -1,11 +1,11 @@
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.
6
8
  module CLI
7
- CONFIG_FILE = ".streerc"
8
-
9
9
  # A utility wrapper around colored strings in the output.
10
10
  class Color
11
11
  attr_reader :value, :code
@@ -70,6 +70,12 @@ module SyntaxTree
70
70
 
71
71
  # The parent action class for the CLI that implements the basics.
72
72
  class Action
73
+ attr_reader :options
74
+
75
+ def initialize(options)
76
+ @options = options
77
+ end
78
+
73
79
  def run(item)
74
80
  end
75
81
 
@@ -93,15 +99,9 @@ module SyntaxTree
93
99
  class UnformattedError < StandardError
94
100
  end
95
101
 
96
- attr_reader :print_width
97
-
98
- def initialize(print_width:)
99
- @print_width = print_width
100
- end
101
-
102
102
  def run(item)
103
103
  source = item.source
104
- if source != item.handler.format(source, print_width)
104
+ if source != item.handler.format(source, options.print_width)
105
105
  raise UnformattedError
106
106
  end
107
107
  rescue StandardError
@@ -124,19 +124,13 @@ module SyntaxTree
124
124
  class NonIdempotentFormatError < StandardError
125
125
  end
126
126
 
127
- attr_reader :print_width
128
-
129
- def initialize(print_width:)
130
- @print_width = print_width
131
- end
132
-
133
127
  def run(item)
134
128
  handler = item.handler
135
129
 
136
130
  warning = "[#{Color.yellow("warn")}] #{item.filepath}"
137
- formatted = handler.format(item.source, print_width)
131
+ formatted = handler.format(item.source, options.print_width)
138
132
 
139
- if formatted != handler.format(formatted, print_width)
133
+ if formatted != handler.format(formatted, options.print_width)
140
134
  raise NonIdempotentFormatError
141
135
  end
142
136
  rescue StandardError
@@ -166,14 +160,8 @@ module SyntaxTree
166
160
 
167
161
  # An action of the CLI that formats the input source and prints it out.
168
162
  class Format < Action
169
- attr_reader :print_width
170
-
171
- def initialize(print_width:)
172
- @print_width = print_width
173
- end
174
-
175
163
  def run(item)
176
- puts item.handler.format(item.source, print_width)
164
+ puts item.handler.format(item.source, options.print_width)
177
165
  end
178
166
  end
179
167
 
@@ -197,18 +185,12 @@ module SyntaxTree
197
185
  # An action of the CLI that formats the input source and writes the
198
186
  # formatted output back to the file.
199
187
  class Write < Action
200
- attr_reader :print_width
201
-
202
- def initialize(print_width:)
203
- @print_width = print_width
204
- end
205
-
206
188
  def run(item)
207
189
  filepath = item.filepath
208
190
  start = Time.now
209
191
 
210
192
  source = item.source
211
- formatted = item.handler.format(source, print_width)
193
+ formatted = item.handler.format(source, options.print_width)
212
194
  File.write(filepath, formatted) if filepath != :stdin
213
195
 
214
196
  color = source == formatted ? Color.gray(filepath) : filepath
@@ -264,74 +246,114 @@ module SyntaxTree
264
246
  The maximum line width to use when formatting.
265
247
  HELP
266
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
+
267
317
  class << self
268
318
  # Run the CLI over the given array of strings that make up the arguments
269
319
  # passed to the invocation.
270
320
  def run(argv)
271
321
  name, *arguments = argv
272
- print_width = DEFAULT_PRINT_WIDTH
273
-
274
- config_file = File.join(Dir.pwd, CONFIG_FILE)
275
- if File.readable?(config_file)
276
- arguments.unshift(*File.readlines(config_file, chomp: true))
277
- end
278
322
 
279
- while arguments.first&.start_with?("--")
280
- case (argument = arguments.shift)
281
- when /^--plugins=(.+)$/
282
- # If there are any plugins specified on the command line, then load
283
- # them by requiring them here. We do this by transforming something
284
- # like
285
- #
286
- # stree format --plugins=haml template.haml
287
- #
288
- # into
289
- #
290
- # require "syntax_tree/haml"
291
- #
292
- $1.split(",").each { |plugin| require "syntax_tree/#{plugin}" }
293
- when /^--print-width=(\d+)$/
294
- # If there is a print width specified on the command line, then
295
- # parse that out here and use it when formatting.
296
- print_width = Integer($1)
297
- else
298
- warn("Unknown CLI option: #{argument}")
299
- warn(HELP)
300
- return 1
301
- end
302
- end
323
+ config_file = ConfigFile.new
324
+ arguments.unshift(*config_file.arguments)
303
325
 
304
- case name
305
- when "help"
306
- puts HELP
307
- return 0
308
- when "lsp"
309
- require "syntax_tree/language_server"
310
- LanguageServer.new(print_width: print_width).run
311
- return 0
312
- when "version"
313
- puts SyntaxTree::VERSION
314
- return 0
315
- end
326
+ options = Options.new
327
+ options.parse(arguments)
316
328
 
317
329
  action =
318
330
  case name
319
331
  when "a", "ast"
320
- AST.new
332
+ AST.new(options)
321
333
  when "c", "check"
322
- Check.new(print_width: print_width)
334
+ Check.new(options)
323
335
  when "debug"
324
- Debug.new(print_width: print_width)
336
+ Debug.new(options)
325
337
  when "doc"
326
- Doc.new
338
+ Doc.new(options)
339
+ when "help"
340
+ puts HELP
341
+ return 0
327
342
  when "j", "json"
328
- 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
329
348
  when "m", "match"
330
- Match.new
349
+ Match.new(options)
331
350
  when "f", "format"
332
- Format.new(print_width: print_width)
351
+ Format.new(options)
352
+ when "version"
353
+ puts SyntaxTree::VERSION
354
+ return 0
333
355
  when "w", "write"
334
- Write.new(print_width: print_width)
356
+ Write.new(options)
335
357
  else
336
358
  warn(HELP)
337
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
@@ -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
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SyntaxTree
4
- VERSION = "3.3.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.3.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-08-02 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