syntax_tree 2.1.0 → 2.1.1
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/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
|