syntax_tree 2.4.1 → 2.7.0

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: e69df6c9df69726ed7040c1b47584e8f17d9f3cc45a7a72de308aa9db39b4b66
4
- data.tar.gz: 9dddf054616a7ca765dc7ebb7bbe98dbdaee8114a34043dd66390d9a6d576ea2
3
+ metadata.gz: 126d8e2e86fc77aeab82d0130da3ed5d20b85ecbfb6cfd84ea4056f48c9c5cb9
4
+ data.tar.gz: c7abdbc2427c75561ae5e08b55345ecce65c4ff4cf6c5b6c02151734f9e54f5c
5
5
  SHA512:
6
- metadata.gz: cf759fc42716b42988156d84333ebe66baa87ad881b85e062e0942d285c8be25f074a894b329c6a69758c68655667c1972291f68339141592f4e01ce089a9a6c
7
- data.tar.gz: e5b5e3a6645fa340959458be14670784cba49f0d6436a518429ef8926581dea2169b03400f14916c8c9bbb66388d1116b8cdedac811e371a1ea37368bd5f3b42
6
+ metadata.gz: 0b06e13f4f4ff47b250a5423e3e47de324c77ca4cd965539a040edc0b02b4aa9e78367cd5a8a5fad504f80dea82029798e8001d82eddf042e745b6080041a389
7
+ data.tar.gz: '0910deb51a5d6a458530923f5014b02030092b957f056e6339ef252ab6cb951014f738e2443d44d28e836dbb399567f934ac21b1b26e8ea75ddb8782475f4647'
@@ -38,7 +38,7 @@ jobs:
38
38
  ruby-version: '3.1'
39
39
  - name: Check
40
40
  run: |
41
- bundle exec rake check
41
+ bundle exec rake stree:check
42
42
  bundle exec rubocop
43
43
 
44
44
  automerge:
data/CHANGELOG.md CHANGED
@@ -6,6 +6,39 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.7.0] - 2022-05-19
10
+
11
+ ### Added
12
+
13
+ - [#88](https://github.com/ruby-syntax-tree/syntax_tree/pull/88) - Provide a `SyntaxTree::BasicVisitor` that has no visit methods implemented.
14
+
15
+ ### Changed
16
+
17
+ - [#90](https://github.com/ruby-syntax-tree/syntax_tree/pull/90) - Provide better formatting for `SyntaxTree::AryPtn` when its nested inside a `SyntaxTree::RAssign`.
18
+
19
+ ## [2.6.0] - 2022-05-16
20
+
21
+ ### Added
22
+
23
+ - [#74](https://github.com/ruby-syntax-tree/syntax_tree/pull/74) - Add Rake test to run check and format commands.
24
+ - [#83](https://github.com/ruby-syntax-tree/syntax_tree/pull/83) - Add a trailing commas plugin.
25
+ - [#84](https://github.com/ruby-syntax-tree/syntax_tree/pull/84) - Handle lambda block-local variables.
26
+
27
+ ### Changed
28
+
29
+ - [#85](https://github.com/ruby-syntax-tree/syntax_tree/pull/85) - Better handle trailing operators on command calls.
30
+
31
+ ## [2.5.0] - 2022-05-13
32
+
33
+ ### Added
34
+
35
+ - [#79](https://github.com/ruby-syntax-tree/syntax_tree/pull/79) - Support an optional `maxwidth` second argument to `SyntaxTree.format`.
36
+
37
+ ### Changed
38
+
39
+ - [#77](https://github.com/ruby-syntax-tree/syntax_tree/pull/77) - Correct the pattern for checking if a dynamic symbol can be converted into a label as a hash key.
40
+ - [#72](https://github.com/ruby-syntax-tree/syntax_tree/pull/72) - Disallow conditionals with `not` without parentheses in the predicate from turning into a ternary.
41
+
9
42
  ## [2.4.1] - 2022-05-10
10
43
 
11
44
  - [#73](https://github.com/ruby-syntax-tree/syntax_tree/pull/73) - Fix nested hash patterns from accidentally adding a `then` to their output.
@@ -213,7 +246,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
213
246
 
214
247
  - 🎉 Initial release! 🎉
215
248
 
216
- [unreleased]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.4.1...HEAD
249
+ [unreleased]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.7.0...HEAD
250
+ [2.7.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.6.0...v2.7.0
251
+ [2.6.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.5.0...v2.6.0
252
+ [2.5.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.4.1...v2.5.0
217
253
  [2.4.1]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.4.0...v2.4.1
218
254
  [2.4.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.3.1...v2.4.0
219
255
  [2.3.1]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.3.0...v2.3.1
data/Gemfile CHANGED
@@ -3,5 +3,3 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gemspec
6
-
7
- gem "rubocop"
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- syntax_tree (2.4.1)
4
+ syntax_tree (2.7.0)
5
+ prettier_print
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
@@ -12,11 +13,12 @@ GEM
12
13
  parallel (1.22.1)
13
14
  parser (3.1.2.0)
14
15
  ast (~> 2.4.1)
16
+ prettier_print (0.1.0)
15
17
  rainbow (3.1.1)
16
18
  rake (13.0.6)
17
- regexp_parser (2.3.1)
19
+ regexp_parser (2.4.0)
18
20
  rexml (3.2.5)
19
- rubocop (1.29.0)
21
+ rubocop (1.29.1)
20
22
  parallel (~> 1.10)
21
23
  parser (>= 3.1.0.0)
22
24
  rainbow (>= 2.2.2, < 4.0)
data/README.md CHANGED
@@ -32,12 +32,16 @@ It is built with only standard library dependencies. It additionally ships with
32
32
  - [construct_keys](#construct_keys)
33
33
  - [Visitor](#visitor)
34
34
  - [visit_method](#visit_method)
35
+ - [BasicVisitor](#basicvisitor)
35
36
  - [Language server](#language-server)
36
37
  - [textDocument/formatting](#textdocumentformatting)
37
38
  - [textDocument/inlayHints](#textdocumentinlayhints)
38
39
  - [syntaxTree/visualizing](#syntaxtreevisualizing)
39
40
  - [Plugins](#plugins)
41
+ - [Configuration](#configuration)
42
+ - [Languages](#languages)
40
43
  - [Integration](#integration)
44
+ - [Rake](#rake)
41
45
  - [RuboCop](#rubocop)
42
46
  - [VSCode](#vscode)
43
47
  - [Contributing](#contributing)
@@ -223,7 +227,7 @@ This function takes an input string containing Ruby code and returns the syntax
223
227
 
224
228
  ### SyntaxTree.format(source)
225
229
 
226
- This function takes an input string containing Ruby code, parses it into its underlying syntax tree, and formats it back out to a string.
230
+ This function takes an input string containing Ruby code, parses it into its underlying syntax tree, and formats it back out to a string. You can optionally pass a second argument to this method as well that is the maximum width to print. It defaults to `80`.
227
231
 
228
232
  ## Nodes
229
233
 
@@ -370,6 +374,20 @@ Did you mean? visit_binary
370
374
  from bin/console:8:in `<main>'
371
375
  ```
372
376
 
377
+ ### BasicVisitor
378
+
379
+ When you're defining your own visitor, by default it will walk down the tree even if you don't define `visit_*` methods. This is to ensure you can define a subset of the necessary methods in order to only interact with the nodes you're interested in. If you'd like to change this default to instead raise an error if you visit a node you haven't explicitly handled, you can instead inherit from `BasicVisitor`.
380
+
381
+ ```ruby
382
+ class MyVisitor < SyntaxTree::BasicVisitor
383
+ def visit_int(node)
384
+ # ...
385
+ end
386
+ end
387
+ ```
388
+
389
+ The visitor defined above will error out unless it's only visiting a `SyntaxTree::Int` node. This is useful in a couple of ways, e.g., if you're trying to define a visitor to handle the whole tree but it's currently a work-in-progress.
390
+
373
391
  ## Language server
374
392
 
375
393
  Syntax Tree additionally ships with a language server conforming to the [language server protocol](https://microsoft.github.io/language-server-protocol/). It can be invoked through the CLI by running:
@@ -408,9 +426,12 @@ You can register additional configuration and additional languages that can flow
408
426
 
409
427
  ### Configuration
410
428
 
411
- To register additional configuration, define a file somewhere in your load path named `syntax_tree/my_plugin` directory. Then when invoking the CLI, you will pass `--plugins=my_plugin`. That will get required. In this way, you can modify Syntax Tree however you would like. Some plugins ship with Syntax Tree itself. They are:
429
+ To register additional configuration, define a file somewhere in your load path named `syntax_tree/my_plugin`. Then when invoking the CLI, you will pass `--plugins=my_plugin`. To require multiple, separate them by a comma. In this way, you can modify Syntax Tree however you would like. Some plugins ship with Syntax Tree itself. They are:
412
430
 
413
431
  * `plugin/single_quotes` - This will change all of your string literals to use single quotes instead of the default double quotes.
432
+ * `plugin/trailing_comma` - This will put trailing commas into multiline array literals, hash literals, and method calls that can support trailing commas.
433
+
434
+ If you're using Syntax Tree as a library, you should require those files directly.
414
435
 
415
436
  ### Languages
416
437
 
@@ -436,6 +457,46 @@ Below are listed all of the "official" language plugins hosted under the same Gi
436
457
 
437
458
  Syntax Tree's goal is to seemlessly integrate into your workflow. To this end, it provides a couple of additional tools beyond the CLI and the Ruby library.
438
459
 
460
+ ### Rake
461
+
462
+ Syntax Tree ships with the ability to define [rake](https://github.com/ruby/rake) tasks that will trigger runs of the CLI. To define them in your application, add the following configuration to your `Rakefile`:
463
+
464
+ ```ruby
465
+ require "syntax_tree/rake_tasks"
466
+ SyntaxTree::Rake::CheckTask.new
467
+ SyntaxTree::Rake::WriteTask.new
468
+ ```
469
+
470
+ These calls will define `rake stree:check` and `rake stree:write` (equivalent to calling `stree check` and `stree write` with the CLI respectively). You can configure them by either passing arguments to the `new` method or by using a block.
471
+
472
+ #### `name`
473
+
474
+ If you'd like to change the default name of the rake task, you can pass that as the first argument, as in:
475
+
476
+ ```ruby
477
+ SyntaxTree::Rake::WriteTask.new(:format)
478
+ ```
479
+
480
+ #### `source_files`
481
+
482
+ If you wanted to configure Syntax Tree to check or write different files than the default (`lib/**/*.rb`), you can set the `source_files` field, as in:
483
+
484
+ ```ruby
485
+ SyntaxTree::Rake::WriteTask.new do |t|
486
+ t.source_files = FileList[%w[Gemfile Rakefile lib/**/*.rb test/**/*.rb]]
487
+ end
488
+ ```
489
+
490
+ #### `plugins`
491
+
492
+ 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:
493
+
494
+ ```ruby
495
+ SyntaxTree::Rake::WriteTask.new do |t|
496
+ t.plugins = ["plugin/single_quotes"]
497
+ end
498
+ ```
499
+
439
500
  ### RuboCop
440
501
 
441
502
  RuboCop and Syntax Tree serve different purposes, but there is overlap with some of RuboCop's functionality. Syntax Tree provides a RuboCop configuration file to disable rules that are redundant with Syntax Tree. To use this configuration file, add the following snippet to the top of your project's `.rubocop.yml`:
data/Rakefile CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "bundler/gem_tasks"
4
4
  require "rake/testtask"
5
+ require "syntax_tree/rake_tasks"
5
6
 
6
7
  Rake::TestTask.new(:test) do |t|
7
8
  t.libs << "test"
@@ -11,24 +12,8 @@ end
11
12
 
12
13
  task default: :test
13
14
 
14
- FILEPATHS = %w[
15
- Gemfile
16
- Rakefile
17
- syntax_tree.gemspec
18
- lib/**/*.rb
19
- test/*.rb
20
- ].freeze
15
+ SOURCE_FILES =
16
+ FileList[%w[Gemfile Rakefile syntax_tree.gemspec lib/**/*.rb test/*.rb]]
21
17
 
22
- task :syntax_tree do
23
- $:.unshift File.expand_path("lib", __dir__)
24
- require "syntax_tree"
25
- require "syntax_tree/cli"
26
- end
27
-
28
- task check: :syntax_tree do
29
- exit SyntaxTree::CLI.run(["check"] + FILEPATHS)
30
- end
31
-
32
- task format: :syntax_tree do
33
- exit SyntaxTree::CLI.run(["write"] + FILEPATHS)
34
- end
18
+ SyntaxTree::Rake::CheckTask.new { |t| t.source_files = SOURCE_FILES }
19
+ SyntaxTree::Rake::WriteTask.new { |t| t.source_files = SOURCE_FILES }
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SyntaxTree
4
+ # BasicVisitor is the parent class of the Visitor class that provides the
5
+ # ability to walk down the tree. It does not define any handlers, so you
6
+ # should extend this class if you want your visitor to raise an error if you
7
+ # attempt to visit a node that you don't handle.
8
+ class BasicVisitor
9
+ # This is raised when you use the Visitor.visit_method method and it fails.
10
+ # It is correctable to through DidYouMean.
11
+ class VisitMethodError < StandardError
12
+ attr_reader :visit_method
13
+
14
+ def initialize(visit_method)
15
+ @visit_method = visit_method
16
+ super("Invalid visit method: #{visit_method}")
17
+ end
18
+ end
19
+
20
+ # This class is used by DidYouMean to offer corrections to invalid visit
21
+ # method names.
22
+ class VisitMethodChecker
23
+ attr_reader :visit_method
24
+
25
+ def initialize(error)
26
+ @visit_method = error.visit_method
27
+ end
28
+
29
+ def corrections
30
+ @corrections ||=
31
+ DidYouMean::SpellChecker.new(
32
+ dictionary: Visitor.visit_methods
33
+ ).correct(visit_method)
34
+ end
35
+
36
+ DidYouMean.correct_error(VisitMethodError, self)
37
+ end
38
+
39
+ class << self
40
+ # This method is here to help folks write visitors.
41
+ #
42
+ # It's not always easy to ensure you're writing the correct method name in
43
+ # the visitor since it's perfectly valid to define methods that don't
44
+ # override these parent methods.
45
+ #
46
+ # If you use this method, you can ensure you're writing the correct method
47
+ # name. It will raise an error if the visit method you're defining isn't
48
+ # actually a method on the parent visitor.
49
+ def visit_method(method_name)
50
+ return if visit_methods.include?(method_name)
51
+
52
+ raise VisitMethodError, method_name
53
+ end
54
+
55
+ # This is the list of all of the valid visit methods.
56
+ def visit_methods
57
+ @visit_methods ||=
58
+ Visitor.instance_methods.grep(/^visit_(?!child_nodes)/)
59
+ end
60
+ end
61
+
62
+ def visit(node)
63
+ node&.accept(self)
64
+ end
65
+
66
+ def visit_all(nodes)
67
+ nodes.map { |node| visit(node) }
68
+ end
69
+
70
+ def visit_child_nodes(node)
71
+ visit_all(node.child_nodes)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SyntaxTree
4
+ class Formatter
5
+ # This module overrides the trailing_comma? method on the formatter to
6
+ # return true.
7
+ module TrailingComma
8
+ def trailing_comma?
9
+ true
10
+ end
11
+ end
12
+ end
13
+ end
@@ -3,11 +3,16 @@
3
3
  module SyntaxTree
4
4
  # A slightly enhanced PP that knows how to format recursively including
5
5
  # comments.
6
- class Formatter < PP
6
+ class Formatter < PrettierPrint
7
7
  COMMENT_PRIORITY = 1
8
8
  HEREDOC_PRIORITY = 2
9
9
 
10
- attr_reader :source, :stack, :quote
10
+ attr_reader :source, :stack
11
+
12
+ # These options are overridden in plugins to we need to make sure they are
13
+ # available here.
14
+ attr_reader :quote, :trailing_comma
15
+ alias trailing_comma? trailing_comma
11
16
 
12
17
  def initialize(source, ...)
13
18
  super(...)
@@ -15,6 +20,7 @@ module SyntaxTree
15
20
  @source = source
16
21
  @stack = []
17
22
  @quote = "\""
23
+ @trailing_comma = false
18
24
  end
19
25
 
20
26
  def self.format(source, node)