ast_transform 3.1.1 → 3.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fb38ad75ff6d31e4f8da1d1b272968b3d65393a3acaf92b914be2c0d35ebdb32
4
- data.tar.gz: f2621b3116184b0f7b7eb87a9a4b4af184f685e4399e5b52761b1deb1f54c998
3
+ metadata.gz: 4bd9891c7329570100d1f706978508d03249b188472557bbe2a6ffef3813ccf3
4
+ data.tar.gz: d2f1620ea7475a63a255c41085db71deb6716e3a28b0dd8a1970a46884a1d742
5
5
  SHA512:
6
- metadata.gz: 3ff9177f5bdd86e95af2406aeb675a53cd93917a63faa2fdf26bcfb12bc6365e415dbadb576247f7d134a2a36a7866d46cca17626351fb648f156379e3ba5473
7
- data.tar.gz: 054fe46ee27bc9cda5f18b163460f62a94c496cc3993407e79a3592079d3011c56c78d300db0639d685749e47a704a0a3e6d3a1915fbcbd044de7a7b6a6c173b
6
+ metadata.gz: 1212107491dedeffe09b7d1f54303cf784aef2ccc3c9da16b9fe81d1f98c377e32bf14a484d4089b3dc16d9b9087d30a1d6b0a5a5caeb61ca965c88cd2218902
7
+ data.tar.gz: 0af32ba36db47e621cb661879763b1aa8092b114f0f8fe49ba50bcf49612da879a99ad873523f9f9d75d704a508d9303f73bd8d09f259d78c0aa85497a934097
data/CHANGELOG.md CHANGED
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [Unreleased]
8
+
9
+ ## [3.2.0] - 2026-11-08
10
+ ### Fixed
11
+ - One-parameter blocks no longer auto-splat their argument after transformation: `[[1, 2]].each { |a| }` emitted as `{ |a,| }` (the trailing-comma form), so `a` saw `1` instead of `[1, 2]`. The parser builder opted into `emit_kwargs` alone and otherwise produced the parser gem's legacy AST, in which a lone `s(:arg)` under `s(:args)` is what Unparser (written against the modern AST) reads as `|a,|`. Lambdas were affected the same way (`->(a) {}` emitted as `lambda { |a,| }`), and forwarding defs lost their header (`def m(...)` emitted as `def m`). (#21)
12
+
13
+ ### Changed
14
+ - `ASTTransform::KwargsBuilder` is now `ASTTransform::ModernBuilder` and opts into the parser gem's full `modernize` set rather than `emit_kwargs` alone. Transformations and analyses now see the modern node shapes: `s(:args, s(:procarg0, s(:arg, :a)))` for `|a|`, `:index`/`:indexasgn` for `foo[1]`/`foo[1] = 2` (previously `:send` with `:[]`/`:[]=`), `:lambda` for `->() {}` (previously `s(:send, nil, :lambda)`), `s(:args, s(:forward_arg))` for `def m(...)` (previously `:forward_args`), and `s(:__ENCODING__)` for `__ENCODING__` (previously the `Encoding` constant). `:kwargs` and `:match_pattern`/`:match_pattern_p` are unchanged: the former was already on, and Prism's translation emits the latter regardless of the flag. Passes that pattern-match the legacy shapes must update.
15
+
16
+ ## [3.1.1] - 2026-08-03
17
+ ### Fixed
18
+ - Line-aligned emission no longer packs displaced statements or container closers onto a heredoc terminator line. Unparser legitimately falls back to `<<-HEREDOC` emission when a dstr fails its quoted-string round-trip; the emitter now treats such a render as line-terminal and opens a fresh line instead, trading one line of alignment for valid Ruby. (#16)
19
+
7
20
  ## [3.1.0] - 2026-07-29
8
21
  ### Added
9
22
  - Analysis passes: `ASTTransform::AbstractAnalysis`, the read-only counterpart of `AbstractTransformation`. Both leaves share the extracted traversal core `ASTTransform::AbstractProcessor` (sealed `process`, `process_node` hook, thunk descent, `TransformationHelper`) and differ only in what `run` returns — the rebuilt tree for transformations, the analysis instance (result readers) for analyses.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ast_transform (3.1.1)
4
+ ast_transform (3.2.0)
5
5
  parser (>= 3.3)
6
6
  prism (>= 1.5)
7
7
  unparser (>= 0.8)
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "prism/translation/parser"
4
+
5
+ module ASTTransform
6
+ # The framework's parser builder: the stock builder with the parser gem's `modernize` opt-ins, which produce the
7
+ # modern AST (`:procarg0`, `:index`/`:indexasgn`, `:lambda`, `:forward_args`, `:kwargs`, `:match_pattern`, ...).
8
+ #
9
+ # Unparser is written against the modern AST, so parsing in the gem's legacy compatibility shapes changes meaning
10
+ # at emission. Two examples that matter to any transformed source:
11
+ #
12
+ # - Block parameters: in the modern AST `{ |a| }` is `s(:args, s(:procarg0, s(:arg, :a)))`, and a lone bare
13
+ # `s(:arg)` means the trailing-comma form `{ |a,| }`. The legacy shape for `{ |a| }` is that lone `s(:arg)`, so
14
+ # Unparser emitted `|a,|` and every one-parameter block auto-splatted its argument (#21).
15
+ # - Keyword arguments: with `emit_kwargs` off, `foo(bar: 1)` and `foo({ bar: 1 })` both parse as :hash; Unparser
16
+ # braces :hash and not :kwargs, and Ruby 3+ treats the two as different calls.
17
+ #
18
+ # The flags are class-level ivars, so modernizing here opts in this builder only — the global
19
+ # Parser::Builders::Default stays untouched.
20
+ #
21
+ # NOTE: parsed nodes deliberately stay plain Parser::AST::Node. Custom node classes exist only for registered
22
+ # custom types (see ASTTransform::Node), which are IR and never reach Unparser: AST::Node#eql? compares class, and
23
+ # Unparser verifies dynamic-string emission by re-parsing and comparing eql? against the freshly parsed
24
+ # (plain-class) node — custom-class nodes of standard types would fail that verification.
25
+ class ModernBuilder < Prism::Translation::Parser::Builder
26
+ modernize
27
+ end
28
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "prism"
4
4
  require "prism/translation/parser"
5
- require "ast_transform/kwargs_builder"
5
+ require "ast_transform/modern_builder"
6
6
 
7
7
  module ASTTransform
8
8
  # Owns source → AST parsing: Prism's C parser through its whitequark translation layer, so every consumer gets the
@@ -11,10 +11,10 @@ module ASTTransform
11
11
  class SourceParser
12
12
  # Constructs a new SourceParser instance.
13
13
  #
14
- # KwargsBuilder is a required implementation detail, not an injection seam: the framework's emission depends
15
- # on the kwargs/hash distinction it preserves, so every parse goes through it.
14
+ # ModernBuilder is a required implementation detail, not an injection seam: the framework's emission depends
15
+ # on the modern AST shapes it produces, so every parse goes through it.
16
16
  def initialize
17
- @builder = KwargsBuilder.new
17
+ @builder = ModernBuilder.new
18
18
  end
19
19
 
20
20
  # Parses the given +source+.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ASTTransform
4
- VERSION = "3.1.1"
4
+ VERSION = "3.2.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ast_transform
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.1
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean-Philippe Duchesne
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-08-03 00:00:00.000000000 Z
11
+ date: 2026-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -87,9 +87,9 @@ files:
87
87
  - lib/ast_transform/instruction_sequence/bootsnap_mixin.rb
88
88
  - lib/ast_transform/instruction_sequence/mixin.rb
89
89
  - lib/ast_transform/instruction_sequence/mixin_utils.rb
90
- - lib/ast_transform/kwargs_builder.rb
91
90
  - lib/ast_transform/layout.rb
92
91
  - lib/ast_transform/line_aligned_emitter.rb
92
+ - lib/ast_transform/modern_builder.rb
93
93
  - lib/ast_transform/node.rb
94
94
  - lib/ast_transform/source_parser.rb
95
95
  - lib/ast_transform/statement_renderer.rb
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "prism/translation/parser"
4
-
5
- module ASTTransform
6
- # The framework's parser builder: the stock builder with the parser gem's `emit_kwargs` opt-in, which
7
- # distinguishes keyword arguments from hash literals in the AST.
8
- #
9
- # With the flag off (the gem's compatibility default) both `foo(bar: 1)` and `foo({ bar: 1 })` emit :hash nodes.
10
- # Unparser uses the node type to decide whether to emit braces: :hash gets `{}`, :kwargs does not. Since Ruby 3.0+
11
- # treats these as semantically different (strict keyword/positional separation), the AST must preserve the
12
- # distinction. `emit_kwargs` rewrites at the call sites where kwargs semantics live (method calls, index,
13
- # super/yield); the flag is a class-level ivar, so setting it here opts in this builder only — the global
14
- # Parser::Builders::Default stays untouched.
15
- #
16
- # NOTE: parsed nodes deliberately stay plain Parser::AST::Node. Custom node classes exist only for registered
17
- # custom types (see ASTTransform::Node), which are IR and never reach Unparser: AST::Node#eql? compares class, and
18
- # Unparser verifies dynamic-string emission by re-parsing and comparing eql? against the freshly parsed
19
- # (plain-class) node — custom-class nodes of standard types would fail that verification.
20
- class KwargsBuilder < Prism::Translation::Parser::Builder
21
- self.emit_kwargs = true
22
- end
23
- end