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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46b573afdda378e664e11b1f5acab2c89ce0fdd2c8b3d4c6400d74e133aaffc3
4
- data.tar.gz: 6be0570ce471fe3f34c53730d7095d9b81be5b7e3e2e84ac5724ba95d7ac7362
3
+ metadata.gz: bd341a51ce36b230703bfbe86078641e7670058a3e41d0dbb125548c0821a65a
4
+ data.tar.gz: 9ebdca60f2956e24f83a58749266c89eb0eed88003a06699432956a0ecfa735a
5
5
  SHA512:
6
- metadata.gz: 36236536a1dda5e6e2907b82c383b74f207f5e2b64f282490cf26161d62d748d1cdf51b68c393cd60f1777d2c5434c294ad2e243f2575faae34c42ac44155f76
7
- data.tar.gz: 5c2e0ee682e5847287cee5a6ca4357c51e4172bacf7aa98b780e427fb7d0912b6bd829bbf6236baa294a919be9be5730d8c7e74b27a0ca630a29a91c37540324
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.0...HEAD
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- syntax_tree (2.1.0)
4
+ syntax_tree (2.1.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
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.
@@ -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
- parent = q.parent
4550
- if PATTERNS.include?(parent.class)
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
- q.format(value) if value
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
 
@@ -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 = message
765
- ending = operator if message == :call
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].flatten(2).compact
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: parts[0].location.to(parts[-1].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 paren
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: paren,
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SyntaxTree
4
- VERSION = "2.1.0"
4
+ VERSION = "2.1.1"
5
5
  end
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.0
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-13 00:00:00.000000000 Z
11
+ date: 2022-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler