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 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