syntax_tree 2.5.0 → 2.6.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 +4 -4
- data/.github/workflows/main.yml +1 -1
- data/CHANGELOG.md +14 -1
- data/Gemfile.lock +1 -1
- data/README.md +48 -2
- data/Rakefile +5 -20
- data/lib/syntax_tree/formatter/trailing_comma.rb +13 -0
- data/lib/syntax_tree/formatter.rb +7 -1
- data/lib/syntax_tree/node.rb +123 -12
- data/lib/syntax_tree/parser.rb +112 -0
- data/lib/syntax_tree/plugin/trailing_comma.rb +4 -0
- data/lib/syntax_tree/rake/check_task.rb +66 -0
- data/lib/syntax_tree/rake/write_task.rb +66 -0
- data/lib/syntax_tree/rake_tasks.rb +4 -0
- data/lib/syntax_tree/version.rb +1 -1
- data/lib/syntax_tree/visitor/field_visitor.rb +8 -0
- data/lib/syntax_tree/visitor.rb +3 -0
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3d700916c1fab01ddc92117fd2b99c26b699df9e03f06b83eafa1415167ef7d
|
4
|
+
data.tar.gz: f5499912fe7bf422b44360bf66ce3f7e74145f3a2cc3ef5668e20fc97bd61948
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e287bcace78e800140ce6b30044a684587e8514f7f0b4c8a57f7b4f3926717a96eb966828e42325a44c1af23715cc602c3cb327dcab27d5390b0353b6a595744
|
7
|
+
data.tar.gz: 7cb34f0d9d423b3129033f04dc543d1bb9b19e62dcc7a9a140eb5c3a3159caaf389746930d15e6556df753e10f0651e38ab5e4db95bad63737836e14f14a86c1
|
data/.github/workflows/main.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,18 @@ 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.6.0] - 2022-05-16
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- [#74](https://github.com/ruby-syntax-tree/syntax_tree/pull/74) - Add Rake test to run check and format commands.
|
14
|
+
- [#83](https://github.com/ruby-syntax-tree/syntax_tree/pull/83) - Add a trailing commas plugin.
|
15
|
+
- [#84](https://github.com/ruby-syntax-tree/syntax_tree/pull/84) - Handle lambda block-local variables.
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
|
19
|
+
- [#85](https://github.com/ruby-syntax-tree/syntax_tree/pull/85) - Better handle trailing operators on command calls.
|
20
|
+
|
9
21
|
## [2.5.0] - 2022-05-13
|
10
22
|
|
11
23
|
### Added
|
@@ -224,7 +236,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
224
236
|
|
225
237
|
- 🎉 Initial release! 🎉
|
226
238
|
|
227
|
-
[unreleased]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.
|
239
|
+
[unreleased]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.6.0...HEAD
|
240
|
+
[2.6.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.5.0...v2.6.0
|
228
241
|
[2.5.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.4.1...v2.5.0
|
229
242
|
[2.4.1]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.4.0...v2.4.1
|
230
243
|
[2.4.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.3.1...v2.4.0
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -37,7 +37,10 @@ It is built with only standard library dependencies. It additionally ships with
|
|
37
37
|
- [textDocument/inlayHints](#textdocumentinlayhints)
|
38
38
|
- [syntaxTree/visualizing](#syntaxtreevisualizing)
|
39
39
|
- [Plugins](#plugins)
|
40
|
+
- [Configuration](#configuration)
|
41
|
+
- [Languages](#languages)
|
40
42
|
- [Integration](#integration)
|
43
|
+
- [Rake](#rake)
|
41
44
|
- [RuboCop](#rubocop)
|
42
45
|
- [VSCode](#vscode)
|
43
46
|
- [Contributing](#contributing)
|
@@ -223,7 +226,7 @@ This function takes an input string containing Ruby code and returns the syntax
|
|
223
226
|
|
224
227
|
### SyntaxTree.format(source)
|
225
228
|
|
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.
|
229
|
+
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
230
|
|
228
231
|
## Nodes
|
229
232
|
|
@@ -408,9 +411,12 @@ You can register additional configuration and additional languages that can flow
|
|
408
411
|
|
409
412
|
### Configuration
|
410
413
|
|
411
|
-
To register additional configuration, define a file somewhere in your load path named `syntax_tree/my_plugin
|
414
|
+
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
415
|
|
413
416
|
* `plugin/single_quotes` - This will change all of your string literals to use single quotes instead of the default double quotes.
|
417
|
+
* `plugin/trailing_comma` - This will put trailing commas into multiline array literals, hash literals, and method calls that can support trailing commas.
|
418
|
+
|
419
|
+
If you're using Syntax Tree as a library, you should require those files directly.
|
414
420
|
|
415
421
|
### Languages
|
416
422
|
|
@@ -436,6 +442,46 @@ Below are listed all of the "official" language plugins hosted under the same Gi
|
|
436
442
|
|
437
443
|
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
444
|
|
445
|
+
### Rake
|
446
|
+
|
447
|
+
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`:
|
448
|
+
|
449
|
+
```ruby
|
450
|
+
require "syntax_tree/rake_tasks"
|
451
|
+
SyntaxTree::Rake::CheckTask.new
|
452
|
+
SyntaxTree::Rake::WriteTask.new
|
453
|
+
```
|
454
|
+
|
455
|
+
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.
|
456
|
+
|
457
|
+
#### `name`
|
458
|
+
|
459
|
+
If you'd like to change the default name of the rake task, you can pass that as the first argument, as in:
|
460
|
+
|
461
|
+
```ruby
|
462
|
+
SyntaxTree::Rake::WriteTask.new(:format)
|
463
|
+
```
|
464
|
+
|
465
|
+
#### `source_files`
|
466
|
+
|
467
|
+
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:
|
468
|
+
|
469
|
+
```ruby
|
470
|
+
SyntaxTree::Rake::WriteTask.new do |t|
|
471
|
+
t.source_files = FileList[%w[Gemfile Rakefile lib/**/*.rb test/**/*.rb]]
|
472
|
+
end
|
473
|
+
```
|
474
|
+
|
475
|
+
#### `plugins`
|
476
|
+
|
477
|
+
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:
|
478
|
+
|
479
|
+
```ruby
|
480
|
+
SyntaxTree::Rake::WriteTask.new do |t|
|
481
|
+
t.plugins = ["plugin/single_quotes"]
|
482
|
+
end
|
483
|
+
```
|
484
|
+
|
439
485
|
### RuboCop
|
440
486
|
|
441
487
|
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
|
-
|
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
|
-
|
23
|
-
|
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 }
|
@@ -7,7 +7,12 @@ module SyntaxTree
|
|
7
7
|
COMMENT_PRIORITY = 1
|
8
8
|
HEREDOC_PRIORITY = 2
|
9
9
|
|
10
|
-
attr_reader :source, :stack
|
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)
|
data/lib/syntax_tree/node.rb
CHANGED
@@ -597,10 +597,30 @@ module SyntaxTree
|
|
597
597
|
q.indent do
|
598
598
|
q.breakable("")
|
599
599
|
q.format(arguments)
|
600
|
+
q.if_break { q.text(",") } if q.trailing_comma? && trailing_comma?
|
600
601
|
end
|
601
602
|
q.breakable("")
|
602
603
|
end
|
603
604
|
end
|
605
|
+
|
606
|
+
private
|
607
|
+
|
608
|
+
def trailing_comma?
|
609
|
+
case arguments
|
610
|
+
in Args[parts: [*, ArgBlock]]
|
611
|
+
# If the last argument is a block, then we can't put a trailing comma
|
612
|
+
# after it without resulting in a syntax error.
|
613
|
+
false
|
614
|
+
in Args[parts: [Command | CommandCall]]
|
615
|
+
# If the only argument is a command or command call, then a trailing
|
616
|
+
# comma would be parsed as part of that expression instead of on this
|
617
|
+
# one, so we don't want to add a trailing comma.
|
618
|
+
false
|
619
|
+
else
|
620
|
+
# Otherwise, we should be okay to add a trailing comma.
|
621
|
+
true
|
622
|
+
end
|
623
|
+
end
|
604
624
|
end
|
605
625
|
|
606
626
|
# Args represents a list of arguments being passed to a method call or array
|
@@ -859,6 +879,7 @@ module SyntaxTree
|
|
859
879
|
end
|
860
880
|
|
861
881
|
q.seplist(contents.parts, separator) { |part| q.format(part) }
|
882
|
+
q.if_break { q.text(",") } if q.trailing_comma?
|
862
883
|
end
|
863
884
|
q.breakable("")
|
864
885
|
end
|
@@ -954,6 +975,7 @@ module SyntaxTree
|
|
954
975
|
q.indent do
|
955
976
|
q.breakable("")
|
956
977
|
q.format(contents)
|
978
|
+
q.if_break { q.text(",") } if q.trailing_comma?
|
957
979
|
end
|
958
980
|
end
|
959
981
|
|
@@ -3030,8 +3052,20 @@ module SyntaxTree
|
|
3030
3052
|
doc =
|
3031
3053
|
q.nest(0) do
|
3032
3054
|
q.format(receiver)
|
3033
|
-
|
3034
|
-
|
3055
|
+
|
3056
|
+
# If there are leading comments on the message then we know we have
|
3057
|
+
# a newline in the source that is forcing these things apart. In
|
3058
|
+
# this case we will have to use a trailing operator.
|
3059
|
+
if message.comments.any?(&:leading?)
|
3060
|
+
q.format(CallOperatorFormatter.new(operator), stackable: false)
|
3061
|
+
q.indent do
|
3062
|
+
q.breakable("")
|
3063
|
+
q.format(message)
|
3064
|
+
end
|
3065
|
+
else
|
3066
|
+
q.format(CallOperatorFormatter.new(operator), stackable: false)
|
3067
|
+
q.format(message)
|
3068
|
+
end
|
3035
3069
|
end
|
3036
3070
|
|
3037
3071
|
case arguments
|
@@ -4751,6 +4785,7 @@ module SyntaxTree
|
|
4751
4785
|
q.indent do
|
4752
4786
|
q.breakable
|
4753
4787
|
q.seplist(assocs) { |assoc| q.format(assoc) }
|
4788
|
+
q.if_break { q.text(",") } if q.trailing_comma?
|
4754
4789
|
end
|
4755
4790
|
q.breakable
|
4756
4791
|
end
|
@@ -5877,7 +5912,7 @@ module SyntaxTree
|
|
5877
5912
|
# ->(value) { value * 2 }
|
5878
5913
|
#
|
5879
5914
|
class Lambda < Node
|
5880
|
-
# [
|
5915
|
+
# [LambdaVar | Paren] the parameter declaration for this lambda
|
5881
5916
|
attr_reader :params
|
5882
5917
|
|
5883
5918
|
# [BodyStmt | Statements] the expressions to be executed in this lambda
|
@@ -5932,24 +5967,100 @@ module SyntaxTree
|
|
5932
5967
|
node.is_a?(Command) || node.is_a?(CommandCall)
|
5933
5968
|
end
|
5934
5969
|
|
5935
|
-
|
5936
|
-
|
5970
|
+
if force_parens
|
5971
|
+
q.text("{")
|
5972
|
+
|
5973
|
+
unless statements.empty?
|
5974
|
+
q.indent do
|
5975
|
+
q.breakable
|
5976
|
+
q.format(statements)
|
5977
|
+
end
|
5978
|
+
q.breakable
|
5979
|
+
end
|
5980
|
+
|
5981
|
+
q.text("}")
|
5982
|
+
else
|
5983
|
+
q.text("do")
|
5984
|
+
|
5985
|
+
unless statements.empty?
|
5986
|
+
q.indent do
|
5987
|
+
q.breakable
|
5988
|
+
q.format(statements)
|
5989
|
+
end
|
5990
|
+
end
|
5991
|
+
|
5937
5992
|
q.breakable
|
5938
|
-
q.
|
5993
|
+
q.text("end")
|
5939
5994
|
end
|
5940
|
-
|
5941
|
-
q.breakable
|
5942
|
-
q.text(force_parens ? "}" : "end")
|
5943
5995
|
end
|
5944
5996
|
.if_flat do
|
5945
|
-
q.text("{
|
5946
|
-
|
5947
|
-
|
5997
|
+
q.text("{")
|
5998
|
+
|
5999
|
+
unless statements.empty?
|
6000
|
+
q.text(" ")
|
6001
|
+
q.format(statements)
|
6002
|
+
q.text(" ")
|
6003
|
+
end
|
6004
|
+
|
6005
|
+
q.text("}")
|
5948
6006
|
end
|
5949
6007
|
end
|
5950
6008
|
end
|
5951
6009
|
end
|
5952
6010
|
|
6011
|
+
# LambdaVar represents the parameters being declared for a lambda. Effectively
|
6012
|
+
# this node is everything contained within the parentheses. This includes all
|
6013
|
+
# of the various parameter types, as well as block-local variable
|
6014
|
+
# declarations.
|
6015
|
+
#
|
6016
|
+
# -> (positional, optional = value, keyword:, █ local) do
|
6017
|
+
# end
|
6018
|
+
#
|
6019
|
+
class LambdaVar < Node
|
6020
|
+
# [Params] the parameters being declared with the block
|
6021
|
+
attr_reader :params
|
6022
|
+
|
6023
|
+
# [Array[ Ident ]] the list of block-local variable declarations
|
6024
|
+
attr_reader :locals
|
6025
|
+
|
6026
|
+
# [Array[ Comment | EmbDoc ]] the comments attached to this node
|
6027
|
+
attr_reader :comments
|
6028
|
+
|
6029
|
+
def initialize(params:, locals:, location:, comments: [])
|
6030
|
+
@params = params
|
6031
|
+
@locals = locals
|
6032
|
+
@location = location
|
6033
|
+
@comments = comments
|
6034
|
+
end
|
6035
|
+
|
6036
|
+
def accept(visitor)
|
6037
|
+
visitor.visit_lambda_var(self)
|
6038
|
+
end
|
6039
|
+
|
6040
|
+
def child_nodes
|
6041
|
+
[params, *locals]
|
6042
|
+
end
|
6043
|
+
|
6044
|
+
alias deconstruct child_nodes
|
6045
|
+
|
6046
|
+
def deconstruct_keys(_keys)
|
6047
|
+
{ params: params, locals: locals, location: location, comments: comments }
|
6048
|
+
end
|
6049
|
+
|
6050
|
+
def empty?
|
6051
|
+
params.empty? && locals.empty?
|
6052
|
+
end
|
6053
|
+
|
6054
|
+
def format(q)
|
6055
|
+
q.format(params)
|
6056
|
+
|
6057
|
+
if locals.any?
|
6058
|
+
q.text("; ")
|
6059
|
+
q.seplist(locals, -> { q.text(", ") }) { |local| q.format(local) }
|
6060
|
+
end
|
6061
|
+
end
|
6062
|
+
end
|
6063
|
+
|
5953
6064
|
# LBrace represents the use of a left brace, i.e., {.
|
5954
6065
|
class LBrace < Node
|
5955
6066
|
# [String] the left brace
|
data/lib/syntax_tree/parser.rb
CHANGED
@@ -1940,6 +1940,41 @@ module SyntaxTree
|
|
1940
1940
|
token.location.start_char > beginning.location.start_char
|
1941
1941
|
end
|
1942
1942
|
|
1943
|
+
# We need to do some special mapping here. Since ripper doesn't support
|
1944
|
+
# capturing lambda var until 3.2, we need to normalize all of that here.
|
1945
|
+
params =
|
1946
|
+
case params
|
1947
|
+
in Paren[contents: Params]
|
1948
|
+
# In this case we've gotten to the <3.2 parentheses wrapping a set of
|
1949
|
+
# parameters case. Here we need to manually scan for lambda locals.
|
1950
|
+
range = (params.location.start_char + 1)...params.location.end_char
|
1951
|
+
locals = lambda_locals(source[range])
|
1952
|
+
|
1953
|
+
location = params.contents.location
|
1954
|
+
location = location.to(locals.last.location) if locals.any?
|
1955
|
+
|
1956
|
+
Paren.new(
|
1957
|
+
lparen: params.lparen,
|
1958
|
+
contents:
|
1959
|
+
LambdaVar.new(
|
1960
|
+
params: params.contents,
|
1961
|
+
locals: locals,
|
1962
|
+
location: location
|
1963
|
+
),
|
1964
|
+
location: params.location,
|
1965
|
+
comments: params.comments
|
1966
|
+
)
|
1967
|
+
in Params
|
1968
|
+
# In this case we've gotten to the <3.2 plain set of parameters. In
|
1969
|
+
# this case there cannot be lambda locals, so we will wrap the
|
1970
|
+
# parameters into a lambda var that has no locals.
|
1971
|
+
LambdaVar.new(params: params, locals: [], location: params.location)
|
1972
|
+
in LambdaVar
|
1973
|
+
# In this case we've gotten to 3.2+ lambda var. In this case we don't
|
1974
|
+
# need to do anything and can just the value as given.
|
1975
|
+
params
|
1976
|
+
end
|
1977
|
+
|
1943
1978
|
if braces
|
1944
1979
|
opening = find_token(TLamBeg)
|
1945
1980
|
closing = find_token(RBrace)
|
@@ -1962,6 +1997,83 @@ module SyntaxTree
|
|
1962
1997
|
)
|
1963
1998
|
end
|
1964
1999
|
|
2000
|
+
# :call-seq:
|
2001
|
+
# on_lambda_var: (Params params, Array[ Ident ] locals) -> LambdaVar
|
2002
|
+
def on_lambda_var(params, locals)
|
2003
|
+
location = params.location
|
2004
|
+
location = location.to(locals.last.location) if locals.any?
|
2005
|
+
|
2006
|
+
LambdaVar.new(params: params, locals: locals || [], location: location)
|
2007
|
+
end
|
2008
|
+
|
2009
|
+
# Ripper doesn't support capturing lambda local variables until 3.2. To
|
2010
|
+
# mitigate this, we have to parse that code for ourselves. We use the range
|
2011
|
+
# from the parentheses to find where we _should_ be looking. Then we check
|
2012
|
+
# if the resulting tokens match a pattern that we determine means that the
|
2013
|
+
# declaration has block-local variables. Once it does, we parse those out
|
2014
|
+
# and convert them into Ident nodes.
|
2015
|
+
def lambda_locals(source)
|
2016
|
+
tokens = Ripper.lex(source)
|
2017
|
+
|
2018
|
+
# First, check that we have a semi-colon. If we do, then we can start to
|
2019
|
+
# parse the tokens _after_ the semicolon.
|
2020
|
+
index = tokens.rindex { |token| token[1] == :on_semicolon }
|
2021
|
+
return [] unless index
|
2022
|
+
|
2023
|
+
# Next, map over the tokens and convert them into Ident nodes. Bail out
|
2024
|
+
# midway through if we encounter a token we didn't expect. Basically we're
|
2025
|
+
# making our own mini-parser here. To do that we'll walk through a small
|
2026
|
+
# state machine:
|
2027
|
+
#
|
2028
|
+
# ┌────────┐ ┌────────┐ ┌─────────┐
|
2029
|
+
# │ │ │ │ │┌───────┐│
|
2030
|
+
# ──> │ item │ ─── ident ──> │ next │ ─── rparen ──> ││ final ││
|
2031
|
+
# │ │ <── comma ─── │ │ │└───────┘│
|
2032
|
+
# └────────┘ └────────┘ └─────────┘
|
2033
|
+
# │ ^ │ ^
|
2034
|
+
# └──┘ └──┘
|
2035
|
+
# ignored_nl, sp nl, sp
|
2036
|
+
#
|
2037
|
+
state = :item
|
2038
|
+
transitions = {
|
2039
|
+
item: {
|
2040
|
+
on_ignored_nl: :item,
|
2041
|
+
on_sp: :item,
|
2042
|
+
on_ident: :next
|
2043
|
+
},
|
2044
|
+
next: {
|
2045
|
+
on_nl: :next,
|
2046
|
+
on_sp: :next,
|
2047
|
+
on_comma: :item,
|
2048
|
+
on_rparen: :final
|
2049
|
+
},
|
2050
|
+
final: {
|
2051
|
+
}
|
2052
|
+
}
|
2053
|
+
|
2054
|
+
tokens[(index + 1)..].each_with_object([]) do |token, locals|
|
2055
|
+
(lineno, column), type, value, = token
|
2056
|
+
|
2057
|
+
# Make the state transition for the parser. If there isn't a transition
|
2058
|
+
# from the current state to a new state for this type, then we're in a
|
2059
|
+
# pattern that isn't actually locals. In that case we can return [].
|
2060
|
+
state = transitions[state].fetch(type) { return [] }
|
2061
|
+
|
2062
|
+
# If we hit an identifier, then add it to our list.
|
2063
|
+
next if type != :on_ident
|
2064
|
+
|
2065
|
+
location =
|
2066
|
+
Location.token(
|
2067
|
+
line: lineno,
|
2068
|
+
char: line_counts[lineno - 1][column],
|
2069
|
+
column: column,
|
2070
|
+
size: value.size
|
2071
|
+
)
|
2072
|
+
|
2073
|
+
locals << Ident.new(value: value, location: location)
|
2074
|
+
end
|
2075
|
+
end
|
2076
|
+
|
1965
2077
|
# :call-seq:
|
1966
2078
|
# on_lbrace: (String value) -> LBrace
|
1967
2079
|
def on_lbrace(value)
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rake"
|
4
|
+
require "rake/tasklib"
|
5
|
+
|
6
|
+
require "syntax_tree"
|
7
|
+
require "syntax_tree/cli"
|
8
|
+
|
9
|
+
module SyntaxTree
|
10
|
+
module Rake
|
11
|
+
# A Rake task that runs check on a set of source files.
|
12
|
+
#
|
13
|
+
# Example:
|
14
|
+
#
|
15
|
+
# require 'syntax_tree/rake/check_task'
|
16
|
+
#
|
17
|
+
# SyntaxTree::Rake::CheckTask.new do |t|
|
18
|
+
# t.source_files = '{app,config,lib}/**/*.rb'
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# This will create task that can be run with:
|
22
|
+
#
|
23
|
+
# rake stree_check
|
24
|
+
#
|
25
|
+
class CheckTask < ::Rake::TaskLib
|
26
|
+
# Name of the task.
|
27
|
+
# Defaults to :"stree:check".
|
28
|
+
attr_accessor :name
|
29
|
+
|
30
|
+
# Glob pattern to match source files.
|
31
|
+
# Defaults to 'lib/**/*.rb'.
|
32
|
+
attr_accessor :source_files
|
33
|
+
|
34
|
+
# The set of plugins to require.
|
35
|
+
# Defaults to [].
|
36
|
+
attr_accessor :plugins
|
37
|
+
|
38
|
+
def initialize(
|
39
|
+
name = :"stree:check",
|
40
|
+
source_files = ::Rake::FileList["lib/**/*.rb"],
|
41
|
+
plugins = []
|
42
|
+
)
|
43
|
+
@name = name
|
44
|
+
@source_files = source_files
|
45
|
+
@plugins = plugins
|
46
|
+
|
47
|
+
yield self if block_given?
|
48
|
+
define_task
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def define_task
|
54
|
+
desc "Runs `stree check` over source files"
|
55
|
+
task(name) { run_task }
|
56
|
+
end
|
57
|
+
|
58
|
+
def run_task
|
59
|
+
arguments = ["check"]
|
60
|
+
arguments << "--plugins=#{plugins.join(",")}" if plugins.any?
|
61
|
+
|
62
|
+
SyntaxTree::CLI.run(arguments + Array(source_files))
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rake"
|
4
|
+
require "rake/tasklib"
|
5
|
+
|
6
|
+
require "syntax_tree"
|
7
|
+
require "syntax_tree/cli"
|
8
|
+
|
9
|
+
module SyntaxTree
|
10
|
+
module Rake
|
11
|
+
# A Rake task that runs format on a set of source files.
|
12
|
+
#
|
13
|
+
# Example:
|
14
|
+
#
|
15
|
+
# require 'syntax_tree/rake/write_task'
|
16
|
+
#
|
17
|
+
# SyntaxTree::Rake::WriteTask.new do |t|
|
18
|
+
# t.source_files = '{app,config,lib}/**/*.rb'
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# This will create task that can be run with:
|
22
|
+
#
|
23
|
+
# rake stree_write
|
24
|
+
#
|
25
|
+
class WriteTask < ::Rake::TaskLib
|
26
|
+
# Name of the task.
|
27
|
+
# Defaults to :"stree:write".
|
28
|
+
attr_accessor :name
|
29
|
+
|
30
|
+
# Glob pattern to match source files.
|
31
|
+
# Defaults to 'lib/**/*.rb'.
|
32
|
+
attr_accessor :source_files
|
33
|
+
|
34
|
+
# The set of plugins to require.
|
35
|
+
# Defaults to [].
|
36
|
+
attr_accessor :plugins
|
37
|
+
|
38
|
+
def initialize(
|
39
|
+
name = :"stree:write",
|
40
|
+
source_files = ::Rake::FileList["lib/**/*.rb"],
|
41
|
+
plugins = []
|
42
|
+
)
|
43
|
+
@name = name
|
44
|
+
@source_files = source_files
|
45
|
+
@plugins = plugins
|
46
|
+
|
47
|
+
yield self if block_given?
|
48
|
+
define_task
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def define_task
|
54
|
+
desc "Runs `stree write` over source files"
|
55
|
+
task(name) { run_task }
|
56
|
+
end
|
57
|
+
|
58
|
+
def run_task
|
59
|
+
arguments = ["write"]
|
60
|
+
arguments << "--plugins=#{plugins.join(",")}" if plugins.any?
|
61
|
+
|
62
|
+
SyntaxTree::CLI.run(arguments + Array(source_files))
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/syntax_tree/version.rb
CHANGED
@@ -586,6 +586,14 @@ module SyntaxTree
|
|
586
586
|
end
|
587
587
|
end
|
588
588
|
|
589
|
+
def visit_lambda_var(node)
|
590
|
+
node(node, "lambda_var") do
|
591
|
+
field("params", node.params)
|
592
|
+
list("locals", node.locals) if node.locals.any?
|
593
|
+
comments(node)
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
589
597
|
def visit_lbrace(node)
|
590
598
|
visit_token(node, "lbrace")
|
591
599
|
end
|
data/lib/syntax_tree/visitor.rb
CHANGED
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: 2.
|
4
|
+
version: 2.6.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-05-
|
11
|
+
date: 2022-05-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: prettier_print
|
@@ -124,11 +124,16 @@ files:
|
|
124
124
|
- lib/syntax_tree/cli.rb
|
125
125
|
- lib/syntax_tree/formatter.rb
|
126
126
|
- lib/syntax_tree/formatter/single_quotes.rb
|
127
|
+
- lib/syntax_tree/formatter/trailing_comma.rb
|
127
128
|
- lib/syntax_tree/language_server.rb
|
128
129
|
- lib/syntax_tree/language_server/inlay_hints.rb
|
129
130
|
- lib/syntax_tree/node.rb
|
130
131
|
- lib/syntax_tree/parser.rb
|
131
132
|
- lib/syntax_tree/plugin/single_quotes.rb
|
133
|
+
- lib/syntax_tree/plugin/trailing_comma.rb
|
134
|
+
- lib/syntax_tree/rake/check_task.rb
|
135
|
+
- lib/syntax_tree/rake/write_task.rb
|
136
|
+
- lib/syntax_tree/rake_tasks.rb
|
132
137
|
- lib/syntax_tree/version.rb
|
133
138
|
- lib/syntax_tree/visitor.rb
|
134
139
|
- lib/syntax_tree/visitor/field_visitor.rb
|
@@ -156,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
161
|
- !ruby/object:Gem::Version
|
157
162
|
version: '0'
|
158
163
|
requirements: []
|
159
|
-
rubygems_version: 3.
|
164
|
+
rubygems_version: 3.4.0.dev
|
160
165
|
signing_key:
|
161
166
|
specification_version: 4
|
162
167
|
summary: A parser based on ripper
|