syntax_tree 2.1.0 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -1
- data/Gemfile.lock +1 -1
- data/README.md +21 -0
- data/lib/syntax_tree/node.rb +11 -5
- data/lib/syntax_tree/parser.rb +32 -22
- data/lib/syntax_tree/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd341a51ce36b230703bfbe86078641e7670058a3e41d0dbb125548c0821a65a
|
4
|
+
data.tar.gz: 9ebdca60f2956e24f83a58749266c89eb0eed88003a06699432956a0ecfa735a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8292d8020afa5ece8afdbaa60e959902357e769f098c75894d2b85686a20f824cf510563b2cd31e86b3f8f781f74cf8aaafac76e0e156e26897999ccb72ae36
|
7
|
+
data.tar.gz: 968a355401a9bd1ca6a3e67d60e5587485de9ad3ad2a5f9e8cbe7add95622364e4c094a757035482c35377ab75cb14926af1f5ab8a0df0e5069ba69f7bed1851
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,16 @@ 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.1.1] - 2022-04-16
|
10
|
+
|
11
|
+
### Changed
|
12
|
+
|
13
|
+
- [#45](https://github.com/ruby-syntax-tree/syntax_tree/issues/45) - Fix parsing expressions like `foo.instance_exec(&T.must(block))`, where there are two `args_add_block` calls with a single `&`. Previously it was associating the `&` with the wrong block.
|
14
|
+
- [#47](https://github.com/ruby-syntax-tree/syntax_tree/pull/47) - Handle expressions like `not()`.
|
15
|
+
- [#48](https://github.com/ruby-syntax-tree/syntax_tree/pull/48) - Handle special call syntax with `::` operator.
|
16
|
+
- [#49](https://github.com/ruby-syntax-tree/syntax_tree/pull/49) - Handle expressions like `case foo; in {}; end`.
|
17
|
+
- [#50](https://github.com/ruby-syntax-tree/syntax_tree/pull/50) - Parsing expressions like `case foo; in **nil; end`.
|
18
|
+
|
9
19
|
## [2.1.0] - 2022-04-12
|
10
20
|
|
11
21
|
### Added
|
@@ -143,7 +153,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
143
153
|
|
144
154
|
- 🎉 Initial release! 🎉
|
145
155
|
|
146
|
-
[unreleased]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.1.
|
156
|
+
[unreleased]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.1.1...HEAD
|
157
|
+
[2.1.1]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.1.0...v2.1.1
|
147
158
|
[2.1.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.0.1...v2.1.0
|
148
159
|
[2.0.1]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v2.0.0...v2.0.1
|
149
160
|
[2.0.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v1.2.0...v2.0.0
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -33,6 +33,7 @@ It is built with only standard library dependencies. It additionally ships with
|
|
33
33
|
- [textDocument/formatting](#textdocumentformatting)
|
34
34
|
- [textDocument/inlayHints](#textdocumentinlayhints)
|
35
35
|
- [syntaxTree/visualizing](#syntaxtreevisualizing)
|
36
|
+
- [Plugins](#plugins)
|
36
37
|
- [Contributing](#contributing)
|
37
38
|
- [License](#license)
|
38
39
|
|
@@ -307,6 +308,26 @@ Implicity, the `2 * 3` is going to be executed first because the `*` operator ha
|
|
307
308
|
|
308
309
|
The language server additionally includes this custom request to return a textual representation of the syntax tree underlying the source code of a file. Language server clients can use this to (for example) open an additional tab with this information displayed.
|
309
310
|
|
311
|
+
## Plugins
|
312
|
+
|
313
|
+
You can register additional languages that can flow through the same CLI with Syntax Tree's plugin system. To register a new language, call:
|
314
|
+
|
315
|
+
```ruby
|
316
|
+
SyntaxTree.register_handler(".mylang", MyLanguage)
|
317
|
+
```
|
318
|
+
|
319
|
+
In this case, whenever the CLI encounters a filepath that ends with the given extension, it will invoke methods on `MyLanguage` instead of `SyntaxTree` itself. To make sure your object conforms to each of the necessary APIs, it should implement:
|
320
|
+
|
321
|
+
* `MyLanguage.read(filepath)` - usually this is just an alias to `File.read(filepath)`, but if you need anything else that hook is here.
|
322
|
+
* `MyLanguage.parse(source)` - this should return the syntax tree corresponding to the given source. Those objects should implement the `pretty_print` interface.
|
323
|
+
* `MyLanguage.format(source)` - this should return the formatted version of the given source.
|
324
|
+
|
325
|
+
Below are listed all of the "official" plugins hosted under the same GitHub organization, which can be used as references for how to implement other plugins.
|
326
|
+
|
327
|
+
* [SyntaxTree::Haml](https://github.com/ruby-syntax-tree/syntax_tree-haml) for the [Haml template language](https://haml.info/).
|
328
|
+
* [SyntaxTree::JSON](https://github.com/ruby-syntax-tree/syntax_tree-json) for JSON.
|
329
|
+
* [SyntaxTree::RBS](https://github.com/ruby-syntax-tree/syntax_tree-rbs) for the [RBS type language](https://github.com/ruby/rbs).
|
330
|
+
|
310
331
|
## Contributing
|
311
332
|
|
312
333
|
Bug reports and pull requests are welcome on GitHub at https://github.com/ruby-syntax-tree/syntax_tree.
|
data/lib/syntax_tree/node.rb
CHANGED
@@ -4536,6 +4536,7 @@ module SyntaxTree
|
|
4536
4536
|
def format(q)
|
4537
4537
|
parts = keywords.map { |(key, value)| KeywordFormatter.new(key, value) }
|
4538
4538
|
parts << KeywordRestFormatter.new(keyword_rest) if keyword_rest
|
4539
|
+
|
4539
4540
|
contents = -> do
|
4540
4541
|
q.seplist(parts) { |part| q.format(part, stackable: false) }
|
4541
4542
|
end
|
@@ -4546,8 +4547,9 @@ module SyntaxTree
|
|
4546
4547
|
return
|
4547
4548
|
end
|
4548
4549
|
|
4549
|
-
|
4550
|
-
|
4550
|
+
if parts.empty?
|
4551
|
+
q.text("{}")
|
4552
|
+
elsif PATTERNS.include?(q.parent.class)
|
4551
4553
|
q.text("{ ")
|
4552
4554
|
contents.call
|
4553
4555
|
q.text(" }")
|
@@ -8168,7 +8170,7 @@ module SyntaxTree
|
|
8168
8170
|
# not value
|
8169
8171
|
#
|
8170
8172
|
class Not < Node
|
8171
|
-
# [untyped] the statement on which to operate
|
8173
|
+
# [nil | untyped] the statement on which to operate
|
8172
8174
|
attr_reader :statement
|
8173
8175
|
|
8174
8176
|
# [boolean] whether or not parentheses were used
|
@@ -8205,7 +8207,7 @@ module SyntaxTree
|
|
8205
8207
|
|
8206
8208
|
def format(q)
|
8207
8209
|
q.text(parentheses ? "not(" : "not ")
|
8208
|
-
q.format(statement)
|
8210
|
+
q.format(statement) if statement
|
8209
8211
|
q.text(")") if parentheses
|
8210
8212
|
end
|
8211
8213
|
end
|
@@ -8675,7 +8677,11 @@ module SyntaxTree
|
|
8675
8677
|
end
|
8676
8678
|
|
8677
8679
|
def format(q)
|
8678
|
-
|
8680
|
+
if value == :nil
|
8681
|
+
q.text("nil")
|
8682
|
+
elsif value
|
8683
|
+
q.format(value)
|
8684
|
+
end
|
8679
8685
|
end
|
8680
8686
|
end
|
8681
8687
|
|
data/lib/syntax_tree/parser.rb
CHANGED
@@ -414,12 +414,19 @@ module SyntaxTree
|
|
414
414
|
# (false | untyped) block
|
415
415
|
# ) -> Args
|
416
416
|
def on_args_add_block(arguments, block)
|
417
|
+
# First, see if there is an & operator that could potentially be
|
418
|
+
# associated with the block part of this args_add_block. If there is not,
|
419
|
+
# then just return the arguments.
|
417
420
|
operator = find_token(Op, "&", consume: false)
|
418
|
-
|
419
|
-
# If we can't find the & operator, then there's no block to add to the
|
420
|
-
# list, so we're just going to return the arguments as-is.
|
421
421
|
return arguments unless operator
|
422
422
|
|
423
|
+
# If there are any arguments and the operator we found from the list is
|
424
|
+
# not after them, then we're going to return the arguments as-is because
|
425
|
+
# we're looking at an & that occurs before the arguments are done.
|
426
|
+
if arguments.parts.any? && operator.location.start_char < arguments.location.end_char
|
427
|
+
return arguments
|
428
|
+
end
|
429
|
+
|
423
430
|
# Now we know we have an & operator, so we're going to delete it from the
|
424
431
|
# list of tokens to make sure it doesn't get confused with anything else.
|
425
432
|
tokens.delete(operator)
|
@@ -428,13 +435,6 @@ module SyntaxTree
|
|
428
435
|
location = operator.location
|
429
436
|
location = operator.location.to(block.location) if block
|
430
437
|
|
431
|
-
# If there are any arguments and the operator we found from the list is
|
432
|
-
# not after them, then we're going to return the arguments as-is because
|
433
|
-
# we're looking at an & that occurs before the arguments are done.
|
434
|
-
if arguments.parts.any? && location.start_char < arguments.location.end_char
|
435
|
-
return arguments
|
436
|
-
end
|
437
|
-
|
438
438
|
# Otherwise, we're looking at an actual block argument (with or without a
|
439
439
|
# block, which could be missing because it could be a bare & since 3.1.0).
|
440
440
|
arg_block = ArgBlock.new(value: block, location: location)
|
@@ -761,8 +761,14 @@ module SyntaxTree
|
|
761
761
|
# (:call | Backtick | Const | Ident | Op) message
|
762
762
|
# ) -> Call
|
763
763
|
def on_call(receiver, operator, message)
|
764
|
-
ending =
|
765
|
-
|
764
|
+
ending =
|
765
|
+
if message != :call
|
766
|
+
message
|
767
|
+
elsif operator != :"::"
|
768
|
+
operator
|
769
|
+
else
|
770
|
+
receiver
|
771
|
+
end
|
766
772
|
|
767
773
|
Call.new(
|
768
774
|
receiver: receiver,
|
@@ -1495,13 +1501,19 @@ module SyntaxTree
|
|
1495
1501
|
# (nil | VarField) keyword_rest
|
1496
1502
|
# ) -> HshPtn
|
1497
1503
|
def on_hshptn(constant, keywords, keyword_rest)
|
1498
|
-
parts = [constant, keywords, keyword_rest].
|
1504
|
+
parts = [constant, *keywords&.flatten(1), keyword_rest].compact
|
1505
|
+
location =
|
1506
|
+
if parts.empty?
|
1507
|
+
find_token(LBrace).location.to(find_token(RBrace).location)
|
1508
|
+
else
|
1509
|
+
parts[0].location.to(parts[-1].location)
|
1510
|
+
end
|
1499
1511
|
|
1500
1512
|
HshPtn.new(
|
1501
1513
|
constant: constant,
|
1502
|
-
keywords: keywords,
|
1514
|
+
keywords: keywords || [],
|
1503
1515
|
keyword_rest: keyword_rest,
|
1504
|
-
location:
|
1516
|
+
location: location
|
1505
1517
|
)
|
1506
1518
|
end
|
1507
1519
|
|
@@ -2837,19 +2849,17 @@ module SyntaxTree
|
|
2837
2849
|
# parentheses they don't get reported as a paren node for some reason.
|
2838
2850
|
|
2839
2851
|
beginning = find_token(Kw, "not")
|
2840
|
-
ending = statement
|
2841
|
-
|
2842
|
-
range = beginning.location.end_char...statement.location.start_char
|
2843
|
-
paren = source[range].include?("(")
|
2852
|
+
ending = statement || beginning
|
2853
|
+
parentheses = source[beginning.location.end_char] == "("
|
2844
2854
|
|
2845
|
-
if
|
2855
|
+
if parentheses
|
2846
2856
|
find_token(LParen)
|
2847
2857
|
ending = find_token(RParen)
|
2848
2858
|
end
|
2849
2859
|
|
2850
2860
|
Not.new(
|
2851
2861
|
statement: statement,
|
2852
|
-
parentheses:
|
2862
|
+
parentheses: parentheses,
|
2853
2863
|
location: beginning.location.to(ending.location)
|
2854
2864
|
)
|
2855
2865
|
else
|
@@ -2981,7 +2991,7 @@ module SyntaxTree
|
|
2981
2991
|
# ) -> VarField
|
2982
2992
|
def on_var_field(value)
|
2983
2993
|
location =
|
2984
|
-
if value
|
2994
|
+
if value && value != :nil
|
2985
2995
|
value.location
|
2986
2996
|
else
|
2987
2997
|
# You can hit this pattern if you're assigning to a splat using
|
data/lib/syntax_tree/version.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.1.
|
4
|
+
version: 2.1.1
|
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-04-
|
11
|
+
date: 2022-04-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|