diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5e3a87fdf8d..aef93c517f6 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,38 +9,15 @@ updates: schedule: interval: 'weekly' - package-ecosystem: 'bundler' - directory: '/gemfiles/2.7' - schedule: - interval: 'weekly' - - package-ecosystem: 'bundler' - directory: '/gemfiles/3.0' - schedule: - interval: 'weekly' - - package-ecosystem: 'bundler' - directory: '/gemfiles/3.1' - schedule: - interval: 'weekly' - - package-ecosystem: 'bundler' - directory: '/gemfiles/3.2' - schedule: - interval: 'weekly' - - package-ecosystem: 'bundler' - directory: '/gemfiles/3.3' - schedule: - interval: 'weekly' - - package-ecosystem: 'bundler' - directory: '/gemfiles/3.4' - schedule: - interval: 'weekly' - - package-ecosystem: 'bundler' - directory: '/gemfiles/jruby' - schedule: - interval: 'weekly' - - package-ecosystem: 'bundler' - directory: '/gemfiles/truffleruby' - schedule: - interval: 'weekly' - - package-ecosystem: 'bundler' - directory: '/gemfiles/typecheck' + directories: + - '/gemfiles/2.7' + - '/gemfiles/3.0' + - '/gemfiles/3.1' + - '/gemfiles/3.2' + - '/gemfiles/3.3' + - '/gemfiles/3.4' + - '/gemfiles/jruby' + - '/gemfiles/truffleruby' + - '/gemfiles/typecheck' schedule: interval: 'weekly' diff --git a/.github/workflows/cpp-bindings.yml b/.github/workflows/cpp-bindings.yml new file mode 100644 index 00000000000..12176470a57 --- /dev/null +++ b/.github/workflows/cpp-bindings.yml @@ -0,0 +1,33 @@ +name: C++ bindings + +on: + push: + paths: + - ".github/workflows/cpp-bindings.yml" + - "include/" + - "src/" + - "cpp/" + - "*akefile*" + branches: + - main + pull_request: + +jobs: + test: + name: test + strategy: + fail-fast: false + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: head + bundler-cache: true + - name: Compile prism + run: bundle exec rake compile + - name: Compile C++ + run: g++ -o ./cpp_test cpp/test.cpp build/static/*.o build/static/util/*.o -Iinclude + - name: Run C++ + run: ./cpp_test diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index fb0b78970dd..d5774705faf 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -20,6 +20,10 @@ jobs: with: ruby-version: "3.3" bundler-cache: true + - name: Set up Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: "1.71.1" - name: Install doxygen and dependencies run: | sudo apt-get update @@ -33,3 +37,8 @@ jobs: - name: Check Java coverage run: javadoc -Xdoclint:all,-missing -d ../doc/java -subpackages * working-directory: java + - name: Generate Rust documentation + run: | + bundle exec rake cargo:build + cargo doc --no-deps --target-dir ../doc/rust + working-directory: rust diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml index 75893901904..14c368c737e 100644 --- a/.github/workflows/github-pages.yml +++ b/.github/workflows/github-pages.yml @@ -33,6 +33,10 @@ jobs: with: ruby-version: "3.2" bundler-cache: true + - name: Set up Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: "1.71.1" - name: Install doxygen and dependencies run: | sudo apt-get update @@ -49,6 +53,11 @@ jobs: - name: Build with JavaDoc run: javadoc -Xdoclint:all,-missing -d ../doc/java -subpackages * working-directory: java + - name: Build with rustdoc + run: | + bundle exec rake cargo:build + cargo doc --no-deps --target-dir ../doc/rust + working-directory: rust - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 07453084b3f..ff6b924fddf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -49,8 +49,8 @@ jobs: with: ruby-version: "3.3" bundler-cache: true - # - name: Check Sorbet - # run: bundle exec rake typecheck:tapioca typecheck:sorbet + - name: Check Sorbet + run: bundle exec rake typecheck:tapioca typecheck:sorbet - name: Check Steep run: bundle exec rake typecheck:steep - name: Check field kinds @@ -215,16 +215,16 @@ jobs: uses: actions/cache@v4 id: cache-valgrind with: - path: valgrind-3.20.0 - key: ${{ runner.os }}-valgrind-3.20.0 + path: valgrind-3.23.0 + key: ${{ runner.os }}-valgrind-3.23.0 - name: Download valgrind if: steps.cache-valgrind.outputs.cache-hit != 'true' run: | - wget https://sourceware.org/pub/valgrind/valgrind-3.20.0.tar.bz2 - tar xf valgrind-3.20.0.tar.bz2 + wget https://sourceware.org/pub/valgrind/valgrind-3.23.0.tar.bz2 + tar xf valgrind-3.23.0.tar.bz2 - name: Install valgrind run: | - cd valgrind-3.20.0 + cd valgrind-3.23.0 ./configure make sudo make install @@ -244,7 +244,8 @@ jobs: with: ruby-version: head bundler-cache: true - - run: bundle exec rake build + - run: bundle config --local frozen false + - run: bundle exec rake build:dev - uses: actions/upload-artifact@v4 with: name: gem-package diff --git a/.github/workflows/rust-bindings.yml b/.github/workflows/rust-bindings.yml index 982767a0277..85e766adb81 100644 --- a/.github/workflows/rust-bindings.yml +++ b/.github/workflows/rust-bindings.yml @@ -86,7 +86,7 @@ jobs: strategy: fail-fast: false matrix: - sanitizer: [leak, address] + sanitizer: [address] steps: - uses: actions/checkout@v4 - name: Set up Ruby diff --git a/.gitignore b/.gitignore index 4893fc368b8..1122263535c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ /doc/c/ /doc/java/ /doc/rb/ +/doc/rust/ /pkg/ /spec/reports/ /top-100-gems/ @@ -64,6 +65,7 @@ out.svg /sig/prism/node.rbs /sig/prism/visitor.rbs /sig/prism/_private/dot_visitor.rbs +/rbi/prism/dsl.rbi /rbi/prism/node.rbi /rbi/prism/visitor.rbi diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 51e30a630da..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: ruby - -dist: jammy - -matrix: - include: - - arch: arm64 - - arch: ppc64le - - arch: s390x - fast_finish: true - -before_install: - - sudo apt update -yq - - sudo apt -yq install gcc-11 - - gcc-11 --version - -before_script: - # Enable the verbose option in mkmf.rb to print the compiling commands. - - export MAKEFLAGS="V=1 CC=gcc-11" diff --git a/CHANGELOG.md b/CHANGELOG.md index 862d1a7e26c..3d198e79b11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,112 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [Unreleased] +## [1.2.0] - 2024-10-10 + +### Added + +- Introduce `Prism::CodeUnitsCache`. + +### Changed + +- Properly handle lexing global variables that begin with `$-`. +- Properly reject invalid multi writes within parentheses. +- Fix unary `*` binding power. +- Set `contains_keywords` flag for implicit `gets` calls when `-p` is used. +- Properly reject invalid non-associative operator patterns. +- Do not warn about unused variables declared on negative lines. + +## [1.1.0] - 2024-10-02 + +### Added + +- Explicitly type each child node field in the Ruby API. +- Add the `main_script` option to the parse APIs, which controls whether or not shebangs are considered. +- Add the `partial_script` options to the parse APIs, which controls whether or not jumps that would otherwise be considered invalid are allowed. This is useful for parsing things like ERB sources, where you know it will be evaluated in a different context. Note that this functionality is replacing the previous idiom of passing in a list of scopes to indicate an `eval` context, because that behavior has changed upstream in `ruby/ruby`. +- Add `ArgumentsNode#contains_multiple_splats?`. +- Add `ArgumentsNode#contains_forwarding?`. +- Accept all valid Ruby versions for the `version` option on parse APIs. +- Accept version shorthands like `"3.3"` and `"3.4"` for the `version` option on parse APIs. +- Support a max depth to protect against malicious payloads without hitting the stack limit. + +### Changed + +- Fix some token incompatibilities in the `parser` translation. +- Fix up parsing tempfiles on Windows. +- Fix up handling UTF-8 characters in file paths on Windows. +- Do not warn for a `\r` at the end of a shebang on Windows. +- Properly handle erroring for parsing a directory on Windows. +- When a numbered reference is out of range, warn instead of raise. +- Allow returns in default parameter values. +- Reject many more invalid syntax patterns. + +## [1.0.0] - 2024-08-28 + +### Added + +- Add `Node#breadth_first_search`. +- Add `Node#node_id`. +- Add `ArgumentsNode#contains_splat?`. +- Passing the special value `false` for the `encoding` option tells Prism to ignore magic encoding comments. +- Expose flags on every node type (allows checking static literal and newline). +- Implement mismatched indentation warning. +- Add C API for receiving a callback when parsing shebangs with additional flags. + +### Changed + +- **BREAKING**: Some fields are renamed that had illogical names. The previous names all now emit deprecation warnings. + - `CaseMatchNode#consequent` was renamed to `CaseMatchNode#else_clause` + - `CaseNode#consequent` was renamed to `CaseNode#else_clause` + - `IfNode#consequent` was renamed to `IfNode#subsequent` + - `RescueNode#consequent` was renamed to `RescueNode#subsequent` + - `UnlessNode#consequent` was renamed to `UnlessNode#else_clause` +- Block exits are now allowed in loop predicates (e.g., `while _ && break do end`). +- Multi-writes are now disallowed when not at the statement level. +- Ensure that range operators are non-associative. +- (JavaScript) Correctly deserialize encoded strings. +- Properly support parsing regular expressions in extended mode. +- Use gmake on FreeBSD. +- Parsing streams now handles NUL bytes in the middle of the stream. +- Properly detect invalid returns. + +## [0.30.0] - 2024-06-07 + +### Added + +- More correctly raise mixed encoding errors. +- Implement ambiguous binary operator warning. +- Fix up regexp escapes with control and meta characters. +- Fix up support for the `it` implicit local variable. +- Heredoc identifiers now properly disallow CLRF. +- Errors added for void value expressions in begin clauses. +- Many updates to more closely match the `parser` gem in parser translation. +- Many errors added for invalid regular expressions. + +### Changed + +- Handle parser translation missing the `parser` gem. +- Handle ruby_parser translation missing the `ruby_parser` gem. +- Various error messages have been updated to more closely match CRuby. +- `RationalNode` now has a `numerator` and `denominator` field instead of a `numeric` field. For the Ruby API we provide a `RationalNode#numeric` method for backwards-compatibility. + +## [0.29.0] - 2024-05-10 + +### Added + +- Added `Prism::CallNode#full_message_loc`, which gives the location including the `=` if there is one. +- A warning for when `# shareable_constant_value` is not used on its own line. +- An error for invalid implicit local variable writes. +- Implicit hash patterns in array patterns are disallowed. +- We now validate that Unicode escape sequences are not surrogates. + +### Changed + +- All fields named `operator` have been renamed to `binary_operator` for `*OperatorWriteNode` nodes. This is to make it easier to provide C++ support. In the Ruby API, the old fields are aliased to the new fields with a deprecation warning. +- Many updated error messages to more closely match CRuby. +- We ensure keyword parameters do not end in `!` or `?`. +- Fixed some escaping in string literals with control sequences and hex escapes. +- Fix a bug with RBS types when used outside the `ruby/prism` codebase. + ## [0.28.0] - 2024-05-03 ### Added @@ -500,7 +606,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - 🎉 Initial release! 🎉 -[unreleased]: https://github.com/ruby/prism/compare/v0.28.0...HEAD +[unreleased]: https://github.com/ruby/prism/compare/v1.2.0...HEAD +[1.2.0]: https://github.com/ruby/prism/compare/v1.1.0...v1.2.0 +[1.1.0]: https://github.com/ruby/prism/compare/v1.0.0...v1.1.0 +[1.0.0]: https://github.com/ruby/prism/compare/v0.30.0...v1.0.0 +[0.30.0]: https://github.com/ruby/prism/compare/v0.29.0...v0.30.0 +[0.29.0]: https://github.com/ruby/prism/compare/v0.28.0...v0.29.0 [0.28.0]: https://github.com/ruby/prism/compare/v0.27.0...v0.28.0 [0.27.0]: https://github.com/ruby/prism/compare/v0.26.0...v0.27.0 [0.26.0]: https://github.com/ruby/prism/compare/v0.25.0...v0.26.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8858d633da7..8e6fa3b85d2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,10 +10,6 @@ The discussions page on the GitHub repository are open. If you have a question o If you want to contribute code, please first open or contribute to a discussion. A lot of the project is in flux, and we want to make sure that you are contributing to the right place. Once you have a discussion going, you can open a pull request with your changes. We will review your code and get it merged in. -### Ruby Features - -Pattern matching and endless method definitions should be avoided as long as the latest TruffleRuby release does not support it. - ## Tests We could always use more tests! One of the biggest challenges of this project is building up a big test suite. If you want to contribute tests, feel free to open a pull request. These will get merged in as soon as possible. diff --git a/Gemfile b/Gemfile index 0dfa52d9bf9..c6977319e25 100644 --- a/Gemfile +++ b/Gemfile @@ -4,18 +4,16 @@ source "https://rubygems.org" gemspec +gem "benchmark-ips" gem "rake" gem "rake-compiler" gem "test-unit" -# Some gems we don't want to install on JRuby or TruffleRuby. -platforms = %i[mri mswin mingw x64_mingw] - -gem "ffi", platform: platforms -gem "parser", platform: platforms -gem "ruby_parser", platform: platforms -gem "benchmark-ips" +platforms :mri, :mswin, :mingw, :x64_mingw do + gem "ffi" + gem "parser" + gem "ruby_memcheck" + gem "ruby_parser" +end -group :memcheck do - gem "ruby_memcheck", platform: platforms -end +gem "onigmo", platforms: :ruby diff --git a/Gemfile.lock b/Gemfile.lock index 8050816b3e1..a4bf9f8ffad 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,27 +1,28 @@ PATH remote: . specs: - prism (0.28.0) + prism (1.2.0) GEM remote: https://rubygems.org/ specs: ast (2.4.2) benchmark-ips (2.13.0) - ffi (1.16.3) - mini_portile2 (2.8.5) - nokogiri (1.16.2) + ffi (1.17.0) + mini_portile2 (2.8.7) + nokogiri (1.16.6) mini_portile2 (~> 2.8.2) racc (~> 1.4) - parser (3.3.0.5) + onigmo (0.1.0) + parser (3.3.3.0) ast (~> 2.4.1) racc power_assert (2.0.3) - racc (1.7.3) - rake (13.1.0) + racc (1.8.0) + rake (13.2.1) rake-compiler (1.2.7) rake - ruby_memcheck (2.3.0) + ruby_memcheck (3.0.0) nokogiri ruby_parser (3.21.0) racc (~> 1.5) @@ -36,6 +37,7 @@ PLATFORMS DEPENDENCIES benchmark-ips ffi + onigmo parser prism! rake diff --git a/README.md b/README.md index ad991c8d28f..b601ee52628 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,8 @@ The repository contains the infrastructure for both a shared library (libprism) ├── rust │   ├── ruby-prism Rustified crate for the shared library │   └── ruby-prism-sys FFI binding for Rust +├── sample +│ └── prism Sample code that uses the Ruby API for documentation purposes ├── sig RBS type signatures for the Ruby library ├── src │   ├── util various utility files @@ -119,6 +121,7 @@ Prism has been integrated into the majority of Ruby runtimes, many libraries, an ### Libraries * [dispersion](https://github.com/joeldrapper/dispersion) +* [minifyrb](https://github.com/koic/minifyrb) * [packwerk](https://github.com/Shopify/packwerk/pull/388) (via parser translator) * [rbi](https://github.com/Shopify/rbi) * [rails](https://github.com/rails/rails) @@ -131,6 +134,7 @@ Prism has been integrated into the majority of Ruby runtimes, many libraries, an * [smart_todo](https://github.com/Shopify/smart_todo/pull/69) * [sorbet-eraser](https://github.com/kddnewton/sorbet-eraser/pull/25) * [synvert](https://github.com/xinminlabs/synvert-core-ruby) +* [typeprof](https://github.com/ruby/typeprof) ### Applications diff --git a/Rakefile b/Rakefile index 957126386e4..7a5e5370392 100644 --- a/Rakefile +++ b/Rakefile @@ -10,7 +10,7 @@ require_relative "templates/template" desc "Generate all ERB template based files" task templates: Prism::Template::TEMPLATES -make = RUBY_PLATFORM.include?("openbsd") ? "gmake" : "make" +make = RUBY_PLATFORM.match?(/openbsd|freebsd/) ? "gmake" : "make" task(make: :templates) { sh(make) } task(make_no_debug: :templates) { sh("#{make} all-no-debug") } task(make_minimal: :templates) { sh("#{make} minimal") } @@ -59,3 +59,17 @@ Prism::Template::TEMPLATES.each do |filepath| Prism::Template.render(t.name) end end + +namespace :build do + task :dev_version_set do + filepath = File.expand_path("prism.gemspec", __dir__) + File.write(filepath, File.read(filepath).sub(/spec\.version = ".+?"/, %Q{spec.version = "9999.9.9"})) + end + + task :dev_version_clear do + sh "git checkout -- prism.gemspec Gemfile.lock" + end + + desc "Build a development version of the gem" + task dev: ["build:dev_version_set", "build", "build:dev_version_clear"] +end diff --git a/Steepfile b/Steepfile index e710262e719..83e877e0a5b 100644 --- a/Steepfile +++ b/Steepfile @@ -8,7 +8,6 @@ target :lib do check "lib" # TODO: Type-checking these files is still WIP - ignore "lib/prism/debug.rb" ignore "lib/prism/desugar_compiler.rb" ignore "lib/prism/lex_compat.rb" ignore "lib/prism/serialize.rb" diff --git a/bin/prism b/bin/prism index b50d6658ef8..d2dfd391dd2 100755 --- a/bin/prism +++ b/bin/prism @@ -13,9 +13,9 @@ module Prism when "console" then console when "dot" then dot(argv) when "encoding" then encoding(argv) + when "error" then error(argv) when "lex" then lex(argv) when "locals" then locals(argv) - when "memsize" then memsize when "parse" then parse(argv) when "parser" then parser(argv) when "ripper" then ripper(argv) @@ -28,9 +28,9 @@ module Prism bin/prism console bin/prism dot [source] bin/prism encoding [encoding] + bin/prism error [name] [source] bin/prism lex [source] bin/prism locals [source] - bin/prism memsize bin/prism parse [source] bin/prism parser [source] bin/prism ripper [source] @@ -98,7 +98,7 @@ module Prism ["3.3.0", ["3.3"]], ["3.4.0-dev", ["3.4", "typecheck"]], ["jruby-9.4.5.0", ["jruby"]], - ["truffleruby-24.0.0", ["truffleruby"]] + ["truffleruby-24.1.0", ["truffleruby"]] ].each do |ruby_version, gemfiles| gemfiles.each do |gemfile| system( @@ -107,6 +107,8 @@ module Prism exception: true, chdir: File.expand_path("../", __dir__) ) + rescue RuntimeError => error + warn("\e[31;m#{ruby_version} (#{gemfile}): #{error.message}\e[m") end end end @@ -157,6 +159,38 @@ module Prism unicode_lists(found) if found == Encoding::UTF_8 || found == Encoding::UTF8_MAC end + # bin/prism error [name] [source] + def error(argv) + name = argv.shift + + source = nil + filepath = File.expand_path("../test/prism/errors/#{name}.txt", __dir__) + + if argv.empty? + raise "Expected #{filepath} to exist" unless File.file?(filepath) + + source = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8) + source = source.lines.grep_v(/^\s*\^/).join.gsub(/\n*\z/, "") + else + if File.file?(filepath) + counter = 1 + + begin + current = "#{File.dirname(filepath)}/#{File.basename(filepath, ".txt")}_#{counter += 1}.txt" + end while File.file?(current) + + filepath = current + end + + source, _ = read_source(argv) + end + + result = Prism.parse(source) + raise "Expected #{source.inspect} to have errors" if result.success? + + File.write(filepath, result.errors_format) + end + # bin/prism lex [source] def lex(argv) source, filepath = read_source(argv) @@ -212,7 +246,7 @@ module Prism # bin/prism locals [source] def locals(argv) - source, filepath = read_source(argv) + source, _ = read_source(argv) puts "CRuby:" p Debug.cruby_locals(source) @@ -244,35 +278,6 @@ module Prism end end - # bin/prism memsize - def memsize - require "yaml" - - filepath = File.expand_path("../config.yml", __dir__) - results = - YAML.load_file(filepath).fetch("nodes").map do |node| - [ - node["name"], - node.fetch("fields", []).sum do |field| - case field["type"] - when "uint8" then 1 - when "uint32", "constant", "constant?" then 4 - when "node", "node?", "double" then 8 - when "location", "location?" then 16 - when "node[]", "string", "token", "token?", "constant[]" then 24 - when "integer" then 32 - when "flags" then 0 - else raise "Unknown type: #{field["type"]}" - end - end - ] - end - - results.sort_by(&:last).reverse_each do |name, size| - puts "#{name}: #{size}" - end - end - # bin/prism parser [source] def parser(argv) require "parser/ruby34" @@ -291,7 +296,7 @@ module Prism # bin/prism ripper [source] def ripper(argv) require "ripper" - source, filepath = read_source(argv) + source, _ = read_source(argv) ripper = Ripper.sexp_raw(source) prism = Prism::Translation::Ripper.sexp_raw(source) @@ -397,14 +402,17 @@ module Prism # Parse the source code indicated by the command-line arguments. def parse_source(argv) + command_line = +"" + command_line << argv.shift[1] while argv.first&.match?(/^-[alnpx]$/) + case argv.first when "-e" - argv.shift - Prism.parse(argv.shift, command_line: "e") + command_line << argv.shift[1] + Prism.parse(argv.shift, command_line: command_line) when nil - Prism.parse_file("test.rb") + Prism.parse_file("test.rb", command_line: command_line) else - Prism.parse_file(argv.shift) + Prism.parse_file(argv.shift, command_line: command_line) end end diff --git a/config.yml b/config.yml index 4fc4aa8e6aa..181180c9fa4 100644 --- a/config.yml +++ b/config.yml @@ -7,13 +7,15 @@ errors: - ARGUMENT_BARE_HASH - ARGUMENT_BLOCK_FORWARDING - ARGUMENT_BLOCK_MULTI + - ARGUMENT_CONFLICT_AMPERSAND + - ARGUMENT_CONFLICT_STAR + - ARGUMENT_CONFLICT_STAR_STAR - ARGUMENT_FORMAL_CLASS - ARGUMENT_FORMAL_CONSTANT - ARGUMENT_FORMAL_GLOBAL - ARGUMENT_FORMAL_IVAR - ARGUMENT_FORWARDING_UNBOUND - - ARGUMENT_IN - - ARGUMENT_NO_FORWARDING_AMP + - ARGUMENT_NO_FORWARDING_AMPERSAND - ARGUMENT_NO_FORWARDING_ELLIPSES - ARGUMENT_NO_FORWARDING_STAR - ARGUMENT_NO_FORWARDING_STAR_STAR @@ -78,8 +80,10 @@ errors: - ESCAPE_INVALID_META_REPEAT - ESCAPE_INVALID_UNICODE - ESCAPE_INVALID_UNICODE_CM_FLAGS + - ESCAPE_INVALID_UNICODE_LIST - ESCAPE_INVALID_UNICODE_LITERAL - ESCAPE_INVALID_UNICODE_LONG + - ESCAPE_INVALID_UNICODE_SHORT - ESCAPE_INVALID_UNICODE_TERM - EXPECT_ARGUMENT - EXPECT_EOL_AFTER_STATEMENT @@ -94,13 +98,16 @@ errors: - EXPECT_EXPRESSION_AFTER_SPLAT - EXPECT_EXPRESSION_AFTER_SPLAT_HASH - EXPECT_EXPRESSION_AFTER_STAR + - EXPECT_FOR_DELIMITER - EXPECT_IDENT_REQ_PARAMETER + - EXPECT_IN_DELIMITER - EXPECT_LPAREN_REQ_PARAMETER - EXPECT_MESSAGE - EXPECT_RBRACKET - EXPECT_RPAREN - EXPECT_RPAREN_AFTER_MULTI - EXPECT_RPAREN_REQ_PARAMETER + - EXPECT_SINGLETON_CLASS_DELIMITER - EXPECT_STRING_CONTENT - EXPECT_WHEN_DELIMITER - EXPRESSION_BARE_HASH @@ -110,6 +117,7 @@ errors: - EXPRESSION_NOT_WRITABLE_FILE - EXPRESSION_NOT_WRITABLE_LINE - EXPRESSION_NOT_WRITABLE_NIL + - EXPRESSION_NOT_WRITABLE_NUMBERED - EXPRESSION_NOT_WRITABLE_SELF - EXPRESSION_NOT_WRITABLE_TRUE - FLOAT_PARSE @@ -133,7 +141,9 @@ errors: - INSTANCE_VARIABLE_BARE - INVALID_BLOCK_EXIT - INVALID_CHARACTER + - INVALID_COMMA - INVALID_ENCODING_MAGIC_COMMENT + - INVALID_ESCAPE_CHARACTER - INVALID_FLOAT_EXPONENT - INVALID_LOCAL_VARIABLE_READ - INVALID_LOCAL_VARIABLE_WRITE @@ -142,11 +152,13 @@ errors: - INVALID_MULTIBYTE_ESCAPE - INVALID_NUMBER_BINARY - INVALID_NUMBER_DECIMAL + - INVALID_NUMBER_FRACTION - INVALID_NUMBER_HEXADECIMAL - INVALID_NUMBER_OCTAL - INVALID_NUMBER_UNDERSCORE_INNER - INVALID_NUMBER_UNDERSCORE_TRAILING - INVALID_PERCENT + - INVALID_PERCENT_EOF - INVALID_PRINTABLE_CHARACTER - INVALID_RETRY_AFTER_ELSE - INVALID_RETRY_AFTER_ENSURE @@ -175,18 +187,22 @@ errors: - MODULE_TERM - MULTI_ASSIGN_MULTI_SPLATS - MULTI_ASSIGN_UNEXPECTED_REST + - NESTING_TOO_DEEP - NO_LOCAL_VARIABLE + - NON_ASSOCIATIVE_OPERATOR - NOT_EXPRESSION - NUMBER_LITERAL_UNDERSCORE + - NUMBERED_PARAMETER_INNER_BLOCK - NUMBERED_PARAMETER_IT - NUMBERED_PARAMETER_ORDINARY - - NUMBERED_PARAMETER_OUTER_SCOPE + - NUMBERED_PARAMETER_OUTER_BLOCK - OPERATOR_MULTI_ASSIGN - OPERATOR_WRITE_ARGUMENTS - OPERATOR_WRITE_BLOCK - PARAMETER_ASSOC_SPLAT_MULTI - PARAMETER_BLOCK_MULTI - PARAMETER_CIRCULAR + - PARAMETER_FORWARDING_AFTER_REST - PARAMETER_METHOD_NAME - PARAMETER_NAME_DUPLICATED - PARAMETER_NO_DEFAULT @@ -196,8 +212,9 @@ errors: - PARAMETER_SPLAT_MULTI - PARAMETER_STAR - PARAMETER_UNEXPECTED_FWD - - PARAMETER_WILD_LOOSE_COMMA - PARAMETER_UNEXPECTED_NO_KW + - PARAMETER_WILD_LOOSE_COMMA + - PATTERN_ARRAY_MULTIPLE_RESTS - PATTERN_CAPTURE_DUPLICATE - PATTERN_EXPRESSION_AFTER_BRACKET - PATTERN_EXPRESSION_AFTER_COMMA @@ -209,8 +226,11 @@ errors: - PATTERN_EXPRESSION_AFTER_PIPE - PATTERN_EXPRESSION_AFTER_RANGE - PATTERN_EXPRESSION_AFTER_REST + - PATTERN_FIND_MISSING_INNER + - PATTERN_HASH_IMPLICIT - PATTERN_HASH_KEY - PATTERN_HASH_KEY_DUPLICATE + - PATTERN_HASH_KEY_INTERPOLATED - PATTERN_HASH_KEY_LABEL - PATTERN_HASH_KEY_LOCALS - PATTERN_IDENT_AFTER_HROCKET @@ -224,6 +244,7 @@ errors: - REGEXP_INCOMPAT_CHAR_ENCODING - REGEXP_INVALID_UNICODE_RANGE - REGEXP_NON_ESCAPED_MBC + - REGEXP_PARSE_ERROR - REGEXP_TERM - REGEXP_UNKNOWN_OPTIONS - REGEXP_UTF8_CHAR_NON_UTF8_REGEXP @@ -248,11 +269,15 @@ errors: - TERNARY_COLON - TERNARY_EXPRESSION_FALSE - TERNARY_EXPRESSION_TRUE + - UNARY_DISALLOWED - UNARY_RECEIVER - UNDEF_ARGUMENT - UNEXPECTED_BLOCK_ARGUMENT - UNEXPECTED_INDEX_BLOCK - UNEXPECTED_INDEX_KEYWORDS + - UNEXPECTED_LABEL + - UNEXPECTED_MULTI_WRITE + - UNEXPECTED_RANGE_OPERATOR - UNEXPECTED_SAFE_NAVIGATION - UNEXPECTED_TOKEN_CLOSE_CONTEXT - UNEXPECTED_TOKEN_IGNORE @@ -264,6 +289,7 @@ errors: - WRITE_TARGET_UNEXPECTED - XSTRING_TERM warnings: + - AMBIGUOUS_BINARY_OPERATOR - AMBIGUOUS_FIRST_ARGUMENT_MINUS - AMBIGUOUS_FIRST_ARGUMENT_PLUS - AMBIGUOUS_PREFIX_AMPERSAND @@ -279,13 +305,15 @@ warnings: - DUPLICATED_WHEN_CLAUSE - FLOAT_OUT_OF_RANGE - IGNORED_FROZEN_STRING_LITERAL + - INDENTATION_MISMATCH - INTEGER_IN_FLIP_FLOP - INVALID_CHARACTER + - INVALID_MAGIC_COMMENT_VALUE - INVALID_NUMBERED_REFERENCE - - INVALID_SHAREABLE_CONSTANT_VALUE - KEYWORD_EOL - LITERAL_IN_CONDITION_DEFAULT - LITERAL_IN_CONDITION_VERBOSE + - SHAREABLE_CONSTANT_VALUE_LINE - SHEBANG_CARRIAGE_RETURN - UNEXPECTED_CARRIAGE_RETURN - UNREACHABLE_STATEMENT @@ -624,10 +652,16 @@ tokens: flags: - name: ArgumentsNodeFlags values: + - name: CONTAINS_FORWARDING + comment: "if the arguments contain forwarding" - name: CONTAINS_KEYWORDS - comment: "if arguments contain keywords" + comment: "if the arguments contain keywords" - name: CONTAINS_KEYWORD_SPLAT - comment: "if arguments contain keyword splat" + comment: "if the arguments contain a keyword splat" + - name: CONTAINS_SPLAT + comment: "if the arguments contain a splat" + - name: CONTAINS_MULTIPLE_SPLATS + comment: "if the arguments contain multiple splats" comment: Flags for arguments nodes. - name: ArrayNodeFlags values: @@ -715,11 +749,6 @@ flags: - name: FORCED_US_ASCII_ENCODING comment: "internal bytes forced the encoding to US-ASCII" comment: Flags for regular expression and match last line nodes. - - name: ReturnNodeFlags - values: - - name: REDUNDANT - comment: "a return statement that is redundant because it is the last statement in a method" - comment: Flags for return nodes. - name: ShareableConstantNodeFlags values: - name: LITERAL @@ -754,15 +783,25 @@ nodes: fields: - name: new_name type: node + kind: + - GlobalVariableReadNode + - BackReferenceReadNode + - NumberedReferenceReadNode comment: | - Represents the new name of the global variable that can be used after aliasing. This can be either a global variable, a back reference, or a numbered reference. + Represents the new name of the global variable that can be used after aliasing. alias $foo $bar ^^^^ - name: old_name type: node + kind: + - GlobalVariableReadNode + - BackReferenceReadNode + - NumberedReferenceReadNode + - on error: SymbolNode # alias $a b + - on error: MissingNode # alias $a 42 comment: | - Represents the old name of the global variable that could be used before aliasing. This can be either a global variable, a back reference, or a numbered reference. + Represents the old name of the global variable that can be used before aliasing. alias $foo $bar ^^^^ @@ -782,8 +821,38 @@ nodes: fields: - name: new_name type: node + kind: + - SymbolNode + - InterpolatedSymbolNode + comment: | + Represents the new name of the method that will be aliased. + + alias foo bar + ^^^ + + alias :foo :bar + ^^^^ + + alias :"#{foo}" :"#{bar}" + ^^^^^^^^^ - name: old_name type: node + kind: + - SymbolNode + - InterpolatedSymbolNode + - on error: GlobalVariableReadNode # alias a $b + - on error: MissingNode # alias a 42 + comment: | + Represents the old name of the method that will be aliased. + + alias foo bar + ^^^ + + alias :foo :bar + ^^^^ + + alias :"#{foo}" :"#{bar}" + ^^^^^^^^^ - name: keyword_loc type: location comment: | @@ -795,10 +864,27 @@ nodes: fields: - name: left type: node + kind: pattern expression + comment: | + Represents the left side of the expression. + + foo => bar | baz + ^^^ - name: right type: node + kind: pattern expression + comment: | + Represents the right side of the expression. + + foo => bar | baz + ^^^ - name: operator_loc type: location + comment: | + Represents the alternation operator location. + + foo => bar | baz + ^ comment: | Represents an alternation pattern in pattern matching. @@ -808,6 +894,7 @@ nodes: fields: - name: left type: node + kind: non-void expression comment: | Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -818,8 +905,9 @@ nodes: ^ - name: right type: node + kind: Node comment: | - Represents the right side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + Represents the right side of the expression. left && right ^^^^^ @@ -839,24 +927,22 @@ nodes: left and right ^^^^^^^^^^^^^^ - name: ArgumentsNode + flags: ArgumentsNodeFlags fields: - - name: flags - type: flags - kind: ArgumentsNodeFlags - name: arguments type: node[] + kind: non-void expression comment: | Represents a set of arguments to a method or a keyword. return foo, bar, baz ^^^^^^^^^^^^^ - name: ArrayNode + flags: ArrayNodeFlags fields: - - name: flags - type: flags - kind: ArrayNodeFlags - name: elements type: node[] + kind: non-void expression comment: Represent the list of zero or more [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression) within the array. - name: opening_loc type: location? @@ -885,12 +971,18 @@ nodes: fields: - name: constant type: node? + kind: + - ConstantReadNode + - ConstantPathNode - name: requireds type: node[] + kind: pattern expression - name: rest type: node? + kind: pattern expression - name: posts type: node[] + kind: pattern expression - name: opening_loc type: location? - name: closing_loc @@ -916,6 +1008,7 @@ nodes: fields: - name: key type: node + kind: non-void expression comment: | The key of the association. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -929,6 +1022,7 @@ nodes: ^^^^^^^^^^ - name: value type: node + kind: non-void expression comment: | The value of the association, if present. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -953,6 +1047,7 @@ nodes: fields: - name: value type: node? + kind: non-void expression comment: | The value to be splatted, if present. Will be missing when keyword rest argument forwarding is used. @@ -1015,18 +1110,17 @@ nodes: fields: - name: expression type: node? + kind: non-void expression - name: operator_loc type: location comment: | - Represents block method arguments. + Represents a block argument using `&`. bar(&args) ^^^^^^^^^^ - name: BlockLocalVariableNode + flags: ParameterFlags fields: - - name: flags - type: flags - kind: ParameterFlags - name: name type: constant comment: | @@ -1040,8 +1134,15 @@ nodes: type: constant[] - name: parameters type: node? + kind: + - BlockParametersNode + - NumberedParametersNode + - ItParametersNode - name: body type: node? + kind: + - StatementsNode + - BeginNode - name: opening_loc type: location - name: closing_loc @@ -1052,10 +1153,8 @@ nodes: [1, 2, 3].each { |i| puts x } ^^^^^^^^^^^^^^ - name: BlockParameterNode + flags: ParameterFlags fields: - - name: flags - type: flags - kind: ParameterFlags - name: name type: constant? - name: name_loc @@ -1063,7 +1162,7 @@ nodes: - name: operator_loc type: location comment: | - Represents a block parameter to a method, block, or lambda definition. + Represents a block parameter of a method, block, or lambda definition. def a(&b) ^^ @@ -1112,12 +1211,11 @@ nodes: break foo ^^^^^^^^^ - name: CallAndWriteNode + flags: CallNodeFlags fields: - - name: flags - type: flags - kind: CallNodeFlags - name: receiver type: node? + kind: non-void expression - name: call_operator_loc type: location? - name: message_loc @@ -1130,18 +1228,18 @@ nodes: type: location - name: value type: node + kind: non-void expression comment: | Represents the use of the `&&=` operator on a call. foo.bar &&= value ^^^^^^^^^^^^^^^^^ - name: CallNode + flags: CallNodeFlags fields: - - name: flags - type: flags - kind: CallNodeFlags - name: receiver type: node? + kind: non-void expression comment: | The object that the method is being called on. This can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -1168,6 +1266,9 @@ nodes: type: location? - name: block type: node? + kind: + - BlockNode + - BlockArgumentNode comment: | Represents a method call, in all of the various forms that can take. @@ -1189,12 +1290,11 @@ nodes: foo&.bar ^^^^^^^^ - name: CallOperatorWriteNode + flags: CallNodeFlags fields: - - name: flags - type: flags - kind: CallNodeFlags - name: receiver type: node? + kind: non-void expression - name: call_operator_loc type: location? - name: message_loc @@ -1203,24 +1303,24 @@ nodes: type: constant - name: write_name type: constant - - name: operator + - name: binary_operator type: constant - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node + kind: non-void expression comment: | Represents the use of an assignment operator on a call. foo.bar += baz ^^^^^^^^^^^^^^ - name: CallOrWriteNode + flags: CallNodeFlags fields: - - name: flags - type: flags - kind: CallNodeFlags - name: receiver type: node? + kind: non-void expression - name: call_operator_loc type: location? - name: message_loc @@ -1233,18 +1333,18 @@ nodes: type: location - name: value type: node + kind: non-void expression comment: | Represents the use of the `||=` operator on a call. foo.bar ||= value ^^^^^^^^^^^^^^^^^ - name: CallTargetNode + flags: CallNodeFlags fields: - - name: flags - type: flags - kind: CallNodeFlags - name: receiver type: node + kind: non-void expression - name: call_operator_loc type: location - name: name @@ -1268,8 +1368,10 @@ nodes: fields: - name: value type: node + kind: pattern expression - name: target type: node + kind: LocalVariableTargetNode - name: operator_loc type: location comment: | @@ -1281,9 +1383,11 @@ nodes: fields: - name: predicate type: node? + kind: non-void expression - name: conditions type: node[] - - name: consequent + kind: InNode + - name: else_clause type: node? kind: ElseNode - name: case_keyword_loc @@ -1301,9 +1405,11 @@ nodes: fields: - name: predicate type: node? + kind: non-void expression - name: conditions type: node[] - - name: consequent + kind: WhenNode + - name: else_clause type: node? kind: ElseNode - name: case_keyword_loc @@ -1325,12 +1431,20 @@ nodes: type: location - name: constant_path type: node + kind: + - ConstantReadNode + - ConstantPathNode + - on error: CallNode # class 0.X end - name: inheritance_operator_loc type: location? - name: superclass type: node? + kind: non-void expression - name: body type: node? + kind: + - StatementsNode + - BeginNode - name: end_keyword_loc type: location - name: name @@ -1350,6 +1464,7 @@ nodes: type: location - name: value type: node + kind: non-void expression comment: | Represents the use of the `&&=` operator for assignment to a class variable. @@ -1361,11 +1476,12 @@ nodes: type: constant - name: name_loc type: location - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node - - name: operator + kind: non-void expression + - name: binary_operator type: constant comment: | Represents assigning to a class variable using an operator that isn't `=`. @@ -1382,6 +1498,7 @@ nodes: type: location - name: value type: node + kind: non-void expression comment: | Represents the use of the `||=` operator for assignment to a class variable. @@ -1430,6 +1547,7 @@ nodes: ^^^^^ - name: value type: node + kind: non-void expression comment: | The value to write to the class variable. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -1460,6 +1578,7 @@ nodes: type: location - name: value type: node + kind: non-void expression comment: | Represents the use of the `&&=` operator for assignment to a constant. @@ -1471,11 +1590,12 @@ nodes: type: constant - name: name_loc type: location - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node - - name: operator + kind: non-void expression + - name: binary_operator type: constant comment: | Represents assigning to a constant using an operator that isn't `=`. @@ -1492,6 +1612,7 @@ nodes: type: location - name: value type: node + kind: non-void expression comment: | Represents the use of the `||=` operator for assignment to a constant. @@ -1506,6 +1627,7 @@ nodes: type: location - name: value type: node + kind: non-void expression comment: | Represents the use of the `&&=` operator for assignment to a constant path. @@ -1515,6 +1637,7 @@ nodes: fields: - name: parent type: node? + kind: non-void expression comment: | The left-hand node of the path, if present. It can be `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). It will be `nil` when the constant lookup is at the root of the module tree. @@ -1559,11 +1682,12 @@ nodes: - name: target type: node kind: ConstantPathNode - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node - - name: operator + kind: non-void expression + - name: binary_operator type: constant comment: | Represents assigning to a constant path using an operator that isn't `=`. @@ -1579,6 +1703,7 @@ nodes: type: location - name: value type: node + kind: non-void expression comment: | Represents the use of the `||=` operator for assignment to a constant path. @@ -1588,6 +1713,7 @@ nodes: fields: - name: parent type: node? + kind: non-void expression - name: name type: constant? - name: delimiter_loc @@ -1621,6 +1747,7 @@ nodes: ^ - name: value type: node + kind: non-void expression comment: | The value to write to the constant path. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -1680,6 +1807,7 @@ nodes: ^^^ - name: value type: node + kind: non-void expression comment: | The value to write to the constant. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -1708,11 +1836,15 @@ nodes: type: location - name: receiver type: node? + kind: non-void expression - name: parameters type: node? kind: ParametersNode - name: body type: node? + kind: + - StatementsNode + - BeginNode - name: locals type: constant[] - name: def_keyword_loc @@ -1739,6 +1871,7 @@ nodes: type: location? - name: value type: node + kind: Node # More than non-void expression as defined?(return) is allowed, yet defined?(BEGIN{}) is SyntaxError - name: rparen_loc type: location? - name: keyword_loc @@ -1782,6 +1915,12 @@ nodes: type: location - name: variable type: node + kind: + - InstanceVariableReadNode + - ClassVariableReadNode + - GlobalVariableReadNode + - BackReferenceReadNode + - NumberedReferenceReadNode comment: | Represents an interpolated variable. @@ -1815,12 +1954,20 @@ nodes: fields: - name: constant type: node? + kind: + - ConstantReadNode + - ConstantPathNode - name: left type: node + kind: SplatNode - name: requireds type: node[] + kind: pattern expression - name: right type: node + kind: + - SplatNode + - on error: MissingNode - name: opening_loc type: location? - name: closing_loc @@ -1837,14 +1984,14 @@ nodes: foo in Foo(*bar, baz, *qux) ^^^^^^^^^^^^^^^^^^^^ - name: FlipFlopNode + flags: RangeFlags fields: - - name: flags - type: flags - kind: RangeFlags - name: left type: node? + kind: non-void expression - name: right type: node? + kind: non-void expression - name: operator_loc type: location comment: | @@ -1866,19 +2013,70 @@ nodes: fields: - name: index type: node + kind: + - LocalVariableTargetNode + - InstanceVariableTargetNode + - ClassVariableTargetNode + - GlobalVariableTargetNode + - ConstantTargetNode + - ConstantPathTargetNode + - CallTargetNode + - IndexTargetNode + - MultiTargetNode + - on error: BackReferenceReadNode # for $& in a end + - on error: NumberedReferenceReadNode # for $1 in a end + - on error: MissingNode # for in 1..10; end + comment: | + The index expression for `for` loops. + + for i in a end + ^ - name: collection type: node + kind: non-void expression + comment: | + The collection to iterate over. + + for i in a end + ^ - name: statements type: node? kind: StatementsNode + comment: | + Represents the body of statements to execute for each iteration of the loop. + + for i in a + foo(i) + ^^^^^^ + end - name: for_keyword_loc type: location + comment: | + The location of the `for` keyword. + + for i in a end + ^^^ - name: in_keyword_loc type: location + comment: | + The location of the `in` keyword. + + for i in a end + ^^ - name: do_keyword_loc type: location? + comment: | + The location of the `do` keyword, if present. + + for i in a do end + ^^ - name: end_keyword_loc type: location + comment: | + The location of the `end` keyword. + + for i in a end + ^^^ comment: | Represents the use of the `for` keyword. @@ -1919,6 +2117,7 @@ nodes: type: location - name: value type: node + kind: non-void expression comment: | Represents the use of the `&&=` operator for assignment to a global variable. @@ -1930,11 +2129,12 @@ nodes: type: constant - name: name_loc type: location - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node - - name: operator + kind: non-void expression + - name: binary_operator type: constant comment: | Represents assigning to a global variable using an operator that isn't `=`. @@ -1951,6 +2151,7 @@ nodes: type: location - name: value type: node + kind: non-void expression comment: | Represents the use of the `||=` operator for assignment to a global variable. @@ -1999,6 +2200,7 @@ nodes: ^^^^ - name: value type: node + kind: non-void expression comment: | The value to write to the global variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -2057,6 +2259,9 @@ nodes: fields: - name: constant type: node? + kind: + - ConstantReadNode + - ConstantPathNode - name: elements type: node[] kind: AssocNode @@ -2090,6 +2295,7 @@ nodes: The `if_keyword_loc` field will be `nil` when the `IfNode` represents a ternary expression. - name: predicate type: node + kind: non-void expression comment: | The node for the condition the `IfNode` is testing. @@ -2125,8 +2331,11 @@ nodes: baz ^^^ end - - name: consequent + - name: subsequent type: node? + kind: + - ElseNode + - IfNode comment: | Represents an `ElseNode` or an `IfNode` when there is an `else` or an `elsif` in the `if` statement. @@ -2179,6 +2388,11 @@ nodes: fields: - name: value type: node + kind: + - LocalVariableReadNode + - CallNode + - ConstantReadNode + - LocalVariableTargetNode comment: | Represents a node that is implicitly being added to the tree but doesn't correspond directly to a node in the source. @@ -2209,6 +2423,7 @@ nodes: fields: - name: pattern type: node + kind: pattern expression - name: statements type: node? kind: StatementsNode @@ -2222,12 +2437,11 @@ nodes: case a; in b then c end ^^^^^^^^^^^ - name: IndexAndWriteNode + flags: CallNodeFlags fields: - - name: flags - type: flags - kind: CallNodeFlags - name: receiver type: node? + kind: non-void expression - name: call_operator_loc type: location? - name: opening_loc @@ -2239,22 +2453,23 @@ nodes: type: location - name: block type: node? + kind: BlockArgumentNode # foo[&b] &&= value, only valid on Ruby < 3.4 - name: operator_loc type: location - name: value type: node + kind: non-void expression comment: | Represents the use of the `&&=` operator on a call to the `[]` method. foo.bar[baz] &&= value ^^^^^^^^^^^^^^^^^^^^^^ - name: IndexOperatorWriteNode + flags: CallNodeFlags fields: - - name: flags - type: flags - kind: CallNodeFlags - name: receiver type: node? + kind: non-void expression - name: call_operator_loc type: location? - name: opening_loc @@ -2266,24 +2481,25 @@ nodes: type: location - name: block type: node? - - name: operator + kind: BlockArgumentNode # foo[&b] += value, only valid on Ruby < 3.4 + - name: binary_operator type: constant - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node + kind: non-void expression comment: | Represents the use of an assignment operator on a call to `[]`. foo.bar[baz] += value ^^^^^^^^^^^^^^^^^^^^^ - name: IndexOrWriteNode + flags: CallNodeFlags fields: - - name: flags - type: flags - kind: CallNodeFlags - name: receiver type: node? + kind: non-void expression - name: call_operator_loc type: location? - name: opening_loc @@ -2295,22 +2511,23 @@ nodes: type: location - name: block type: node? + kind: BlockArgumentNode # foo[&b] ||= value, only valid on Ruby < 3.4 - name: operator_loc type: location - name: value type: node + kind: non-void expression comment: | Represents the use of the `||=` operator on a call to `[]`. foo.bar[baz] ||= value ^^^^^^^^^^^^^^^^^^^^^^ - name: IndexTargetNode + flags: CallNodeFlags fields: - - name: flags - type: flags - kind: CallNodeFlags - name: receiver type: node + kind: non-void expression - name: opening_loc type: location - name: arguments @@ -2320,6 +2537,7 @@ nodes: type: location - name: block type: node? + kind: BlockArgumentNode # foo[&b], = 1, only valid on Ruby < 3.4 comment: | Represents assigning to an index. @@ -2343,6 +2561,7 @@ nodes: type: location - name: value type: node + kind: non-void expression comment: | Represents the use of the `&&=` operator for assignment to an instance variable. @@ -2354,11 +2573,12 @@ nodes: type: constant - name: name_loc type: location - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node - - name: operator + kind: non-void expression + - name: binary_operator type: constant comment: | Represents assigning to an instance variable using an operator that isn't `=`. @@ -2375,6 +2595,7 @@ nodes: type: location - name: value type: node + kind: non-void expression comment: | Represents the use of the `||=` operator for assignment to an instance variable. @@ -2423,6 +2644,7 @@ nodes: ^^^ - name: value type: node + kind: non-void expression comment: | The value to write to the instance variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -2444,10 +2666,8 @@ nodes: @foo = 1 ^^^^^^^^ - name: IntegerNode + flags: IntegerBaseFlags fields: - - name: flags - type: flags - kind: IntegerBaseFlags - name: value type: integer comment: The value of the integer literal as a number. @@ -2457,10 +2677,8 @@ nodes: 1 ^ - name: InterpolatedMatchLastLineNode + flags: RegularExpressionFlags fields: - - name: flags - type: flags - kind: RegularExpressionFlags - name: opening_loc type: location - name: parts @@ -2478,10 +2696,8 @@ nodes: if /foo #{bar} baz/ then end ^^^^^^^^^^^^^^^^ - name: InterpolatedRegularExpressionNode + flags: RegularExpressionFlags fields: - - name: flags - type: flags - kind: RegularExpressionFlags - name: opening_loc type: location - name: parts @@ -2499,10 +2715,8 @@ nodes: /foo #{bar} baz/ ^^^^^^^^^^^^^^^^ - name: InterpolatedStringNode + flags: InterpolatedStringNodeFlags fields: - - name: flags - type: flags - kind: InterpolatedStringNodeFlags - name: opening_loc type: location? - name: parts @@ -2556,6 +2770,12 @@ nodes: `foo #{bar} baz` ^^^^^^^^^^^^^^^^ + - name: ItLocalVariableReadNode + comment: | + Represents reading from the implicit `it` local variable. + + -> { it } + ^^ - name: ItParametersNode comment: | Represents an implicit set of parameters through the use of the `it` keyword within a block or lambda. @@ -2563,10 +2783,8 @@ nodes: -> { it + it } ^^^^^^^^^^^^^^ - name: KeywordHashNode + flags: KeywordHashNodeFlags fields: - - name: flags - type: flags - kind: KeywordHashNodeFlags - name: elements type: node[] kind: @@ -2578,10 +2796,8 @@ nodes: foo(a: b) ^^^^ - name: KeywordRestParameterNode + flags: ParameterFlags fields: - - name: flags - type: flags - kind: ParameterFlags - name: name type: constant? - name: name_loc @@ -2606,8 +2822,15 @@ nodes: type: location - name: parameters type: node? + kind: + - BlockParametersNode + - NumberedParametersNode + - ItParametersNode - name: body type: node? + kind: + - StatementsNode + - BeginNode comment: | Represents using a lambda literal (not the lambda method call). @@ -2621,6 +2844,7 @@ nodes: type: location - name: value type: node + kind: non-void expression - name: name type: constant - name: depth @@ -2634,13 +2858,14 @@ nodes: fields: - name: name_loc type: location - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node + kind: non-void expression - name: name type: constant - - name: operator + - name: binary_operator type: constant - name: depth type: uint32 @@ -2657,6 +2882,7 @@ nodes: type: location - name: value type: node + kind: non-void expression - name: name type: constant - name: depth @@ -2681,10 +2907,6 @@ nodes: _1 # name `:_1` - Finally, for the default `it` block parameter, the name is `0it`. This is to distinguish it from an `it` local variable that is explicitly declared. - - it # name `:0it` - - name: depth type: uint32 comment: | @@ -2740,6 +2962,7 @@ nodes: ^^^ - name: value type: node + kind: non-void expression comment: | The value to write to the local variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -2765,10 +2988,8 @@ nodes: foo = 1 ^^^^^^^ - name: MatchLastLineNode + flags: RegularExpressionFlags fields: - - name: flags - type: flags - kind: RegularExpressionFlags - name: opening_loc type: location - name: content_loc @@ -2786,8 +3007,10 @@ nodes: fields: - name: value type: node + kind: non-void expression - name: pattern type: node + kind: pattern expression - name: operator_loc type: location comment: | @@ -2799,8 +3022,10 @@ nodes: fields: - name: value type: node + kind: non-void expression - name: pattern type: node + kind: pattern expression - name: operator_loc type: location comment: | @@ -2832,8 +3057,15 @@ nodes: type: location - name: constant_path type: node + kind: + - ConstantReadNode + - ConstantPathNode + - on error: MissingNode # module Parent module end - name: body type: node? + kind: + - StatementsNode + - BeginNode - name: end_keyword_loc type: location - name: name @@ -2857,11 +3089,39 @@ nodes: - CallTargetNode - IndexTargetNode - MultiTargetNode - - RequiredParameterNode - - BackReferenceReadNode # On parsing error of `$',` - - NumberedReferenceReadNode # On parsing error of `$1,` + - RequiredParameterNode # def m((a,b)); end + - on error: BackReferenceReadNode # a, (b, $&) = z + - on error: NumberedReferenceReadNode # a, (b, $1) = z + comment: | + Represents the targets expressions before a splat node. + + a, (b, c, *) = 1, 2, 3, 4, 5 + ^^^^ + + The splat node can be absent, in that case all target expressions are in the left field. + + a, (b, c) = 1, 2, 3, 4, 5 + ^^^^ - name: rest type: node? + kind: + - ImplicitRestNode + - SplatNode + comment: | + Represents a splat node in the target expression. + + a, (b, *c) = 1, 2, 3, 4 + ^^ + + The variable can be empty, this results in a `SplatNode` with a `nil` expression field. + + a, (b, *) = 1, 2, 3, 4 + ^ + + If the `*` is omitted, this field will contain an `ImplicitRestNode` + + a, (b,) = 1, 2, 3, 4 + ^ - name: rights type: node[] kind: @@ -2874,17 +3134,38 @@ nodes: - CallTargetNode - IndexTargetNode - MultiTargetNode - - RequiredParameterNode - - BackReferenceReadNode # On parsing error of `*,$'` + - RequiredParameterNode # def m((*,b)); end + - on error: BackReferenceReadNode # a, (*, $&) = z + - on error: NumberedReferenceReadNode # a, (*, $1) = z + comment: | + Represents the targets expressions after a splat node. + + a, (*, b, c) = 1, 2, 3, 4, 5 + ^^^^ - name: lparen_loc type: location? + comment: | + The location of the opening parenthesis. + + a, (b, c) = 1, 2, 3 + ^ - name: rparen_loc type: location? + comment: | + The location of the closing parenthesis. + + a, (b, c) = 1, 2, 3 + ^ comment: | Represents a multi-target expression. a, (b, c) = 1, 2, 3 ^^^^^^ + + This can be a part of `MultiWriteNode` as above, or the target of a `for` loop + + for a, b in [[1, 2], [3, 4]] + ^^^^ - name: MultiWriteNode fields: - name: lefts @@ -2899,8 +3180,38 @@ nodes: - CallTargetNode - IndexTargetNode - MultiTargetNode + - on error: BackReferenceReadNode # $&, = z + - on error: NumberedReferenceReadNode # $1, = z + comment: | + Represents the targets expressions before a splat node. + + a, b, * = 1, 2, 3, 4, 5 + ^^^^ + + The splat node can be absent, in that case all target expressions are in the left field. + + a, b, c = 1, 2, 3, 4, 5 + ^^^^^^^ - name: rest type: node? + kind: + - ImplicitRestNode + - SplatNode + comment: | + Represents a splat node in the target expression. + + a, b, *c = 1, 2, 3, 4 + ^^ + + The variable can be empty, this results in a `SplatNode` with a `nil` expression field. + + a, b, * = 1, 2, 3, 4 + ^ + + If the `*` is omitted, this field will contain an `ImplicitRestNode` + + a, b, = 1, 2, 3, 4 + ^ - name: rights type: node[] kind: @@ -2913,14 +3224,42 @@ nodes: - CallTargetNode - IndexTargetNode - MultiTargetNode + - on error: BackReferenceReadNode # *, $& = z + - on error: NumberedReferenceReadNode # *, $1 = z + comment: | + Represents the targets expressions after a splat node. + + a, *, b, c = 1, 2, 3, 4, 5 + ^^^^ - name: lparen_loc type: location? + comment: | + The location of the opening parenthesis. + + (a, b, c) = 1, 2, 3 + ^ - name: rparen_loc type: location? + comment: | + The location of the closing parenthesis. + + (a, b, c) = 1, 2, 3 + ^ - name: operator_loc type: location + comment: | + The location of the operator. + + a, b, c = 1, 2, 3 + ^ - name: value type: node + kind: non-void expression + comment: | + The value to write to the targets. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + + a, b, c = 1, 2, 3 + ^^^^^^^ comment: | Represents a write to a multi-target expression. @@ -2983,16 +3322,15 @@ nodes: $1 ^^ - name: OptionalKeywordParameterNode + flags: ParameterFlags fields: - - name: flags - type: flags - kind: ParameterFlags - name: name type: constant - name: name_loc type: location - name: value type: node + kind: non-void expression comment: | Represents an optional keyword parameter to a method, block, or lambda definition. @@ -3000,10 +3338,8 @@ nodes: ^^^^ end - name: OptionalParameterNode + flags: ParameterFlags fields: - - name: flags - type: flags - kind: ParameterFlags - name: name type: constant - name: name_loc @@ -3012,6 +3348,7 @@ nodes: type: location - name: value type: node + kind: non-void expression comment: | Represents an optional parameter to a method, block, or lambda definition. @@ -3022,6 +3359,7 @@ nodes: fields: - name: left type: node + kind: non-void expression comment: | Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -3032,8 +3370,9 @@ nodes: ^ - name: right type: node + kind: Node comment: | - Represents the right side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + Represents the right side of the expression. left || right ^^^^^ @@ -3073,8 +3412,10 @@ nodes: - RequiredParameterNode - MultiTargetNode # On parsing error of `f(**kwargs, ...)` or `f(**nil, ...)`, the keyword_rest value is moved here: - - KeywordRestParameterNode - - NoKeywordsParameterNode + - on error: KeywordRestParameterNode + - on error: NoKeywordsParameterNode + # On parsing error of `f(..., ...)`, the first forwarding parameter is moved here: + - on error: ForwardingParameterNode - name: keywords type: node[] kind: @@ -3099,6 +3440,7 @@ nodes: fields: - name: body type: node? + kind: non-void expression # Usually a StatementsNode but not always e.g. `1 in (..10)` - name: opening_loc type: location - name: closing_loc @@ -3113,6 +3455,7 @@ nodes: fields: - name: expression type: node + kind: non-void expression - name: operator_loc type: location - name: lparen_loc @@ -3128,6 +3471,15 @@ nodes: fields: - name: variable type: node + kind: + - LocalVariableReadNode + - InstanceVariableReadNode + - ClassVariableReadNode + - GlobalVariableReadNode # foo in ^$a + - BackReferenceReadNode # foo in ^$& + - NumberedReferenceReadNode # foo in ^$1 + - ItLocalVariableReadNode # proc { 1 in ^it } + - on error: MissingNode # foo in ^Bar - name: operator_loc type: location comment: | @@ -3176,12 +3528,11 @@ nodes: kind: StatementsNode comment: The top level node of any parse tree. - name: RangeNode + flags: RangeFlags fields: - - name: flags - type: flags - kind: RangeFlags - name: left type: node? + kind: non-void expression comment: | The left-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -3192,6 +3543,7 @@ nodes: ^^^^^ - name: right type: node? + kind: non-void expression comment: | The right-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -3214,9 +3566,20 @@ nodes: c if a =~ /left/ ... b =~ /right/ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - name: RationalNode + flags: IntegerBaseFlags fields: - - name: numeric - type: node + - name: numerator + type: integer + comment: | + The numerator of the rational number. + + 1.5r # numerator 3 + - name: denominator + type: integer + comment: | + The denominator of the rational number. + + 1.5r # denominator 2 comment: | Represents a rational number literal. @@ -3229,10 +3592,8 @@ nodes: redo ^^^^ - name: RegularExpressionNode + flags: RegularExpressionFlags fields: - - name: flags - type: flags - kind: RegularExpressionFlags - name: opening_loc type: location - name: content_loc @@ -3247,10 +3608,8 @@ nodes: /foo/i ^^^^^^ - name: RequiredKeywordParameterNode + flags: ParameterFlags fields: - - name: flags - type: flags - kind: ParameterFlags - name: name type: constant - name: name_loc @@ -3262,10 +3621,8 @@ nodes: ^^ end - name: RequiredParameterNode + flags: ParameterFlags fields: - - name: flags - type: flags - kind: ParameterFlags - name: name type: constant comment: | @@ -3278,10 +3635,12 @@ nodes: fields: - name: expression type: node + kind: Node - name: keyword_loc type: location - name: rescue_expression type: node + kind: Node newline: expression comment: | Represents an expression modified with a rescue. @@ -3294,14 +3653,27 @@ nodes: type: location - name: exceptions type: node[] + kind: non-void expression - name: operator_loc type: location? - name: reference type: node? + kind: + - LocalVariableTargetNode + - InstanceVariableTargetNode + - ClassVariableTargetNode + - GlobalVariableTargetNode + - ConstantTargetNode + - ConstantPathTargetNode + - CallTargetNode + - IndexTargetNode + - on error: BackReferenceReadNode # => begin; rescue => $&; end + - on error: NumberedReferenceReadNode # => begin; rescue => $1; end + - on error: MissingNode # begin; rescue =>; end - name: statements type: node? kind: StatementsNode - - name: consequent + - name: subsequent type: node? kind: RescueNode comment: | @@ -3313,12 +3685,10 @@ nodes: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ end - `Foo, *splat, Bar` are in the `exceptions` field. `ex` is in the `exception` field. + `Foo, *splat, Bar` are in the `exceptions` field. `ex` is in the `reference` field. - name: RestParameterNode + flags: ParameterFlags fields: - - name: flags - type: flags - kind: ParameterFlags - name: name type: constant? - name: name_loc @@ -3339,9 +3709,6 @@ nodes: ^^^^^ - name: ReturnNode fields: - - name: flags - type: flags - kind: ReturnNodeFlags - name: keyword_loc type: location - name: arguments @@ -3359,10 +3726,8 @@ nodes: self ^^^^ - name: ShareableConstantNode + flags: ShareableConstantNodeFlags fields: - - name: flags - type: flags - kind: ShareableConstantNodeFlags - name: write type: node kind: @@ -3391,8 +3756,12 @@ nodes: type: location - name: expression type: node + kind: non-void expression - name: body type: node? + kind: + - StatementsNode + - BeginNode - name: end_keyword_loc type: location comment: | @@ -3407,10 +3776,8 @@ nodes: __ENCODING__ ^^^^^^^^^^^^ - name: SourceFileNode + flags: StringFlags fields: - - name: flags - type: flags - kind: StringFlags - name: filepath type: string comment: Represents the file path being parsed. This corresponds directly to the `filepath` option given to the various `Prism::parse*` APIs. @@ -3431,6 +3798,7 @@ nodes: type: location - name: expression type: node? + kind: non-void expression comment: | Represents the use of the splat operator. @@ -3440,16 +3808,15 @@ nodes: fields: - name: body type: node[] + kind: Node comment: | Represents a set of statements contained within some scope. foo; bar; baz ^^^^^^^^^^^^^ - name: StringNode + flags: StringFlags fields: - - name: flags - type: flags - kind: StringFlags - name: opening_loc type: location? - name: content_loc @@ -3482,6 +3849,9 @@ nodes: type: location? - name: block type: node? + kind: + - BlockNode + - BlockArgumentNode comment: | Represents the use of the `super` keyword with parentheses or arguments. @@ -3491,10 +3861,8 @@ nodes: super foo, bar ^^^^^^^^^^^^^^ - name: SymbolNode + flags: SymbolFlags fields: - - name: flags - type: flags - kind: SymbolFlags - name: opening_loc type: location? - name: value_loc @@ -3545,6 +3913,7 @@ nodes: ^^^^^^ - name: predicate type: node + kind: non-void expression comment: | The condition to be evaluated for the unless expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -3555,7 +3924,7 @@ nodes: ^^^^ - name: then_keyword_loc type: location? - comment: + comment: | The location of the `then` keyword, if present. unless cond then bar end @@ -3569,7 +3938,7 @@ nodes: unless cond then bar end ^^^ - - name: consequent + - name: else_clause type: node? kind: ElseNode comment: | @@ -3594,16 +3963,15 @@ nodes: unless foo then bar end ^^^^^^^^^^^^^^^^^^^^^^^ - name: UntilNode + flags: LoopFlags fields: - - name: flags - type: flags - kind: LoopFlags - name: keyword_loc type: location - name: closing_loc type: location? - name: predicate type: node + kind: non-void expression - name: statements type: node? kind: StatementsNode @@ -3622,6 +3990,7 @@ nodes: type: location - name: conditions type: node[] + kind: non-void expression - name: then_keyword_loc type: location? - name: statements @@ -3635,16 +4004,15 @@ nodes: ^^^^^^^^^ end - name: WhileNode + flags: LoopFlags fields: - - name: flags - type: flags - kind: LoopFlags - name: keyword_loc type: location - name: closing_loc type: location? - name: predicate type: node + kind: non-void expression - name: statements type: node? kind: StatementsNode @@ -3658,10 +4026,8 @@ nodes: while foo do bar end ^^^^^^^^^^^^^^^^^^^^ - name: XStringNode + flags: EncodingFlags fields: - - name: flags - type: flags - kind: EncodingFlags - name: opening_loc type: location - name: content_loc diff --git a/cpp/test.cpp b/cpp/test.cpp new file mode 100644 index 00000000000..af993c9fca9 --- /dev/null +++ b/cpp/test.cpp @@ -0,0 +1,24 @@ +extern "C" { + #include "prism.h" +} + +#include + +int main() { + pm_parser_t parser; + pm_parser_init(&parser, reinterpret_cast("1 + 2"), 5, NULL); + + pm_node_t *root = pm_parse(&parser); + pm_buffer_t buffer = { 0 }; + + pm_prettyprint(&buffer, &parser, root); + pm_buffer_append_byte(&buffer, '\0'); + + std::cout << buffer.value << std::endl; + + pm_buffer_free(&buffer); + pm_node_destroy(&parser, root); + pm_parser_free(&parser); + + return 0; +} diff --git a/doc/images/rust.svg b/doc/images/rust.svg new file mode 100644 index 00000000000..dd830c261bf --- /dev/null +++ b/doc/images/rust.svg @@ -0,0 +1,57 @@ + + + \ No newline at end of file diff --git a/doc/index.css b/doc/index.css index dc8e5c1b1f8..b4683cf24ff 100644 --- a/doc/index.css +++ b/doc/index.css @@ -34,6 +34,14 @@ main { } } +@media only screen and (max-width: 900px) { + main { + grid-template-rows: repeat(1fr); + grid-template-columns: 1fr; + height: 72vh; + } +} + @media only screen and (max-width: 600px) { main { margin: 2vh 5vw; @@ -52,10 +60,6 @@ main { vertical-align: middle; } -.reference:first-child { - grid-column: span 2; -} - .reference > img { height: 10vh; width: 10vh; diff --git a/doc/index.html b/doc/index.html index 3f662bc4f55..9e0e38cb60b 100644 --- a/doc/index.html +++ b/doc/index.html @@ -22,6 +22,10 @@

C reference

Ruby

Ruby reference

+ + Rust +

Rust reference

+
Java

Java reference

diff --git a/docs/fuzzing.md b/docs/fuzzing.md index 8565af24056..b6ec6112a82 100644 --- a/docs/fuzzing.md +++ b/docs/fuzzing.md @@ -26,7 +26,7 @@ fuzz There are currently three fuzzing targets - `pm_serialize_parse` (parse) -- `pm_regexp_named_capture_group_names` (regexp) +- `pm_regexp_parse` (regexp) Respectively, fuzzing can be performed with diff --git a/docs/parsing_rules.md b/docs/parsing_rules.md index 1537bd4bab9..36475ba40e3 100644 --- a/docs/parsing_rules.md +++ b/docs/parsing_rules.md @@ -12,7 +12,10 @@ Constants in Ruby begin with an upper-case letter. This is followed by any numbe Most expressions in CRuby are non-void. This means the expression they represent resolves to a value. For example, `1 + 2` is a non-void expression, because it resolves to a method call. Even things like `class Foo; end` is a non-void expression, because it returns the last evaluated expression in the body of the class (or `nil`). -Certain nodes, however, are void expressions, and cannot be combined to form larger expressions. For example, `BEGIN {}`, `END {}`, `alias foo bar`, and `undef foo`. +Certain nodes, however, are void expressions, and cannot be combined to form larger expressions. +* `BEGIN {}`, `END {}`, `alias foo bar`, and `undef foo` can only be at a statement position. +* The "jumps": `return`, `break`, `next`, `redo`, `retry` are void expressions. +* `value => pattern` is also considered a void expression. ## Identifiers diff --git a/docs/ripper_translation.md b/docs/ripper_translation.md index 5fb04437cfa..af765da56f8 100644 --- a/docs/ripper_translation.md +++ b/docs/ripper_translation.md @@ -48,3 +48,25 @@ ArithmeticRipper.new("1 + 2 - 3").parse # => [0] ``` The exact names of the `on_*` methods are listed in the `Ripper` source. + +## Background + +It is helpful to understand the differences between the `Ripper` library and the `Prism` library. Both libraries perform parsing and provide you with APIs to manipulate and understand the resulting syntax tree. However, there are a few key differences. + +### Design + +`Ripper` is a streaming parser. This means as it is parsing Ruby code, it dispatches events back to the consumer. This allows quite a bit of flexibility. You can use it to build your own syntax tree or to find specific patterns in the code. `Prism` on the other hand returns to your the completed syntax tree _before_ it allows you to manipulate it. This means the tree that you get back is the only representation that can be generated by the parser _at parse time_ (but of course can be manipulated later). + +### Fields + +We use the term "field" to mean a piece of information on a syntax tree node. `Ripper` provides the minimal number of fields to accurately represent the syntax tree for the purposes of compilation/interpretation. For example, in the callbacks for nodes that are based on keywords (`class`, `module`, `for`, `while`, etc.) you are not given the keyword itself, you need to attach it on your own. In other cases, tokens are not necessarily dispatched at all, meaning you need to find them yourself. `Prism` provides the opposite: the maximum number of fields on nodes is provided. As a tradeoff, this requires more memory, but this is chosen to make it easier on consumers. + +### Maintainability + +The `Ripper` interface is not guaranteed in any way, and tends to change between patch versions of CRuby. This is largely due to the fact that `Ripper` is a by-product of the generated parser, as opposed to its own parser. As an example, in the expression `foo::bar = baz`, there are three different represents possible for the call operator, including: + +* `:"::"` - Ruby 1.9 to Ruby 3.1.4 +* `73` - Ruby 3.1.5 to Ruby 3.1.6 +* `[:@op, "::", [lineno, column]]` - Ruby 3.2.0 and later + +The `Prism` interface is guaranteed going forward to be the consistent, and the official Ruby syntax tree interface. This means you can rely on this interface without having to worry about individual changes between Ruby versions. It also is a gem, which means it is versioned based on the gem version, as opposed to being versioned based on the Ruby version. Finally, you can use `Prism` to parse multiple versions of Ruby, whereas `Ripper` is tied to the Ruby version it is running on. diff --git a/docs/serialization.md b/docs/serialization.md index 6e7ececfee3..ec395f8847d 100644 --- a/docs/serialization.md +++ b/docs/serialization.md @@ -116,7 +116,9 @@ Each node is structured like the following table: | # bytes | field | | --- | --- | | `1` | node type | +| varuint | node identifier | | location | node location | +| varuint | node flags | Every field on the node is then appended to the serialized string. The fields can be determined by referencing `config.yml`. Depending on the type of field, it could take a couple of different forms, described below: @@ -199,6 +201,7 @@ The final argument to `pm_serialize_parse` is an optional string that controls t | `1` | frozen string literal | | `1` | command line flags | | `1` | syntax version, see [pm_options_version_t](https://github.com/ruby/prism/blob/main/include/prism/options.h) for valid values | +| `1` | whether or not the encoding is locked (should almost always be false) | | `4` | the number of scopes | | ... | the scopes | diff --git a/ext/prism/extconf.rb b/ext/prism/extconf.rb index 53800785efc..53a5bfcc049 100644 --- a/ext/prism/extconf.rb +++ b/ext/prism/extconf.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "rbconfig" + if ARGV.delete("--help") print(<<~TEXT) USAGE: ruby #{$PROGRAM_NAME} [options] @@ -40,26 +42,6 @@ def generate_templates end end -# We're going to need to run `make` using prism's `Makefile`. We want to match -# up as much of the configuration to the configuration that built the current -# version of Ruby as possible. -require "rbconfig" -env = RbConfig::CONFIG.slice("SOEXT", "CPPFLAGS", "CFLAGS", "CC", "AR", "ARFLAGS", "MAKEDIRS", "RMALL") - -# It's possible that the Ruby that is being run wasn't actually compiled on this -# machine, in which case the configuration might be incorrect. In this case -# we'll need to do some additional checks and potentially fall back to defaults. -if env.key?("CC") && !File.exist?(env["CC"]) - env.delete("CC") - env.delete("CFLAGS") - env.delete("CPPFLAGS") -end - -if env.key?("AR") && !File.exist?(env["AR"]) - env.delete("AR") - env.delete("ARFLAGS") -end - # Runs `make` in the root directory of the project. Note that this is the # `Makefile` for the overall project, not the `Makefile` that is being generated # by this script.` @@ -68,7 +50,7 @@ def make(env, target) Dir.chdir(File.expand_path("../..", __dir__)) do system( env, - RUBY_PLATFORM.include?("openbsd") ? "gmake" : "make", + RUBY_PLATFORM.match?(/openbsd|freebsd/) ? "gmake" : "make", target, exception: true ) @@ -77,15 +59,37 @@ def make(env, target) # On non-CRuby we only need the shared library since we'll interface with it # through FFI, so we'll build only that and not the C extension. We also avoid -# `require "mkmf"` as that prepends the LLVM toolchain to PATH on TruffleRuby, -# but we want to use the native toolchain here since libprism is run natively. +# `require "mkmf"` as that prepends the GraalVM LLVM toolchain to PATH on TruffleRuby < 24.0, +# but we want to use the system toolchain here since libprism is run natively. if RUBY_ENGINE != "ruby" generate_templates - make(env, "build/libprism.#{RbConfig::CONFIG["SOEXT"]}") + soext = RbConfig::CONFIG["SOEXT"] + # Pass SOEXT to avoid an extra subprocess just to query that + make({ "SOEXT" => soext }, "build/libprism.#{soext}") File.write("Makefile", "all install clean:\n\t@#{RbConfig::CONFIG["NULLCMD"]}\n") return end +# We're going to need to run `make` using prism's `Makefile`. +# We want to use the same toolchain (compiler, flags, etc) to compile libprism.a and +# the C extension since they will be linked together. +# The C extension uses RbConfig, which contains values from the toolchain that built the running Ruby. +env = RbConfig::CONFIG.slice("SOEXT", "CPPFLAGS", "CFLAGS", "CC", "AR", "ARFLAGS", "MAKEDIRS", "RMALL") + +# It's possible that the Ruby that is being run wasn't actually compiled on this +# machine, in which case parts of RbConfig might be incorrect. In this case +# we'll need to do some additional checks and potentially fall back to defaults. +if env.key?("CC") && !File.exist?(env["CC"]) + env.delete("CC") + env.delete("CFLAGS") + env.delete("CPPFLAGS") +end + +if env.key?("AR") && !File.exist?(env["AR"]) + env.delete("AR") + env.delete("ARFLAGS") +end + require "mkmf" # First, ensure that we can find the header for the prism library. diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 84872914c42..26415c2b6da 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -21,38 +21,36 @@ VALUE rb_cPrismParseError; VALUE rb_cPrismParseWarning; VALUE rb_cPrismResult; VALUE rb_cPrismParseResult; +VALUE rb_cPrismLexResult; VALUE rb_cPrismParseLexResult; +VALUE rb_cPrismStringQuery; VALUE rb_cPrismDebugEncoding; -ID rb_option_id_command_line; -ID rb_option_id_encoding; -ID rb_option_id_filepath; -ID rb_option_id_frozen_string_literal; -ID rb_option_id_line; -ID rb_option_id_scopes; -ID rb_option_id_version; -ID rb_prism_source_id_for; +ID rb_id_option_command_line; +ID rb_id_option_encoding; +ID rb_id_option_filepath; +ID rb_id_option_frozen_string_literal; +ID rb_id_option_line; +ID rb_id_option_main_script; +ID rb_id_option_partial_script; +ID rb_id_option_scopes; +ID rb_id_option_version; +ID rb_id_source_for; /******************************************************************************/ /* IO of Ruby code */ /******************************************************************************/ /** - * Check if the given VALUE is a string. If it's nil, then return NULL. If it's - * not a string, then raise a type error. Otherwise return the VALUE as a C - * string. + * Check if the given VALUE is a string. If it's not a string, then raise a + * TypeError. Otherwise return the VALUE as a C string. */ static const char * check_string(VALUE value) { - // If the value is nil, then we don't need to do anything. - if (NIL_P(value)) { - return NULL; - } - // Check if the value is a string. If it's not, then raise a type error. if (!RB_TYPE_P(value, T_STRING)) { - rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected String)", rb_obj_class(value)); + rb_raise(rb_eTypeError, "wrong argument type %" PRIsVALUE " (expected String)", rb_obj_class(value)); } // Otherwise, return the value as a C string. @@ -66,7 +64,7 @@ static void input_load_string(pm_string_t *input, VALUE string) { // Check if the string is a string. If it's not, then raise a type error. if (!RB_TYPE_P(string, T_STRING)) { - rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected String)", rb_obj_class(string)); + rb_raise(rb_eTypeError, "wrong argument type %" PRIsVALUE " (expected String)", rb_obj_class(string)); } pm_string_constant_init(input, RSTRING_PTR(string), RSTRING_LEN(string)); @@ -135,15 +133,21 @@ build_options_i(VALUE key, VALUE value, VALUE argument) { pm_options_t *options = (pm_options_t *) argument; ID key_id = SYM2ID(key); - if (key_id == rb_option_id_filepath) { + if (key_id == rb_id_option_filepath) { if (!NIL_P(value)) pm_options_filepath_set(options, check_string(value)); - } else if (key_id == rb_option_id_encoding) { - if (!NIL_P(value)) pm_options_encoding_set(options, rb_enc_name(rb_to_encoding(value))); - } else if (key_id == rb_option_id_line) { + } else if (key_id == rb_id_option_encoding) { + if (!NIL_P(value)) { + if (value == Qfalse) { + pm_options_encoding_locked_set(options, true); + } else { + pm_options_encoding_set(options, rb_enc_name(rb_to_encoding(value))); + } + } + } else if (key_id == rb_id_option_line) { if (!NIL_P(value)) pm_options_line_set(options, NUM2INT(value)); - } else if (key_id == rb_option_id_frozen_string_literal) { + } else if (key_id == rb_id_option_frozen_string_literal) { if (!NIL_P(value)) pm_options_frozen_string_literal_set(options, RTEST(value)); - } else if (key_id == rb_option_id_version) { + } else if (key_id == rb_id_option_version) { if (!NIL_P(value)) { const char *version = check_string(value); @@ -151,9 +155,9 @@ build_options_i(VALUE key, VALUE value, VALUE argument) { rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value); } } - } else if (key_id == rb_option_id_scopes) { + } else if (key_id == rb_id_option_scopes) { if (!NIL_P(value)) build_options_scopes(options, value); - } else if (key_id == rb_option_id_command_line) { + } else if (key_id == rb_id_option_command_line) { if (!NIL_P(value)) { const char *string = check_string(value); uint8_t command_line = 0; @@ -172,6 +176,10 @@ build_options_i(VALUE key, VALUE value, VALUE argument) { pm_options_command_line_set(options, command_line); } + } else if (key_id == rb_id_option_main_script) { + if (!NIL_P(value)) pm_options_main_script_set(options, RTEST(value)); + } else if (key_id == rb_id_option_partial_script) { + if (!NIL_P(value)) pm_options_partial_script_set(options, RTEST(value)); } else { rb_raise(rb_eArgError, "unknown keyword: %" PRIsVALUE, key); } @@ -206,6 +214,7 @@ build_options(VALUE argument) { static void extract_options(pm_options_t *options, VALUE filepath, VALUE keywords) { options->line = 1; // default + if (!NIL_P(keywords)) { struct build_options_data data = { .options = options, .keywords = keywords }; struct build_options_data *argument = &data; @@ -246,27 +255,41 @@ string_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options) * Read options for methods that look like (filepath, **options). */ static void -file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options) { +file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, VALUE *encoded_filepath) { VALUE filepath; VALUE keywords; rb_scan_args(argc, argv, "1:", &filepath, &keywords); Check_Type(filepath, T_STRING); + *encoded_filepath = rb_str_encode_ospath(filepath); + extract_options(options, *encoded_filepath, keywords); - extract_options(options, filepath, keywords); - - const char * string_source = (const char *) pm_string_source(&options->filepath); + const char *source = (const char *) pm_string_source(&options->filepath); + pm_string_init_result_t result; - if (!pm_string_file_init(input, string_source)) { - pm_options_free(options); + switch (result = pm_string_file_init(input, source)) { + case PM_STRING_INIT_SUCCESS: + break; + case PM_STRING_INIT_ERROR_GENERIC: { + pm_options_free(options); #ifdef _WIN32 - int e = rb_w32_map_errno(GetLastError()); + int e = rb_w32_map_errno(GetLastError()); #else - int e = errno; + int e = errno; #endif - rb_syserr_fail(e, string_source); + rb_syserr_fail(e, source); + break; + } + case PM_STRING_INIT_ERROR_DIRECTORY: + pm_options_free(options); + rb_syserr_fail(EISDIR, source); + break; + default: + pm_options_free(options); + rb_raise(rb_eRuntimeError, "Unknown error (%d) initializing file: %s", result, source); + break; } } @@ -344,7 +367,8 @@ dump_file(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; - file_options(argc, argv, &input, &options); + VALUE encoded_filepath; + file_options(argc, argv, &input, &options, &encoded_filepath); VALUE value = dump_input(&input, &options); pm_string_free(&input); @@ -364,7 +388,7 @@ dump_file(int argc, VALUE *argv, VALUE self) { */ static VALUE parser_comments(pm_parser_t *parser, VALUE source) { - VALUE comments = rb_ary_new(); + VALUE comments = rb_ary_new_capa(parser->comment_list.size); for (pm_comment_t *comment = (pm_comment_t *) parser->comment_list.head; comment != NULL; comment = (pm_comment_t *) comment->node.next) { VALUE location_argv[] = { @@ -386,7 +410,7 @@ parser_comments(pm_parser_t *parser, VALUE source) { */ static VALUE parser_magic_comments(pm_parser_t *parser, VALUE source) { - VALUE magic_comments = rb_ary_new(); + VALUE magic_comments = rb_ary_new_capa(parser->magic_comment_list.size); for (pm_magic_comment_t *magic_comment = (pm_magic_comment_t *) parser->magic_comment_list.head; magic_comment != NULL; magic_comment = (pm_magic_comment_t *) magic_comment->node.next) { VALUE key_loc_argv[] = { @@ -436,7 +460,7 @@ parser_data_loc(const pm_parser_t *parser, VALUE source) { */ static VALUE parser_errors(pm_parser_t *parser, rb_encoding *encoding, VALUE source) { - VALUE errors = rb_ary_new(); + VALUE errors = rb_ary_new_capa(parser->error_list.size); pm_diagnostic_t *error; for (error = (pm_diagnostic_t *) parser->error_list.head; error != NULL; error = (pm_diagnostic_t *) error->node.next) { @@ -479,7 +503,7 @@ parser_errors(pm_parser_t *parser, rb_encoding *encoding, VALUE source) { */ static VALUE parser_warnings(pm_parser_t *parser, rb_encoding *encoding, VALUE source) { - VALUE warnings = rb_ary_new(); + VALUE warnings = rb_ary_new_capa(parser->warning_list.size); pm_diagnostic_t *warning; for (warning = (pm_diagnostic_t *) parser->warning_list.head; warning != NULL; warning = (pm_diagnostic_t *) warning->node.next) { @@ -556,9 +580,10 @@ static void parse_lex_token(void *data, pm_parser_t *parser, pm_token_t *token) { parse_lex_data_t *parse_lex_data = (parse_lex_data_t *) parser->lex_callback->data; - VALUE yields = rb_ary_new_capa(2); - rb_ary_push(yields, pm_token_new(parser, token, parse_lex_data->encoding, parse_lex_data->source)); - rb_ary_push(yields, INT2FIX(parser->lex_state)); + VALUE yields = rb_assoc_new( + pm_token_new(parser, token, parse_lex_data->encoding, parse_lex_data->source), + INT2FIX(parser->lex_state) + ); rb_ary_push(parse_lex_data->tokens, yields); } @@ -599,8 +624,8 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod pm_parser_register_encoding_changed_callback(&parser, parse_lex_encoding_changed_callback); VALUE source_string = rb_str_new((const char *) pm_string_source(input), pm_string_length(input)); - VALUE offsets = rb_ary_new(); - VALUE source = rb_funcall(rb_cPrismSource, rb_prism_source_id_for, 3, source_string, LONG2NUM(parser.start_line), offsets); + VALUE offsets = rb_ary_new_capa(parser.newline_list.size); + VALUE source = rb_funcall(rb_cPrismSource, rb_id_source_for, 3, source_string, LONG2NUM(parser.start_line), offsets); parse_lex_data_t parse_lex_data = { .source = source, @@ -628,16 +653,16 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod rb_ary_push(offsets, ULONG2NUM(parser.newline_list.offsets[index])); } - VALUE value; + VALUE result; if (return_nodes) { - value = rb_ary_new_capa(2); + VALUE value = rb_ary_new_capa(2); rb_ary_push(value, pm_ast_new(&parser, node, parse_lex_data.encoding, source)); rb_ary_push(value, parse_lex_data.tokens); + result = parse_result_create(rb_cPrismParseLexResult, &parser, value, parse_lex_data.encoding, source); } else { - value = parse_lex_data.tokens; + result = parse_result_create(rb_cPrismLexResult, &parser, parse_lex_data.tokens, parse_lex_data.encoding, source); } - VALUE result = parse_result_create(rb_cPrismParseLexResult, &parser, value, parse_lex_data.encoding, source); pm_node_destroy(&parser, node); pm_parser_free(&parser); @@ -646,10 +671,10 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod /** * call-seq: - * Prism::lex(source, **options) -> Array + * Prism::lex(source, **options) -> LexResult * - * Return an array of Token instances corresponding to the given string. For - * supported options, see Prism::parse. + * Return a LexResult instance that contains an array of Token instances + * corresponding to the given string. For supported options, see Prism::parse. */ static VALUE lex(int argc, VALUE *argv, VALUE self) { @@ -666,17 +691,18 @@ lex(int argc, VALUE *argv, VALUE self) { /** * call-seq: - * Prism::lex_file(filepath, **options) -> Array + * Prism::lex_file(filepath, **options) -> LexResult * - * Return an array of Token instances corresponding to the given file. For - * supported options, see Prism::parse. + * Return a LexResult instance that contains an array of Token instances + * corresponding to the given file. For supported options, see Prism::parse. */ static VALUE lex_file(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; - file_options(argc, argv, &input, &options); + VALUE encoded_filepath; + file_options(argc, argv, &input, &options, &encoded_filepath); VALUE value = parse_lex_input(&input, &options, false); pm_string_free(&input); @@ -728,14 +754,27 @@ parse_input(pm_string_t *input, const pm_options_t *options) { * has been set. This should be a boolean or nil. * * `line` - the line number that the parse starts on. This should be an * integer or nil. Note that this is 1-indexed. + * * `main_script` - a boolean indicating whether or not the source being parsed + * is the main script being run by the interpreter. This controls whether + * or not shebangs are parsed for additional flags and whether or not the + * parser will attempt to find a matching shebang if the first one does + * not contain the word "ruby". + * * `partial_script` - when the file being parsed is considered a "partial" + * script, jumps will not be marked as errors if they are not contained + * within loops/blocks. This is used in the case that you're parsing a + * script that you know will be embedded inside another script later, but + * you do not have that context yet. For example, when parsing an ERB + * template that will be evaluated inside another script. * * `scopes` - the locals that are in scope surrounding the code that is being * parsed. This should be an array of arrays of symbols or nil. Scopes are * ordered from the outermost scope to the innermost one. * * `version` - the version of Ruby syntax that prism should used to parse Ruby * code. By default prism assumes you want to parse with the latest version * of Ruby syntax (which you can trigger with `nil` or `"latest"`). You - * may also restrict the syntax to a specific version of Ruby. The - * supported values are `"3.3.0"` and `"3.4.0"`. + * may also restrict the syntax to a specific version of Ruby, e.g., with `"3.3.0"`. + * To parse with the same syntax version that the current Ruby is running + * use `version: RUBY_VERSION`. Raises ArgumentError if the version is not + * currently supported by Prism. */ static VALUE parse(int argc, VALUE *argv, VALUE self) { @@ -761,6 +800,85 @@ parse(int argc, VALUE *argv, VALUE self) { return value; } +/** + * call-seq: + * Prism::parse_file(filepath, **options) -> ParseResult + * + * Parse the given file and return a ParseResult instance. For supported + * options, see Prism::parse. + */ +static VALUE +parse_file(int argc, VALUE *argv, VALUE self) { + pm_string_t input; + pm_options_t options = { 0 }; + + VALUE encoded_filepath; + file_options(argc, argv, &input, &options, &encoded_filepath); + + VALUE value = parse_input(&input, &options); + pm_string_free(&input); + pm_options_free(&options); + + return value; +} + +/** + * Parse the given input and return nothing. + */ +static void +profile_input(pm_string_t *input, const pm_options_t *options) { + pm_parser_t parser; + pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options); + + pm_node_t *node = pm_parse(&parser); + pm_node_destroy(&parser, node); + pm_parser_free(&parser); +} + +/** + * call-seq: + * Prism::profile(source, **options) -> nil + * + * Parse the given string and return nothing. This method is meant to allow + * profilers to avoid the overhead of reifying the AST to Ruby. For supported + * options, see Prism::parse. + */ +static VALUE +profile(int argc, VALUE *argv, VALUE self) { + pm_string_t input; + pm_options_t options = { 0 }; + + string_options(argc, argv, &input, &options); + profile_input(&input, &options); + pm_string_free(&input); + pm_options_free(&options); + + return Qnil; +} + +/** + * call-seq: + * Prism::profile_file(filepath, **options) -> nil + * + * Parse the given file and return nothing. This method is meant to allow + * profilers to avoid the overhead of reifying the AST to Ruby. For supported + * options, see Prism::parse. + */ +static VALUE +profile_file(int argc, VALUE *argv, VALUE self) { + pm_string_t input; + pm_options_t options = { 0 }; + + VALUE encoded_filepath; + file_options(argc, argv, &input, &options, &encoded_filepath); + + profile_input(&input, &options); + pm_string_free(&input); + pm_options_free(&options); + + return Qnil; +} + /** * An implementation of fgets that is suitable for use with Ruby IO objects. */ @@ -773,8 +891,8 @@ parse_stream_fgets(char *string, int size, void *stream) { return NULL; } - const char *cstr = StringValueCStr(line); - size_t length = strlen(cstr); + const char *cstr = RSTRING_PTR(line); + long length = RSTRING_LEN(line); memcpy(string, cstr, length); string[length] = '\0'; @@ -815,27 +933,6 @@ parse_stream(int argc, VALUE *argv, VALUE self) { return result; } -/** - * call-seq: - * Prism::parse_file(filepath, **options) -> ParseResult - * - * Parse the given file and return a ParseResult instance. For supported - * options, see Prism::parse. - */ -static VALUE -parse_file(int argc, VALUE *argv, VALUE self) { - pm_string_t input; - pm_options_t options = { 0 }; - - file_options(argc, argv, &input, &options); - - VALUE value = parse_input(&input, &options); - pm_string_free(&input); - pm_options_free(&options); - - return value; -} - /** * Parse the given input and return an array of Comment objects. */ @@ -888,7 +985,8 @@ parse_file_comments(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; - file_options(argc, argv, &input, &options); + VALUE encoded_filepath; + file_options(argc, argv, &input, &options, &encoded_filepath); VALUE value = parse_input_comments(&input, &options); pm_string_free(&input); @@ -899,9 +997,9 @@ parse_file_comments(int argc, VALUE *argv, VALUE self) { /** * call-seq: - * Prism::parse_lex(source, **options) -> ParseResult + * Prism::parse_lex(source, **options) -> ParseLexResult * - * Parse the given string and return a ParseResult instance that contains a + * Parse the given string and return a ParseLexResult instance that contains a * 2-element array, where the first element is the AST and the second element is * an array of Token instances. * @@ -926,9 +1024,9 @@ parse_lex(int argc, VALUE *argv, VALUE self) { /** * call-seq: - * Prism::parse_lex_file(filepath, **options) -> ParseResult + * Prism::parse_lex_file(filepath, **options) -> ParseLexResult * - * Parse the given file and return a ParseResult instance that contains a + * Parse the given file and return a ParseLexResult instance that contains a * 2-element array, where the first element is the AST and the second element is * an array of Token instances. * @@ -943,7 +1041,8 @@ parse_lex_file(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; - file_options(argc, argv, &input, &options); + VALUE encoded_filepath; + file_options(argc, argv, &input, &options, &encoded_filepath); VALUE value = parse_lex_input(&input, &options, true); pm_string_free(&input); @@ -1013,7 +1112,8 @@ parse_file_success_p(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; - file_options(argc, argv, &input, &options); + VALUE encoded_filepath; + file_options(argc, argv, &input, &options, &encoded_filepath); VALUE result = parse_input_success_p(&input, &options); pm_string_free(&input); @@ -1035,300 +1135,65 @@ parse_file_failure_p(int argc, VALUE *argv, VALUE self) { } /******************************************************************************/ -/* Utility functions exposed to make testing easier */ +/* String query methods */ /******************************************************************************/ /** - * call-seq: - * Debug::named_captures(source) -> Array - * - * Returns an array of strings corresponding to the named capture groups in the - * given source string. If prism was unable to parse the regular expression, - * this function returns nil. - */ -static VALUE -named_captures(VALUE self, VALUE source) { - pm_string_list_t string_list = { 0 }; - - if (!pm_regexp_named_capture_group_names((const uint8_t *) RSTRING_PTR(source), RSTRING_LEN(source), &string_list, false, PM_ENCODING_UTF_8_ENTRY)) { - pm_string_list_free(&string_list); - return Qnil; - } - - VALUE names = rb_ary_new(); - for (size_t index = 0; index < string_list.length; index++) { - const pm_string_t *string = &string_list.strings[index]; - rb_ary_push(names, rb_str_new((const char *) pm_string_source(string), pm_string_length(string))); - } - - pm_string_list_free(&string_list); - return names; -} - -/** - * call-seq: - * Debug::integer_parse(source) -> [Integer, String] - * - * Parses the given source string and returns the integer it represents, as well - * as a decimal string representation. - */ -static VALUE -integer_parse(VALUE self, VALUE source) { - const uint8_t *start = (const uint8_t *) RSTRING_PTR(source); - size_t length = RSTRING_LEN(source); - - pm_integer_t integer = { 0 }; - pm_integer_parse(&integer, PM_INTEGER_BASE_UNKNOWN, start, start + length); - - pm_buffer_t buffer = { 0 }; - pm_integer_string(&buffer, &integer); - - VALUE string = rb_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer)); - pm_buffer_free(&buffer); - - VALUE result = rb_ary_new_capa(2); - rb_ary_push(result, pm_integer_new(&integer)); - rb_ary_push(result, string); - pm_integer_free(&integer); - - return result; -} - -/** - * call-seq: - * Debug::memsize(source) -> { length: xx, memsize: xx, node_count: xx } - * - * Return a hash of information about the given source string's memory usage. - */ -static VALUE -memsize(VALUE self, VALUE string) { - pm_parser_t parser; - size_t length = RSTRING_LEN(string); - pm_parser_init(&parser, (const uint8_t *) RSTRING_PTR(string), length, NULL); - - pm_node_t *node = pm_parse(&parser); - pm_memsize_t memsize; - pm_node_memsize(node, &memsize); - - pm_node_destroy(&parser, node); - pm_parser_free(&parser); - - VALUE result = rb_hash_new(); - rb_hash_aset(result, ID2SYM(rb_intern("length")), INT2FIX(length)); - rb_hash_aset(result, ID2SYM(rb_intern("memsize")), INT2FIX(memsize.memsize)); - rb_hash_aset(result, ID2SYM(rb_intern("node_count")), INT2FIX(memsize.node_count)); - return result; -} - -/** - * call-seq: - * Debug::profile_file(filepath) -> nil - * - * Parse the file, but do nothing with the result. This is used to profile the - * parser for memory and speed. + * Process the result of a call to a string query method and return an + * appropriate value. */ static VALUE -profile_file(VALUE self, VALUE filepath) { - pm_string_t input; - - const char *checked = check_string(filepath); - Check_Type(filepath, T_STRING); - - if (!pm_string_mapped_init(&input, checked)) { -#ifdef _WIN32 - int e = rb_w32_map_errno(GetLastError()); -#else - int e = errno; -#endif - - rb_syserr_fail(e, checked); +string_query(pm_string_query_t result) { + switch (result) { + case PM_STRING_QUERY_ERROR: + rb_raise(rb_eArgError, "Invalid or non ascii-compatible encoding"); + return Qfalse; + case PM_STRING_QUERY_FALSE: + return Qfalse; + case PM_STRING_QUERY_TRUE: + return Qtrue; } - - pm_options_t options = { 0 }; - pm_options_filepath_set(&options, checked); - - pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), &options); - - pm_node_t *node = pm_parse(&parser); - pm_node_destroy(&parser, node); - pm_parser_free(&parser); - pm_options_free(&options); - pm_string_free(&input); - - return Qnil; + return Qfalse; } -#ifndef PRISM_EXCLUDE_PRETTYPRINT - /** * call-seq: - * Debug::inspect_node(source) -> inspected + * Prism::StringQuery::local?(string) -> bool * - * Inspect the AST that represents the given source using the prism pretty print - * as opposed to the Ruby implementation. + * Returns true if the string constitutes a valid local variable name. Note that + * this means the names that can be set through Binding#local_variable_set, not + * necessarily the ones that can be set through a local variable assignment. */ static VALUE -inspect_node(VALUE self, VALUE source) { - pm_string_t input; - input_load_string(&input, source); - - pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), NULL); - - pm_node_t *node = pm_parse(&parser); - pm_buffer_t buffer = { 0 }; - - pm_prettyprint(&buffer, &parser, node); - - rb_encoding *encoding = rb_enc_find(parser.encoding->name); - VALUE string = rb_enc_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer), encoding); - - pm_buffer_free(&buffer); - pm_node_destroy(&parser, node); - pm_parser_free(&parser); - - return string; +string_query_local_p(VALUE self, VALUE string) { + const uint8_t *source = (const uint8_t *) check_string(string); + return string_query(pm_string_query_local(source, RSTRING_LEN(string), rb_enc_get(string)->name)); } -#endif - /** * call-seq: - * Debug::format_errors(source, colorize) -> String + * Prism::StringQuery::constant?(string) -> bool * - * Format the errors that are found when parsing the given source string. + * Returns true if the string constitutes a valid constant name. Note that this + * means the names that can be set through Module#const_set, not necessarily the + * ones that can be set through a constant assignment. */ static VALUE -format_errors(VALUE self, VALUE source, VALUE colorize) { - pm_string_t input; - input_load_string(&input, source); - - pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), NULL); - - pm_node_t *node = pm_parse(&parser); - pm_buffer_t buffer = { 0 }; - - pm_parser_errors_format(&parser, &parser.error_list, &buffer, RTEST(colorize), true); - - rb_encoding *encoding = rb_enc_find(parser.encoding->name); - VALUE result = rb_enc_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer), encoding); - - pm_buffer_free(&buffer); - pm_node_destroy(&parser, node); - pm_parser_free(&parser); - pm_string_free(&input); - - return result; +string_query_constant_p(VALUE self, VALUE string) { + const uint8_t *source = (const uint8_t *) check_string(string); + return string_query(pm_string_query_constant(source, RSTRING_LEN(string), rb_enc_get(string)->name)); } /** * call-seq: - * Debug::static_inspect(source) -> String - * - * Inspect the node as it would be inspected by the warnings used in static - * literal sets. - */ -static VALUE -static_inspect(int argc, VALUE *argv, VALUE self) { - pm_string_t input; - pm_options_t options = { 0 }; - string_options(argc, argv, &input, &options); - - pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), &options); - - pm_node_t *program = pm_parse(&parser); - pm_node_t *node = ((pm_program_node_t *) program)->statements->body.nodes[0]; - - pm_buffer_t buffer = { 0 }; - pm_static_literal_inspect(&buffer, &parser.newline_list, parser.start_line, parser.encoding->name, node); - - rb_encoding *encoding = rb_enc_find(parser.encoding->name); - VALUE result = rb_enc_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer), encoding); - - pm_buffer_free(&buffer); - pm_node_destroy(&parser, program); - pm_parser_free(&parser); - pm_string_free(&input); - pm_options_free(&options); - - return result; -} - -/** - * call-seq: Debug::Encoding.all -> Array[Debug::Encoding] + * Prism::StringQuery::method_name?(string) -> bool * - * Return an array of all of the encodings that prism knows about. + * Returns true if the string constitutes a valid method name. */ static VALUE -encoding_all(VALUE self) { - VALUE encodings = rb_ary_new(); - - for (size_t index = 0; index < PM_ENCODING_MAXIMUM; index++) { - const pm_encoding_t *encoding = &pm_encodings[index]; - - VALUE encoding_argv[] = { rb_str_new_cstr(encoding->name), encoding->multibyte ? Qtrue : Qfalse }; - rb_ary_push(encodings, rb_class_new_instance(2, encoding_argv, rb_cPrismDebugEncoding)); - } - - return encodings; -} - -static const pm_encoding_t * -encoding_find(VALUE name) { - const uint8_t *source = (const uint8_t *) RSTRING_PTR(name); - size_t length = RSTRING_LEN(name); - - const pm_encoding_t *encoding = pm_encoding_find(source, source + length); - if (encoding == NULL) { rb_raise(rb_eArgError, "Unknown encoding: %s", source); } - - return encoding; -} - -/** - * call-seq: Debug::Encoding.width(source) -> Integer - * - * Returns the width of the first character in the given string if it is valid - * in the encoding. If it is not, this function returns 0. - */ -static VALUE -encoding_char_width(VALUE self, VALUE name, VALUE value) { - return ULONG2NUM(encoding_find(name)->char_width((const uint8_t *) RSTRING_PTR(value), RSTRING_LEN(value))); -} - -/** - * call-seq: Debug::Encoding.alnum?(source) -> true | false - * - * Returns true if the first character in the given string is an alphanumeric - * character in the encoding. - */ -static VALUE -encoding_alnum_char(VALUE self, VALUE name, VALUE value) { - return encoding_find(name)->alnum_char((const uint8_t *) RSTRING_PTR(value), RSTRING_LEN(value)) > 0 ? Qtrue : Qfalse; -} - -/** - * call-seq: Debug::Encoding.alpha?(source) -> true | false - * - * Returns true if the first character in the given string is an alphabetic - * character in the encoding. - */ -static VALUE -encoding_alpha_char(VALUE self, VALUE name, VALUE value) { - return encoding_find(name)->alpha_char((const uint8_t *) RSTRING_PTR(value), RSTRING_LEN(value)) > 0 ? Qtrue : Qfalse; -} - -/** - * call-seq: Debug::Encoding.upper?(source) -> true | false - * - * Returns true if the first character in the given string is an uppercase - * character in the encoding. - */ -static VALUE -encoding_isupper_char(VALUE self, VALUE name, VALUE value) { - return encoding_find(name)->isupper_char((const uint8_t *) RSTRING_PTR(value), RSTRING_LEN(value)) ? Qtrue : Qfalse; +string_query_method_name_p(VALUE self, VALUE string) { + const uint8_t *source = (const uint8_t *) check_string(string); + return string_query(pm_string_query_method_name(source, RSTRING_LEN(string), rb_enc_get(string)->name)); } /******************************************************************************/ @@ -1364,22 +1229,24 @@ Init_prism(void) { rb_cPrismMagicComment = rb_define_class_under(rb_cPrism, "MagicComment", rb_cObject); rb_cPrismParseError = rb_define_class_under(rb_cPrism, "ParseError", rb_cObject); rb_cPrismParseWarning = rb_define_class_under(rb_cPrism, "ParseWarning", rb_cObject); - rb_cPrismResult = rb_define_class_under(rb_cPrism, "Result", rb_cObject); rb_cPrismParseResult = rb_define_class_under(rb_cPrism, "ParseResult", rb_cPrismResult); + rb_cPrismLexResult = rb_define_class_under(rb_cPrism, "LexResult", rb_cPrismResult); rb_cPrismParseLexResult = rb_define_class_under(rb_cPrism, "ParseLexResult", rb_cPrismResult); - - // Intern all of the options that we support so that we don't have to do it - // every time we parse. - rb_option_id_command_line = rb_intern_const("command_line"); - rb_option_id_encoding = rb_intern_const("encoding"); - rb_option_id_filepath = rb_intern_const("filepath"); - rb_option_id_frozen_string_literal = rb_intern_const("frozen_string_literal"); - rb_option_id_line = rb_intern_const("line"); - rb_option_id_scopes = rb_intern_const("scopes"); - rb_option_id_version = rb_intern_const("version"); - - rb_prism_source_id_for = rb_intern("for"); + rb_cPrismStringQuery = rb_define_class_under(rb_cPrism, "StringQuery", rb_cObject); + + // Intern all of the IDs eagerly that we support so that we don't have to do + // it every time we parse. + rb_id_option_command_line = rb_intern_const("command_line"); + rb_id_option_encoding = rb_intern_const("encoding"); + rb_id_option_filepath = rb_intern_const("filepath"); + rb_id_option_frozen_string_literal = rb_intern_const("frozen_string_literal"); + rb_id_option_line = rb_intern_const("line"); + rb_id_option_main_script = rb_intern_const("main_script"); + rb_id_option_partial_script = rb_intern_const("partial_script"); + rb_id_option_scopes = rb_intern_const("scopes"); + rb_id_option_version = rb_intern_const("version"); + rb_id_source_for = rb_intern("for"); /** * The version of the prism library. @@ -1390,8 +1257,10 @@ Init_prism(void) { rb_define_singleton_method(rb_cPrism, "lex", lex, -1); rb_define_singleton_method(rb_cPrism, "lex_file", lex_file, -1); rb_define_singleton_method(rb_cPrism, "parse", parse, -1); - rb_define_singleton_method(rb_cPrism, "parse_stream", parse_stream, -1); rb_define_singleton_method(rb_cPrism, "parse_file", parse_file, -1); + rb_define_singleton_method(rb_cPrism, "profile", profile, -1); + rb_define_singleton_method(rb_cPrism, "profile_file", profile_file, -1); + rb_define_singleton_method(rb_cPrism, "parse_stream", parse_stream, -1); rb_define_singleton_method(rb_cPrism, "parse_comments", parse_comments, -1); rb_define_singleton_method(rb_cPrism, "parse_file_comments", parse_file_comments, -1); rb_define_singleton_method(rb_cPrism, "parse_lex", parse_lex, -1); @@ -1406,28 +1275,9 @@ Init_prism(void) { rb_define_singleton_method(rb_cPrism, "dump_file", dump_file, -1); #endif - // Next, the functions that will be called by the parser to perform various - // internal tasks. We expose these to make them easier to test. - VALUE rb_cPrismDebug = rb_define_module_under(rb_cPrism, "Debug"); - rb_define_singleton_method(rb_cPrismDebug, "named_captures", named_captures, 1); - rb_define_singleton_method(rb_cPrismDebug, "integer_parse", integer_parse, 1); - rb_define_singleton_method(rb_cPrismDebug, "memsize", memsize, 1); - rb_define_singleton_method(rb_cPrismDebug, "profile_file", profile_file, 1); - rb_define_singleton_method(rb_cPrismDebug, "format_errors", format_errors, 2); - rb_define_singleton_method(rb_cPrismDebug, "static_inspect", static_inspect, -1); - -#ifndef PRISM_EXCLUDE_PRETTYPRINT - rb_define_singleton_method(rb_cPrismDebug, "inspect_node", inspect_node, 1); -#endif - - // Next, define the functions that are exposed through the private - // Debug::Encoding class. - rb_cPrismDebugEncoding = rb_define_class_under(rb_cPrismDebug, "Encoding", rb_cObject); - rb_define_singleton_method(rb_cPrismDebugEncoding, "all", encoding_all, 0); - rb_define_singleton_method(rb_cPrismDebugEncoding, "_width", encoding_char_width, 2); - rb_define_singleton_method(rb_cPrismDebugEncoding, "_alnum?", encoding_alnum_char, 2); - rb_define_singleton_method(rb_cPrismDebugEncoding, "_alpha?", encoding_alpha_char, 2); - rb_define_singleton_method(rb_cPrismDebugEncoding, "_upper?", encoding_isupper_char, 2); + rb_define_singleton_method(rb_cPrismStringQuery, "local?", string_query_local_p, 1); + rb_define_singleton_method(rb_cPrismStringQuery, "constant?", string_query_constant_p, 1); + rb_define_singleton_method(rb_cPrismStringQuery, "method_name?", string_query_method_name_p, 1); // Next, initialize the other APIs. Init_prism_api_node(); diff --git a/ext/prism/extension.h b/ext/prism/extension.h index 93ad58fdc8f..5241f8dc1e5 100644 --- a/ext/prism/extension.h +++ b/ext/prism/extension.h @@ -1,7 +1,7 @@ #ifndef PRISM_EXT_NODE_H #define PRISM_EXT_NODE_H -#define EXPECTED_PRISM_VERSION "0.28.0" +#define EXPECTED_PRISM_VERSION "1.2.0" #include #include @@ -14,6 +14,6 @@ VALUE pm_integer_new(const pm_integer_t *integer); void Init_prism_api_node(void); void Init_prism_pack(void); -PRISM_EXPORTED_FUNCTION void Init_prism(void); +RUBY_FUNC_EXPORTED void Init_prism(void); #endif diff --git a/fuzz/regexp.c b/fuzz/regexp.c index 45fa58d87e5..3837d74d572 100644 --- a/fuzz/regexp.c +++ b/fuzz/regexp.c @@ -1,8 +1,21 @@ #include +void +regexp_name_callback(const pm_string_t *name, void *data) { + // Do nothing +} + +void +regexp_error_callback(const uint8_t *start, const uint8_t *end, const char *message, void *data) { + // Do nothing +} + void harness(const uint8_t *input, size_t size) { - pm_string_list_t capture_list = { 0 }; - pm_regexp_named_capture_group_names(input, size, &capture_list, false, PM_ENCODING_UTF_8_ENTRY); - pm_string_list_free(&capture_list); + pm_parser_t parser; + pm_parser_init(&parser, input, size, NULL); + + pm_regexp_parse(&parser, input, size, false, regexp_name_callback, NULL, regexp_error_callback, NULL); + + pm_parser_free(&parser); } diff --git a/gemfiles/2.7/Gemfile b/gemfiles/2.7/Gemfile index 813a0a48c9c..5e90f796659 100644 --- a/gemfiles/2.7/Gemfile +++ b/gemfiles/2.7/Gemfile @@ -7,8 +7,9 @@ ruby "~> 2.7.0" gemspec path: "../.." gem "ffi" +gem "onigmo", platforms: :ruby gem "parser" -gem "rake" gem "rake-compiler" +gem "rake" gem "rbs" gem "test-unit" diff --git a/gemfiles/2.7/Gemfile.lock b/gemfiles/2.7/Gemfile.lock index 01bd9d19e32..8a781b0298a 100644 --- a/gemfiles/2.7/Gemfile.lock +++ b/gemfiles/2.7/Gemfile.lock @@ -1,20 +1,21 @@ PATH remote: ../.. specs: - prism (0.28.0) + prism (1.2.0) GEM remote: https://rubygems.org/ specs: ast (2.4.2) ffi (1.16.3) - parser (3.3.1.0) + onigmo (0.1.0) + parser (3.3.5.0) ast (~> 2.4.1) racc - power_assert (2.0.3) - racc (1.7.3) + power_assert (2.0.4) + racc (1.8.1) rake (13.2.1) - rake-compiler (1.2.7) + rake-compiler (1.2.8) rake rbs (3.1.3) test-unit (3.6.2) @@ -25,6 +26,7 @@ PLATFORMS DEPENDENCIES ffi + onigmo parser prism! rake diff --git a/gemfiles/3.0/Gemfile b/gemfiles/3.0/Gemfile index 6c5262c32d3..e754485dd7b 100644 --- a/gemfiles/3.0/Gemfile +++ b/gemfiles/3.0/Gemfile @@ -7,9 +7,10 @@ ruby "~> 3.0.0" gemspec path: "../.." gem "ffi" +gem "onigmo", platforms: :ruby gem "parser" -gem "rake" gem "rake-compiler" +gem "rake" gem "rbs" gem "ruby_memcheck" gem "test-unit" diff --git a/gemfiles/3.0/Gemfile.lock b/gemfiles/3.0/Gemfile.lock index 49d7449301e..2e4832cf31b 100644 --- a/gemfiles/3.0/Gemfile.lock +++ b/gemfiles/3.0/Gemfile.lock @@ -1,29 +1,30 @@ PATH remote: ../.. specs: - prism (0.28.0) + prism (1.2.0) GEM remote: https://rubygems.org/ specs: - abbrev (0.1.2) ast (2.4.2) - ffi (1.16.3) - mini_portile2 (2.8.6) - nokogiri (1.16.4) + ffi (1.17.0) + logger (1.6.1) + mini_portile2 (2.8.7) + nokogiri (1.16.7) mini_portile2 (~> 2.8.2) racc (~> 1.4) - parser (3.3.1.0) + onigmo (0.1.0) + parser (3.3.5.0) ast (~> 2.4.1) racc - power_assert (2.0.3) - racc (1.7.3) + power_assert (2.0.4) + racc (1.8.1) rake (13.2.1) - rake-compiler (1.2.7) + rake-compiler (1.2.8) rake - rbs (3.4.4) - abbrev - ruby_memcheck (2.3.0) + rbs (3.6.1) + logger + ruby_memcheck (3.0.0) nokogiri test-unit (3.6.2) power_assert @@ -33,6 +34,7 @@ PLATFORMS DEPENDENCIES ffi + onigmo parser prism! rake diff --git a/gemfiles/3.1/Gemfile b/gemfiles/3.1/Gemfile index e18079675dc..ac42206a2d8 100644 --- a/gemfiles/3.1/Gemfile +++ b/gemfiles/3.1/Gemfile @@ -7,9 +7,10 @@ ruby "~> 3.1.0" gemspec path: "../.." gem "ffi" +gem "onigmo", platforms: :ruby gem "parser" -gem "rake" gem "rake-compiler" +gem "rake" gem "rbs" gem "ruby_memcheck" gem "test-unit" diff --git a/gemfiles/3.1/Gemfile.lock b/gemfiles/3.1/Gemfile.lock index a66fe29ab38..1b46ad70043 100644 --- a/gemfiles/3.1/Gemfile.lock +++ b/gemfiles/3.1/Gemfile.lock @@ -1,29 +1,30 @@ PATH remote: ../.. specs: - prism (0.28.0) + prism (1.2.0) GEM remote: https://rubygems.org/ specs: - abbrev (0.1.2) ast (2.4.2) - ffi (1.16.3) - mini_portile2 (2.8.6) - nokogiri (1.16.4) + ffi (1.17.0) + logger (1.6.1) + mini_portile2 (2.8.7) + nokogiri (1.16.7) mini_portile2 (~> 2.8.2) racc (~> 1.4) - parser (3.3.1.0) + onigmo (0.1.0) + parser (3.3.5.0) ast (~> 2.4.1) racc - power_assert (2.0.3) - racc (1.7.3) + power_assert (2.0.4) + racc (1.8.1) rake (13.2.1) - rake-compiler (1.2.7) + rake-compiler (1.2.8) rake - rbs (3.4.4) - abbrev - ruby_memcheck (2.3.0) + rbs (3.6.1) + logger + ruby_memcheck (3.0.0) nokogiri test-unit (3.6.2) power_assert @@ -33,6 +34,7 @@ PLATFORMS DEPENDENCIES ffi + onigmo parser prism! rake diff --git a/gemfiles/3.2/Gemfile b/gemfiles/3.2/Gemfile index c260051a003..89a77a8ba8f 100644 --- a/gemfiles/3.2/Gemfile +++ b/gemfiles/3.2/Gemfile @@ -7,9 +7,10 @@ ruby "~> 3.2.0" gemspec path: "../.." gem "ffi" +gem "onigmo", platforms: :ruby gem "parser" -gem "rake" gem "rake-compiler" +gem "rake" gem "rbs" gem "ruby_memcheck" gem "test-unit" diff --git a/gemfiles/3.2/Gemfile.lock b/gemfiles/3.2/Gemfile.lock index 8000ea805aa..cb86aa3062e 100644 --- a/gemfiles/3.2/Gemfile.lock +++ b/gemfiles/3.2/Gemfile.lock @@ -1,29 +1,30 @@ PATH remote: ../.. specs: - prism (0.28.0) + prism (1.2.0) GEM remote: https://rubygems.org/ specs: - abbrev (0.1.2) ast (2.4.2) - ffi (1.16.3) - mini_portile2 (2.8.6) - nokogiri (1.16.4) + ffi (1.17.0) + logger (1.6.1) + mini_portile2 (2.8.7) + nokogiri (1.16.7) mini_portile2 (~> 2.8.2) racc (~> 1.4) - parser (3.3.1.0) + onigmo (0.1.0) + parser (3.3.5.0) ast (~> 2.4.1) racc - power_assert (2.0.3) - racc (1.7.3) + power_assert (2.0.4) + racc (1.8.1) rake (13.2.1) - rake-compiler (1.2.7) + rake-compiler (1.2.8) rake - rbs (3.4.4) - abbrev - ruby_memcheck (2.3.0) + rbs (3.6.1) + logger + ruby_memcheck (3.0.0) nokogiri test-unit (3.6.2) power_assert @@ -33,6 +34,7 @@ PLATFORMS DEPENDENCIES ffi + onigmo parser prism! rake diff --git a/gemfiles/3.3/Gemfile b/gemfiles/3.3/Gemfile index 2c809a67775..a8c44be84a0 100644 --- a/gemfiles/3.3/Gemfile +++ b/gemfiles/3.3/Gemfile @@ -7,9 +7,10 @@ ruby "~> 3.3.0" gemspec path: "../.." gem "ffi" +gem "onigmo", platforms: :ruby gem "parser" -gem "rake" gem "rake-compiler" +gem "rake" gem "rbs" gem "ruby_memcheck" gem "test-unit" diff --git a/gemfiles/3.3/Gemfile.lock b/gemfiles/3.3/Gemfile.lock index 636cc21f461..59feebfe9c3 100644 --- a/gemfiles/3.3/Gemfile.lock +++ b/gemfiles/3.3/Gemfile.lock @@ -1,29 +1,30 @@ PATH remote: ../.. specs: - prism (0.28.0) + prism (1.2.0) GEM remote: https://rubygems.org/ specs: - abbrev (0.1.2) ast (2.4.2) - ffi (1.16.3) - mini_portile2 (2.8.6) - nokogiri (1.16.4) + ffi (1.17.0) + logger (1.6.1) + mini_portile2 (2.8.7) + nokogiri (1.16.7) mini_portile2 (~> 2.8.2) racc (~> 1.4) - parser (3.3.1.0) + onigmo (0.1.0) + parser (3.3.5.0) ast (~> 2.4.1) racc - power_assert (2.0.3) - racc (1.7.3) + power_assert (2.0.4) + racc (1.8.1) rake (13.2.1) - rake-compiler (1.2.7) + rake-compiler (1.2.8) rake - rbs (3.4.4) - abbrev - ruby_memcheck (2.3.0) + rbs (3.6.1) + logger + ruby_memcheck (3.0.0) nokogiri test-unit (3.6.2) power_assert @@ -33,6 +34,7 @@ PLATFORMS DEPENDENCIES ffi + onigmo parser prism! rake diff --git a/gemfiles/3.4/Gemfile b/gemfiles/3.4/Gemfile index e506db232d8..0b59662a560 100644 --- a/gemfiles/3.4/Gemfile +++ b/gemfiles/3.4/Gemfile @@ -7,9 +7,10 @@ ruby "~> 3.4.0.dev" gemspec path: "../.." gem "ffi" +gem "onigmo", platforms: :ruby gem "parser" -gem "rake" gem "rake-compiler" +gem "rake" gem "rbs" gem "ruby_memcheck" gem "test-unit" diff --git a/gemfiles/3.4/Gemfile.lock b/gemfiles/3.4/Gemfile.lock index aaf4427ca64..ed27cb31ce1 100644 --- a/gemfiles/3.4/Gemfile.lock +++ b/gemfiles/3.4/Gemfile.lock @@ -1,29 +1,30 @@ PATH remote: ../.. specs: - prism (0.28.0) + prism (1.2.0) GEM remote: https://rubygems.org/ specs: - abbrev (0.1.2) ast (2.4.2) - ffi (1.16.3) - mini_portile2 (2.8.6) - nokogiri (1.16.4) + ffi (1.17.0) + logger (1.6.1) + mini_portile2 (2.8.7) + nokogiri (1.16.7) mini_portile2 (~> 2.8.2) racc (~> 1.4) - parser (3.3.1.0) + onigmo (0.1.0) + parser (3.3.5.0) ast (~> 2.4.1) racc - power_assert (2.0.3) - racc (1.7.3) + power_assert (2.0.4) + racc (1.8.1) rake (13.2.1) - rake-compiler (1.2.7) + rake-compiler (1.2.8) rake - rbs (3.4.4) - abbrev - ruby_memcheck (2.3.0) + rbs (3.6.1) + logger + ruby_memcheck (3.0.0) nokogiri test-unit (3.6.2) power_assert @@ -33,6 +34,7 @@ PLATFORMS DEPENDENCIES ffi + onigmo parser prism! rake diff --git a/gemfiles/jruby/Gemfile.lock b/gemfiles/jruby/Gemfile.lock index d5ec924000a..0435e9328fc 100644 --- a/gemfiles/jruby/Gemfile.lock +++ b/gemfiles/jruby/Gemfile.lock @@ -1,27 +1,30 @@ PATH remote: ../.. specs: - prism (0.28.0) + prism (1.2.0) GEM remote: https://rubygems.org/ specs: ast (2.4.2) - parser (3.3.1.0) + parser (3.3.5.0) ast (~> 2.4.1) racc - power_assert (2.0.3) - racc (1.7.3-java) + power_assert (2.0.4) + racc (1.8.1-java) rake (13.2.1) - rake-compiler (1.2.7) + rake-compiler (1.2.8) rake test-unit (3.6.2) power_assert PLATFORMS universal-java-11 + universal-java-17 universal-java-20 universal-java-21 + universal-java-22 + universal-java-23 DEPENDENCIES parser diff --git a/gemfiles/truffleruby/Gemfile b/gemfiles/truffleruby/Gemfile index b9c6d3b1418..af6b4bc766f 100644 --- a/gemfiles/truffleruby/Gemfile +++ b/gemfiles/truffleruby/Gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" -ruby "~> 3.2.2", engine: "truffleruby", engine_version: "~> 24.0.0" +ruby "~> 3.2.2", engine: "truffleruby", engine_version: "~> 24.1.0" gemspec path: "../.." diff --git a/gemfiles/truffleruby/Gemfile.lock b/gemfiles/truffleruby/Gemfile.lock index 666e1b1e369..2ccb7db5882 100644 --- a/gemfiles/truffleruby/Gemfile.lock +++ b/gemfiles/truffleruby/Gemfile.lock @@ -1,19 +1,19 @@ PATH remote: ../.. specs: - prism (0.28.0) + prism (1.2.0) GEM remote: https://rubygems.org/ specs: ast (2.4.2) - parser (3.3.1.0) + parser (3.3.5.0) ast (~> 2.4.1) racc - power_assert (2.0.3) - racc (1.7.3) + power_assert (2.0.4) + racc (1.8.1) rake (13.2.1) - rake-compiler (1.2.7) + rake-compiler (1.2.8) rake test-unit (3.6.2) power_assert @@ -29,7 +29,7 @@ DEPENDENCIES test-unit RUBY VERSION - ruby 3.2.2p0 (truffleruby 24.0.0) + ruby 3.2.4p0 (truffleruby 24.1.0) BUNDLED WITH 2.2.32 diff --git a/gemfiles/typecheck/Gemfile b/gemfiles/typecheck/Gemfile index 24594774a9d..f448096bb80 100644 --- a/gemfiles/typecheck/Gemfile +++ b/gemfiles/typecheck/Gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" -gemspec path: "../.." +# gemspec path: "../.." gem "minitest" gem "parser" diff --git a/gemfiles/typecheck/Gemfile.lock b/gemfiles/typecheck/Gemfile.lock index cc530d079a6..1812bb06f6d 100644 --- a/gemfiles/typecheck/Gemfile.lock +++ b/gemfiles/typecheck/Gemfile.lock @@ -1,81 +1,75 @@ -PATH - remote: ../.. - specs: - prism (0.28.0) - GEM remote: https://rubygems.org/ specs: - abbrev (0.1.2) - activesupport (7.1.3.2) + activesupport (7.2.1) base64 bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) + concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) - mutex_m - tzinfo (~> 2.0) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) ast (2.4.2) base64 (0.2.0) - bigdecimal (3.1.7) - concurrent-ruby (1.2.3) + bigdecimal (3.1.8) + concurrent-ruby (1.3.4) connection_pool (2.4.1) csv (3.3.0) drb (2.2.1) - erubi (1.12.0) - ffi (1.16.3) + erubi (1.13.0) + ffi (1.17.0) fileutils (1.7.2) - i18n (1.14.4) + i18n (1.14.6) concurrent-ruby (~> 1.0) json (2.7.2) language_server-protocol (3.17.0.3) listen (3.9.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - logger (1.6.0) - minitest (5.22.3) - mutex_m (0.2.0) + logger (1.6.1) + minitest (5.25.1) netrc (0.11.0) - parallel (1.24.0) - parser (3.3.1.0) + parallel (1.26.3) + parser (3.3.5.0) ast (~> 2.4.1) racc - power_assert (2.0.3) - racc (1.7.3) + power_assert (2.0.4) + prism (1.1.0) + racc (1.8.1) rainbow (3.1.1) rake (13.2.1) - rake-compiler (1.2.7) + rake-compiler (1.2.8) rake rb-fsevent (0.11.2) - rb-inotify (0.10.1) + rb-inotify (0.11.1) ffi (~> 1.0) - rbi (0.1.12) - prism (>= 0.18.0, < 0.28) + rbi (0.2.1) + prism (~> 1.0) sorbet-runtime (>= 0.5.9204) - rbs (3.4.4) - abbrev - ruby_parser (3.21.0) + rbs (3.6.1) + logger + ruby_parser (3.21.1) racc (~> 1.5) sexp_processor (~> 4.16) securerandom (0.3.1) - sexp_processor (4.17.1) - sorbet (0.5.11361) - sorbet-static (= 0.5.11361) - sorbet-runtime (0.5.11361) - sorbet-static (0.5.11361-aarch64-linux) - sorbet-static (0.5.11361-universal-darwin) - sorbet-static (0.5.11361-x86_64-linux) - sorbet-static-and-runtime (0.5.11361) - sorbet (= 0.5.11361) - sorbet-runtime (= 0.5.11361) - spoom (1.3.0) + sexp_processor (4.17.2) + sorbet (0.5.11597) + sorbet-static (= 0.5.11597) + sorbet-runtime (0.5.11597) + sorbet-static (0.5.11597-universal-darwin) + sorbet-static (0.5.11597-x86_64-linux) + sorbet-static-and-runtime (0.5.11597) + sorbet (= 0.5.11597) + sorbet-runtime (= 0.5.11597) + spoom (1.5.0) erubi (>= 1.10.0) - prism (>= 0.19.0) + prism (>= 0.28.0) sorbet-static-and-runtime (>= 0.5.10187) thor (>= 0.19.2) - steep (1.7.0.dev.3) + steep (1.8.0) activesupport (>= 5.1) concurrent-ruby (>= 1.1.10) csv (>= 3.0.9) @@ -86,16 +80,16 @@ GEM logger (>= 1.3.0) parser (>= 3.1) rainbow (>= 2.2.2, < 4.0) - rbs (>= 3.1.0) + rbs (~> 3.6.0) securerandom (>= 0.1) strscan (>= 1.0.0) terminal-table (>= 2, < 4) strscan (3.1.0) - tapioca (0.13.3) + tapioca (0.16.3) bundler (>= 2.2.25) netrc (>= 0.11.0) parallel (>= 1.21.0) - rbi (>= 0.1.4, < 0.2) + rbi (~> 0.2) sorbet-static-and-runtime (>= 0.5.11087) spoom (>= 1.2.0) thor (>= 1.2.0) @@ -104,24 +98,22 @@ GEM unicode-display_width (>= 1.1.1, < 3) test-unit (3.6.2) power_assert - thor (1.3.1) + thor (1.3.2) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unicode-display_width (2.5.0) - yard (0.9.36) - yard-sorbet (0.8.1) - sorbet-runtime (>= 0.5) - yard (>= 0.9) + unicode-display_width (2.6.0) + yard (0.9.37) + yard-sorbet (0.9.0) + sorbet-runtime + yard PLATFORMS - aarch64-linux - universal-darwin + arm64-darwin-23 x86_64-linux DEPENDENCIES minitest parser - prism! rake rake-compiler rbs diff --git a/include/prism.h b/include/prism.h index 59067c3021a..6f7b850a316 100644 --- a/include/prism.h +++ b/include/prism.h @@ -219,17 +219,6 @@ PRISM_EXPORTED_FUNCTION const char * pm_token_type_name(pm_token_type_t token_ty */ const char * pm_token_type_human(pm_token_type_t token_type); -/** - * Format the errors on the parser into the given buffer. - * - * @param parser The parser to format the errors for. - * @param error_list The list of errors to format. - * @param buffer The buffer to format the errors into. - * @param colorize Whether or not to colorize the errors with ANSI escape sequences. - * @param inline_messages Whether or not to inline the messages with the source. - */ -PRISM_EXPORTED_FUNCTION void pm_parser_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, pm_buffer_t *buffer, bool colorize, bool inline_messages); - // We optionally support dumping to JSON. For systems that don't want or need // this functionality, it can be turned off with the PRISM_EXCLUDE_JSON define. #ifndef PRISM_EXCLUDE_JSON @@ -245,6 +234,53 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t #endif +/** + * Represents the results of a slice query. + */ +typedef enum { + /** Returned if the encoding given to a slice query was invalid. */ + PM_STRING_QUERY_ERROR = -1, + + /** Returned if the result of the slice query is false. */ + PM_STRING_QUERY_FALSE, + + /** Returned if the result of the slice query is true. */ + PM_STRING_QUERY_TRUE +} pm_string_query_t; + +/** + * Check that the slice is a valid local variable name. + * + * @param source The source to check. + * @param length The length of the source. + * @param encoding_name The name of the encoding of the source. + * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if + * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid. + */ +PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_local(const uint8_t *source, size_t length, const char *encoding_name); + +/** + * Check that the slice is a valid constant name. + * + * @param source The source to check. + * @param length The length of the source. + * @param encoding_name The name of the encoding of the source. + * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if + * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid. + */ +PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_constant(const uint8_t *source, size_t length, const char *encoding_name); + +/** + * Check that the slice is a valid method name. + * + * @param source The source to check. + * @param length The length of the source. + * @param encoding_name The name of the encoding of the source. + * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if + * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid. + */ +PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint8_t *source, size_t length, const char *encoding_name); + /** * @mainpage * diff --git a/include/prism/defines.h b/include/prism/defines.h index 849ca6d0516..e78c7dd75ce 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -25,6 +25,15 @@ #define __STDC_FORMAT_MACROS #include +/** + * When we are parsing using recursive descent, we want to protect against + * malicious payloads that could attempt to crash our parser. We do this by + * specifying a maximum depth to which we are allowed to recurse. + */ +#ifndef PRISM_DEPTH_MAXIMUM + #define PRISM_DEPTH_MAXIMUM 1000 +#endif + /** * By default, we compile with -fvisibility=hidden. When this is enabled, we * need to mark certain functions as being publically-visible. This macro does @@ -118,6 +127,15 @@ # endif #endif +/** + * If PRISM_HAS_NO_FILESYSTEM is defined, then we want to exclude all filesystem + * related code from the library. All filesystem related code should be guarded + * by PRISM_HAS_FILESYSTEM. + */ +#ifndef PRISM_HAS_NO_FILESYSTEM +# define PRISM_HAS_FILESYSTEM +#endif + /** * isinf on Windows is defined as accepting a float, but on POSIX systems it * accepts a float, a double, or a long double. We want to mirror this behavior @@ -203,4 +221,22 @@ #define PRISM_ENCODING_EXCLUDE_FULL #endif +/** + * Support PRISM_LIKELY and PRISM_UNLIKELY to help the compiler optimize its + * branch predication. + */ +#if defined(__GNUC__) || defined(__clang__) + /** The compiler should predicate that this branch will be taken. */ + #define PRISM_LIKELY(x) __builtin_expect(!!(x), 1) + + /** The compiler should predicate that this branch will not be taken. */ + #define PRISM_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else + /** Void because this platform does not support branch prediction hints. */ + #define PRISM_LIKELY(x) (x) + + /** Void because this platform does not support branch prediction hints. */ + #define PRISM_UNLIKELY(x) (x) +#endif + #endif diff --git a/include/prism/node.h b/include/prism/node.h index 8736e59a94d..e8686a327c7 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -56,27 +56,6 @@ void pm_node_list_free(pm_node_list_t *list); */ PRISM_EXPORTED_FUNCTION void pm_node_destroy(pm_parser_t *parser, struct pm_node *node); -/** - * This struct stores the information gathered by the pm_node_memsize function. - * It contains both the memory footprint and additionally metadata about the - * shape of the tree. - */ -typedef struct { - /** The total memory footprint of the node and all of its children. */ - size_t memsize; - - /** The number of children the node has. */ - size_t node_count; -} pm_memsize_t; - -/** - * Calculates the memory footprint of a given node. - * - * @param node The node to calculate the memory footprint of. - * @param memsize The memory footprint of the node and all of its children. - */ -PRISM_EXPORTED_FUNCTION void pm_node_memsize(pm_node_t *node, pm_memsize_t *memsize); - /** * Returns a string representation of the given node type. * diff --git a/include/prism/options.h b/include/prism/options.h index a623ae0b839..c96fa684ac6 100644 --- a/include/prism/options.h +++ b/include/prism/options.h @@ -7,6 +7,7 @@ #define PRISM_OPTIONS_H #include "prism/defines.h" +#include "prism/util/pm_char.h" #include "prism/util/pm_string.h" #include @@ -40,6 +41,23 @@ typedef struct pm_options_scope { pm_string_t *locals; } pm_options_scope_t; +// Forward declaration needed by the callback typedef. +struct pm_options; + +/** + * The callback called when additional switches are found in a shebang comment + * that need to be processed by the runtime. + * + * @param options The options struct that may be updated by this callback. + * Certain fields will be checked for changes, specifically encoding, + * command_line, and frozen_string_literal. + * @param source The source of the shebang comment. + * @param length The length of the source. + * @param shebang_callback_data Any additional data that should be passed along + * to the callback. + */ +typedef void (*pm_options_shebang_callback_t)(struct pm_options *options, const uint8_t *source, size_t length, void *shebang_callback_data); + /** * The version of Ruby syntax that we should be parsing with. This is used to * allow consumers to specify which behavior they want in case they need to @@ -56,7 +74,19 @@ typedef enum { /** * The options that can be passed to the parser. */ -typedef struct { +typedef struct pm_options { + /** + * The callback to call when additional switches are found in a shebang + * comment. + */ + pm_options_shebang_callback_t shebang_callback; + + /** + * Any additional data that should be passed along to the shebang callback + * if one was set. + */ + void *shebang_callback_data; + /** The name of the file that is currently being parsed. */ pm_string_t filepath; @@ -103,6 +133,30 @@ typedef struct { * - PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET */ int8_t frozen_string_literal; + + /** + * Whether or not the encoding magic comments should be respected. This is a + * niche use-case where you want to parse a file with a specific encoding + * but ignore any encoding magic comments at the top of the file. + */ + bool encoding_locked; + + /** + * When the file being parsed is the main script, the shebang will be + * considered for command-line flags (or for implicit -x). The caller needs + * to pass this information to the parser so that it can behave correctly. + */ + bool main_script; + + /** + * When the file being parsed is considered a "partial" script, jumps will + * not be marked as errors if they are not contained within loops/blocks. + * This is used in the case that you're parsing a script that you know will + * be embedded inside another script later, but you do not have that context + * yet. For example, when parsing an ERB template that will be evaluated + * inside another script. + */ + bool partial_script; } pm_options_t; /** @@ -142,6 +196,16 @@ static const uint8_t PM_OPTIONS_COMMAND_LINE_P = 0x10; */ static const uint8_t PM_OPTIONS_COMMAND_LINE_X = 0x20; +/** + * Set the shebang callback option on the given options struct. + * + * @param options The options struct to set the shebang callback on. + * @param shebang_callback The shebang callback to set. + * @param shebang_callback_data Any additional data that should be passed along + * to the callback. + */ +PRISM_EXPORTED_FUNCTION void pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callback_t shebang_callback, void *shebang_callback_data); + /** * Set the filepath option on the given options struct. * @@ -166,6 +230,14 @@ PRISM_EXPORTED_FUNCTION void pm_options_line_set(pm_options_t *options, int32_t */ PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, const char *encoding); +/** + * Set the encoding_locked option on the given options struct. + * + * @param options The options struct to set the encoding_locked value on. + * @param encoding_locked The encoding_locked value to set. + */ +PRISM_EXPORTED_FUNCTION void pm_options_encoding_locked_set(pm_options_t *options, bool encoding_locked); + /** * Set the frozen string literal option on the given options struct. * @@ -194,6 +266,22 @@ PRISM_EXPORTED_FUNCTION void pm_options_command_line_set(pm_options_t *options, */ PRISM_EXPORTED_FUNCTION bool pm_options_version_set(pm_options_t *options, const char *version, size_t length); +/** + * Set the main script option on the given options struct. + * + * @param options The options struct to set the main script value on. + * @param main_script The main script value to set. + */ +PRISM_EXPORTED_FUNCTION void pm_options_main_script_set(pm_options_t *options, bool main_script); + +/** + * Set the partial script option on the given options struct. + * + * @param options The options struct to set the partial script value on. + * @param partial_script The partial script value to set. + */ +PRISM_EXPORTED_FUNCTION void pm_options_partial_script_set(pm_options_t *options, bool partial_script); + /** * Allocate and zero out the scopes array on the given options struct. * @@ -261,6 +349,9 @@ PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options); * | `1` | -l command line option | * | `1` | -a command line option | * | `1` | the version | + * | `1` | encoding locked | + * | `1` | main script | + * | `1` | partial script | * | `4` | the number of scopes | * | ... | the scopes | * @@ -293,8 +384,8 @@ PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options); * * The encoding can have a length of 0, in which case we'll use the default * encoding (UTF-8). If it's not 0, it should correspond to a name of an * encoding that can be passed to `Encoding.find` in Ruby. - * * The frozen string literal and suppress warnings fields are booleans, so - * their values should be either 0 or 1. + * * The frozen string literal, encoding locked, main script, and partial script + * fields are booleans, so their values should be either 0 or 1. * * The number of scopes can be 0. * * @param options The options struct to deserialize into. diff --git a/include/prism/parser.h b/include/prism/parser.h index 8054e332f73..992729d6555 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -82,6 +82,23 @@ typedef enum { PM_HEREDOC_INDENT_TILDE, } pm_heredoc_indent_t; +/** + * All of the information necessary to store to lexing a heredoc. + */ +typedef struct { + /** A pointer to the start of the heredoc identifier. */ + const uint8_t *ident_start; + + /** The length of the heredoc identifier. */ + size_t ident_length; + + /** The type of quote that the heredoc uses. */ + pm_heredoc_quote_t quote; + + /** The type of indentation that the heredoc uses. */ + pm_heredoc_indent_t indent; +} pm_heredoc_lex_mode_t; + /** * When lexing Ruby source, the lexer has a small amount of state to tell which * kind of token it is currently lexing. For example, when we find the start of @@ -210,17 +227,10 @@ typedef struct pm_lex_mode { } string; struct { - /** A pointer to the start of the heredoc identifier. */ - const uint8_t *ident_start; - - /** The length of the heredoc identifier. */ - size_t ident_length; - - /** The type of quote that the heredoc uses. */ - pm_heredoc_quote_t quote; - - /** The type of indentation that the heredoc uses. */ - pm_heredoc_indent_t indent; + /** + * All of the data necessary to lex a heredoc. + */ + pm_heredoc_lex_mode_t base; /** * This is the pointer to the character where lexing should resume @@ -233,7 +243,7 @@ typedef struct pm_lex_mode { * line so that we know how much to dedent each line in the case of * a tilde heredoc. */ - size_t common_whitespace; + size_t *common_whitespace; /** True if the previous token ended with a line continuation. */ bool line_continuation; @@ -364,6 +374,9 @@ typedef enum { /** a rescue statement within a lambda expression */ PM_CONTEXT_LAMBDA_RESCUE, + /** the predicate clause of a loop statement */ + PM_CONTEXT_LOOP_PREDICATE, + /** the top level context */ PM_CONTEXT_MAIN, @@ -379,6 +392,9 @@ typedef enum { /** a rescue statement within a module statement */ PM_CONTEXT_MODULE_RESCUE, + /** a multiple target expression */ + PM_CONTEXT_MULTI_TARGET, + /** a parenthesized expression */ PM_CONTEXT_PARENS, @@ -505,9 +521,9 @@ typedef struct { /** The type of shareable constant value that can be set. */ typedef uint8_t pm_shareable_constant_value_t; static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_NONE = 0x0; -static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_LITERAL = 0x1; -static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING = 0x2; -static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY = 0x4; +static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_LITERAL = PM_SHAREABLE_CONSTANT_NODE_FLAGS_LITERAL; +static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING = PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_EVERYTHING; +static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY = PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY; /** * This tracks an individual local variable in a certain lexical context, as @@ -546,6 +562,17 @@ typedef struct pm_locals { pm_local_t *locals; } pm_locals_t; +/** The flags about scope parameters that can be set. */ +typedef uint8_t pm_scope_parameters_t; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NONE = 0x0; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS = 0x1; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS = 0x2; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_BLOCK = 0x4; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_ALL = 0x8; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_IMPLICIT_DISALLOWED = 0x10; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NUMBERED_INNER = 0x20; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NUMBERED_FOUND = 0x40; + /** * This struct represents a node in a linked list of scopes. Some scopes can see * into their parent scopes, while others cannot. @@ -557,10 +584,19 @@ typedef struct pm_scope { /** The IDs of the locals in the given scope. */ pm_locals_t locals; + /** + * This is a list of the implicit parameters contained within the block. + * These will be processed after the block is parsed to determine the kind + * of parameters node that should be used and to check if any errors need to + * be added. + */ + pm_node_list_t implicit_parameters; + /** * This is a bitfield that indicates the parameters that are being used in - * this scope. It is a combination of the PM_SCOPE_PARAMS_* constants. There - * are three different kinds of parameters that can be used in a scope: + * this scope. It is a combination of the PM_SCOPE_PARAMETERS_* constants. + * There are three different kinds of parameters that can be used in a + * scope: * * - Ordinary parameters (e.g., def foo(bar); end) * - Numbered parameters (e.g., def foo; _1; end) @@ -575,15 +611,7 @@ typedef struct pm_scope { * - def foo(&); end * - def foo(...); end */ - uint8_t parameters; - - /** - * An integer indicating the number of numbered parameters on this scope. - * This is necessary to determine if child blocks are allowed to use - * numbered parameters, and to pass information to consumers of the AST - * about how many numbered parameters exist. - */ - int8_t numbered_parameters; + pm_scope_parameters_t parameters; /** * The current state of constant shareability for this scope. This is @@ -598,20 +626,6 @@ typedef struct pm_scope { bool closed; } pm_scope_t; -static const uint8_t PM_SCOPE_PARAMETERS_NONE = 0x0; -static const uint8_t PM_SCOPE_PARAMETERS_ORDINARY = 0x1; -static const uint8_t PM_SCOPE_PARAMETERS_NUMBERED = 0x2; -static const uint8_t PM_SCOPE_PARAMETERS_IT = 0x4; -static const uint8_t PM_SCOPE_PARAMETERS_TYPE_MASK = 0x7; - -static const uint8_t PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS = 0x8; -static const uint8_t PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS = 0x10; -static const uint8_t PM_SCOPE_PARAMETERS_FORWARDING_BLOCK = 0x20; -static const uint8_t PM_SCOPE_PARAMETERS_FORWARDING_ALL = 0x40; - -static const int8_t PM_SCOPE_NUMBERED_PARAMETERS_DISALLOWED = -1; -static const int8_t PM_SCOPE_NUMBERED_PARAMETERS_NONE = 0; - /** * A struct that represents a stack of boolean values. */ @@ -624,6 +638,13 @@ typedef uint32_t pm_state_stack_t; * it's considering. */ struct pm_parser { + /** + * The next node identifier that will be assigned. This is a unique + * identifier used to track nodes such that the syntax tree can be dropped + * but the node can be found through another parse. + */ + uint32_t node_id; + /** The current state of the lexer. */ pm_lex_state_t lex_state; @@ -853,12 +874,27 @@ struct pm_parser { */ bool parsing_eval; + /** + * Whether or not we are parsing a "partial" script, which is a script that + * will be evaluated in the context of another script, so we should not + * check jumps (next/break/etc.) for validity. + */ + bool partial_script; + /** Whether or not we're at the beginning of a command. */ bool command_start; /** Whether or not we're currently recovering from a syntax error. */ bool recovering; + /** + * This is very specialized behavior for when you want to parse in a context + * that does not respect encoding comments. Its main use case is translating + * into the whitequark/parser AST which re-encodes source files in UTF-8 + * before they are parsed and ignores encoding comments. + */ + bool encoding_locked; + /** * Whether or not the encoding has been changed by a magic comment. We use * this to provide a fast path for the lexer instead of going through the @@ -886,6 +922,12 @@ struct pm_parser { * characters. */ bool current_regular_expression_ascii_only; + + /** + * By default, Ruby always warns about mismatched indentation. This can be + * toggled with a magic comment. + */ + bool warn_mismatched_indentation; }; #endif diff --git a/include/prism/regexp.h b/include/prism/regexp.h index c5ceab11f99..c0b3163e93b 100644 --- a/include/prism/regexp.h +++ b/include/prism/regexp.h @@ -10,7 +10,6 @@ #include "prism/parser.h" #include "prism/encoding.h" #include "prism/util/pm_memchr.h" -#include "prism/util/pm_string_list.h" #include "prism/util/pm_string.h" #include @@ -18,16 +17,27 @@ #include /** - * Parse a regular expression and extract the names of all of the named capture - * groups. + * This callback is called when a named capture group is found. + */ +typedef void (*pm_regexp_name_callback_t)(const pm_string_t *name, void *data); + +/** + * This callback is called when a parse error is found. + */ +typedef void (*pm_regexp_error_callback_t)(const uint8_t *start, const uint8_t *end, const char *message, void *data); + +/** + * Parse a regular expression. * + * @param parser The parser that is currently being used. * @param source The source code to parse. * @param size The size of the source code. - * @param named_captures The list to add the names of the named capture groups. - * @param encoding_changed Whether or not the encoding changed from the default. - * @param encoding The encoding of the source code. - * @return Whether or not the parsing was successful. + * @param extended_mode Whether to parse the regular expression in extended mode. + * @param name_callback The optional callback to call when a named capture group is found. + * @param name_data The optional data to pass to the name callback. + * @param error_callback The callback to call when a parse error is found. + * @param error_data The data to pass to the error callback. */ -PRISM_EXPORTED_FUNCTION bool pm_regexp_named_capture_group_names(const uint8_t *source, size_t size, pm_string_list_t *named_captures, bool encoding_changed, const pm_encoding_t *encoding); +PRISM_EXPORTED_FUNCTION void pm_regexp_parse(pm_parser_t *parser, const uint8_t *source, size_t size, bool extended_mode, pm_regexp_name_callback_t name_callback, void *name_data, pm_regexp_error_callback_t error_callback, void *error_data); #endif diff --git a/include/prism/static_literals.h b/include/prism/static_literals.h index 72706054c13..bd29761899c 100644 --- a/include/prism/static_literals.h +++ b/include/prism/static_literals.h @@ -95,9 +95,10 @@ typedef struct { * @param start_line The line number that the parser starts on. * @param literals The set of static literals to add the node to. * @param node The node to add to the set. + * @param replace Whether to replace the previous node if one already exists. * @return A pointer to the node that is being overwritten, if there is one. */ -pm_node_t * pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node); +pm_node_t * pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace); /** * Free the internal memory associated with the given static literals set. @@ -115,6 +116,6 @@ void pm_static_literals_free(pm_static_literals_t *literals); * @param encoding_name The name of the encoding of the source being parsed. * @param node The node to create a string representation of. */ -PRISM_EXPORTED_FUNCTION void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_newline_list_t *newline_list, int32_t start_line, const char *encoding_name, const pm_node_t *node); +void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_newline_list_t *newline_list, int32_t start_line, const char *encoding_name, const pm_node_t *node); #endif diff --git a/include/prism/util/pm_char.h b/include/prism/util/pm_char.h index 32f698a42b9..deeafd63217 100644 --- a/include/prism/util/pm_char.h +++ b/include/prism/util/pm_char.h @@ -34,8 +34,7 @@ size_t pm_strspn_whitespace(const uint8_t *string, ptrdiff_t length); * @return The number of characters at the start of the string that are * whitespace. */ -size_t -pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_newline_list_t *newline_list); +size_t pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_newline_list_t *newline_list); /** * Returns the number of characters at the start of the string that are inline diff --git a/include/prism/util/pm_constant_pool.h b/include/prism/util/pm_constant_pool.h index 0fe16858a0d..6df23f8f501 100644 --- a/include/prism/util/pm_constant_pool.h +++ b/include/prism/util/pm_constant_pool.h @@ -87,14 +87,6 @@ void pm_constant_id_list_insert(pm_constant_id_list_t *list, size_t index, pm_co */ bool pm_constant_id_list_includes(pm_constant_id_list_t *list, pm_constant_id_t id); -/** - * Get the memory size of a list of constant ids. - * - * @param list The list to get the memory size of. - * @return The memory size of the list. - */ -size_t pm_constant_id_list_memsize(pm_constant_id_list_t *list); - /** * Free the memory associated with a list of constant ids. * diff --git a/include/prism/util/pm_integer.h b/include/prism/util/pm_integer.h index 7f172988b3e..a9e29667034 100644 --- a/include/prism/util/pm_integer.h +++ b/include/prism/util/pm_integer.h @@ -18,12 +18,6 @@ * A structure represents an arbitrary-sized integer. */ typedef struct { - /** - * Embedded value for small integer. This value is set to 0 if the value - * does not fit into uint32_t. - */ - uint32_t value; - /** * The number of allocated values. length is set to 0 if the integer fits * into uint32_t. @@ -35,6 +29,12 @@ typedef struct { */ uint32_t *values; + /** + * Embedded value for small integer. This value is set to 0 if the value + * does not fit into uint32_t. + */ + uint32_t value; + /** * Whether or not the integer is negative. It is stored this way so that a * zeroed pm_integer_t is always positive zero. @@ -48,6 +48,9 @@ typedef struct { * from the string itself. */ typedef enum { + /** The default decimal base, with no prefix. Leading 0s will be ignored. */ + PM_INTEGER_BASE_DEFAULT, + /** The binary base, indicated by a 0b or 0B prefix. */ PM_INTEGER_BASE_BINARY, @@ -79,15 +82,7 @@ typedef enum { * @param start The start of the string. * @param end The end of the string. */ -PRISM_EXPORTED_FUNCTION void pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end); - -/** - * Return the memory size of the integer. - * - * @param integer The integer to get the memory size of. - * @return The size of the memory associated with the integer. - */ -size_t pm_integer_memsize(const pm_integer_t *integer); +void pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end); /** * Compare two integers. This function returns -1 if the left integer is less @@ -100,6 +95,18 @@ size_t pm_integer_memsize(const pm_integer_t *integer); */ int pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right); +/** + * Reduce a ratio of integers to its simplest form. + * + * If either the numerator or denominator do not fit into a 32-bit integer, then + * this function is a no-op. In the future, we may consider reducing even the + * larger numbers, but for now we're going to keep it simple. + * + * @param numerator The numerator of the ratio. + * @param denominator The denominator of the ratio. + */ +void pm_integers_reduce(pm_integer_t *numerator, pm_integer_t *denominator); + /** * Convert an integer to a decimal string. * diff --git a/include/prism/util/pm_newline_list.h b/include/prism/util/pm_newline_list.h index 7ae9b6b3da0..406abe8ba59 100644 --- a/include/prism/util/pm_newline_list.h +++ b/include/prism/util/pm_newline_list.h @@ -80,6 +80,17 @@ pm_newline_list_clear(pm_newline_list_t *list); */ bool pm_newline_list_append(pm_newline_list_t *list, const uint8_t *cursor); +/** + * Returns the line of the given offset. If the offset is not in the list, the + * line of the closest offset less than the given offset is returned. + * + * @param list The list to search. + * @param cursor A pointer to the offset to search for. + * @param start_line The line to start counting from. + * @return The line of the given offset. + */ +int32_t pm_newline_list_line(const pm_newline_list_t *list, const uint8_t *cursor, int32_t start_line); + /** * Returns the line and column of the given offset. If the offset is not in the * list, the line and column of the closest offset less than the given offset diff --git a/include/prism/util/pm_string.h b/include/prism/util/pm_string.h index a68e2a7c912..f99f1abdf38 100644 --- a/include/prism/util/pm_string.h +++ b/include/prism/util/pm_string.h @@ -9,6 +9,7 @@ #include "prism/defines.h" #include +#include #include #include #include @@ -21,6 +22,9 @@ #include #include #include +#elif defined(PRISM_HAS_FILESYSTEM) +#include +#include #endif /** @@ -92,6 +96,26 @@ void pm_string_owned_init(pm_string_t *string, uint8_t *source, size_t length); */ void pm_string_constant_init(pm_string_t *string, const char *source, size_t length); +/** + * Represents the result of calling pm_string_mapped_init or + * pm_string_file_init. We need this additional information because there is + * not a platform-agnostic way to indicate that the file that was attempted to + * be opened was a directory. + */ +typedef enum { + /** Indicates that the string was successfully initialized. */ + PM_STRING_INIT_SUCCESS = 0, + /** + * Indicates a generic error from a string_*_init function, where the type + * of error should be read from `errno` or `GetLastError()`. + */ + PM_STRING_INIT_ERROR_GENERIC = 1, + /** + * Indicates that the file that was attempted to be opened was a directory. + */ + PM_STRING_INIT_ERROR_DIRECTORY = 2 +} pm_string_init_result_t; + /** * Read the file indicated by the filepath parameter into source and load its * contents and size into the given `pm_string_t`. The given `pm_string_t` @@ -105,9 +129,9 @@ void pm_string_constant_init(pm_string_t *string, const char *source, size_t len * * @param string The string to initialize. * @param filepath The filepath to read. - * @return Whether or not the file was successfully mapped. + * @return The success of the read, indicated by the value of the enum. */ -PRISM_EXPORTED_FUNCTION bool pm_string_mapped_init(pm_string_t *string, const char *filepath); +PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_t *string, const char *filepath); /** * Read the file indicated by the filepath parameter into source and load its @@ -116,17 +140,9 @@ PRISM_EXPORTED_FUNCTION bool pm_string_mapped_init(pm_string_t *string, const ch * * @param string The string to initialize. * @param filepath The filepath to read. - * @return Whether or not the file was successfully read. - */ -PRISM_EXPORTED_FUNCTION bool pm_string_file_init(pm_string_t *string, const char *filepath); - -/** - * Returns the memory size associated with the string. - * - * @param string The string to get the memory size of. - * @return The size of the memory associated with the string. + * @return The success of the read, indicated by the value of the enum. */ -size_t pm_string_memsize(const pm_string_t *string); +PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_file_init(pm_string_t *string, const char *filepath); /** * Ensure the string is owned. If it is not, then reinitialize it as owned and diff --git a/include/prism/util/pm_string_list.h b/include/prism/util/pm_string_list.h deleted file mode 100644 index 0d406cc5d80..00000000000 --- a/include/prism/util/pm_string_list.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @file pm_string_list.h - * - * A list of strings. - */ -#ifndef PRISM_STRING_LIST_H -#define PRISM_STRING_LIST_H - -#include "prism/defines.h" -#include "prism/util/pm_string.h" - -#include -#include - -/** - * A list of strings. - */ -typedef struct { - /** The length of the string list. */ - size_t length; - - /** The capacity of the string list that has been allocated. */ - size_t capacity; - - /** A pointer to the start of the string list. */ - pm_string_t *strings; -} pm_string_list_t; - -/** - * Append a pm_string_t to the given string list. - * - * @param string_list The string list to append to. - * @param string The string to append. - */ -void pm_string_list_append(pm_string_list_t *string_list, pm_string_t *string); - -/** - * Free the memory associated with the string list. - * - * @param string_list The string list to free. - */ -PRISM_EXPORTED_FUNCTION void pm_string_list_free(pm_string_list_t *string_list); - -#endif diff --git a/include/prism/version.h b/include/prism/version.h index 195d1dab0a0..e3fd9308cda 100644 --- a/include/prism/version.h +++ b/include/prism/version.h @@ -9,12 +9,12 @@ /** * The major version of the Prism library as an int. */ -#define PRISM_VERSION_MAJOR 0 +#define PRISM_VERSION_MAJOR 1 /** * The minor version of the Prism library as an int. */ -#define PRISM_VERSION_MINOR 28 +#define PRISM_VERSION_MINOR 2 /** * The patch version of the Prism library as an int. @@ -24,6 +24,6 @@ /** * The version of the Prism library as a constant string. */ -#define PRISM_VERSION "0.28.0" +#define PRISM_VERSION "1.2.0" #endif diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index 582f3a39a64..62ba45c93e4 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -15,14 +15,14 @@ 11 11 - 5.10.2 + 5.11.2 com.dylibso.chicory runtime - 0.0.9 + 0.0.12 org.junit.jupiter @@ -37,7 +37,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.5.1 diff --git a/java-wasm/src/test/java/org/prism/DummyTest.java b/java-wasm/src/test/java/org/prism/DummyTest.java index 3bd7bfb79c7..a261b551570 100644 --- a/java-wasm/src/test/java/org/prism/DummyTest.java +++ b/java-wasm/src/test/java/org/prism/DummyTest.java @@ -40,6 +40,9 @@ public void test1() { false, EnumSet.noneOf(ParsingOptions.CommandLine.class), ParsingOptions.SyntaxVersion.LATEST, + false, + false, + false, new byte[][][] {} ); @@ -91,6 +94,9 @@ public void test2() { false, EnumSet.noneOf(ParsingOptions.CommandLine.class), ParsingOptions.SyntaxVersion.LATEST, + false, + false, + false, new byte[][][] {} ); diff --git a/java/org/prism/ParsingOptions.java b/java/org/prism/ParsingOptions.java index 598b07a0be7..35a6a7b0c94 100644 --- a/java/org/prism/ParsingOptions.java +++ b/java/org/prism/ParsingOptions.java @@ -43,10 +43,13 @@ public enum CommandLine { A, E, L, N, P, X }; * @param frozenStringLiteral whether the frozen string literal option has been set * @param commandLine the set of flags that were set on the command line * @param version code of Ruby version which syntax will be used to parse + * @param encodingLocked whether the encoding is locked (should almost always be false) + * @param mainScript whether the file is the main script + * @param partialScript whether the file is a partial script * @param scopes scopes surrounding the code that is being parsed with local variable names defined in every scope * ordered from the outermost scope to the innermost one */ - public static byte[] serialize(byte[] filepath, int line, byte[] encoding, boolean frozenStringLiteral, EnumSet commandLine, SyntaxVersion version, byte[][][] scopes) { + public static byte[] serialize(byte[] filepath, int line, byte[] encoding, boolean frozenStringLiteral, EnumSet commandLine, SyntaxVersion version, boolean encodingLocked, boolean mainScript, boolean partialScript, byte[][][] scopes) { final ByteArrayOutputStream output = new ByteArrayOutputStream(); // filepath @@ -69,10 +72,20 @@ public static byte[] serialize(byte[] filepath, int line, byte[] encoding, boole // version output.write(version.getValue()); + // encodingLocked + output.write(encodingLocked ? 1 : 0); + + // mainScript + output.write(mainScript ? 1 : 0); + + // partialScript + output.write(partialScript ? 1 : 0); + // scopes // number of scopes write(output, serializeInt(scopes.length)); + // local variables in each scope for (byte[][] scope : scopes) { // number of locals diff --git a/javascript/package.json b/javascript/package.json index 80b6e2d3d64..3f2c36943f4 100644 --- a/javascript/package.json +++ b/javascript/package.json @@ -1,6 +1,6 @@ { "name": "@ruby/prism", - "version": "0.28.0", + "version": "1.2.0", "description": "Prism Ruby parser", "type": "module", "main": "src/index.js", diff --git a/javascript/src/parsePrism.js b/javascript/src/parsePrism.js index c1e8b67d621..ea200105bd4 100644 --- a/javascript/src/parsePrism.js +++ b/javascript/src/parsePrism.js @@ -62,6 +62,11 @@ function dumpCommandLineOptions(options) { return value; } +// Convert a boolean value into a serialized byte. +function dumpBooleanOption(value) { + return (value === undefined || value === false || value === null) ? 0 : 1; +} + // Converts the given options into a serialized options string. function dumpOptions(options) { const values = []; @@ -92,20 +97,29 @@ function dumpOptions(options) { } template.push("C"); - values.push(options.frozen_string_literal === undefined ? 0 : 1); + values.push(dumpBooleanOption(options.frozen_string_literal)); template.push("C"); values.push(dumpCommandLineOptions(options)); template.push("C"); - if (!options.version || options.version === "latest" || options.version === "3.4.0") { + if (!options.version || options.version === "latest" || options.version.match(/^3\.4(\.\d+)?$/)) { values.push(0); - } else if (options.version === "3.3.0") { + } else if (options.version.match(/^3\.3(\.\d+)?$/)) { values.push(1); } else { throw new Error(`Unsupported version '${options.version}' in compiler options`); } + template.push("C"); + values.push(options.encoding === false ? 1 : 0); + + template.push("C"); + values.push(dumpBooleanOption(options.main_script)); + + template.push("C"); + values.push(dumpBooleanOption(options.partial_script)); + template.push("L"); if (options.scopes) { const scopes = options.scopes; diff --git a/javascript/test.js b/javascript/test.js index 5b8e17d08cc..58801708cc7 100644 --- a/javascript/test.js +++ b/javascript/test.js @@ -27,7 +27,84 @@ test("node[]", () => { test("string", () => { const result = parse('"foo"'); - assert(result.value.statements.body[0].unescaped === "foo"); + const node = result.value.statements.body[0]; + + assert(!node.isForcedUtf8Encoding()) + assert(!node.isForcedBinaryEncoding()) + + assert(node.unescaped.value === "foo"); + assert(node.unescaped.encoding === "utf-8"); + assert(node.unescaped.validEncoding); +}); + +test("forced utf-8 string using \\u syntax", () => { + const result = parse('# encoding: utf-8\n"\\u{9E7F}"'); + const node = result.value.statements.body[0]; + const str = node.unescaped; + + assert(node.isForcedUtf8Encoding()); + assert(!node.isForcedBinaryEncoding()); + + assert(str.value === "鹿"); + assert(str.encoding === "utf-8"); + assert(str.validEncoding); +}); + +test("forced utf-8 string with invalid byte sequence", () => { + const result = parse('# encoding: utf-8\n"\\xFF\\xFF\\xFF"'); + const node = result.value.statements.body[0]; + const str = node.unescaped; + + assert(node.isForcedUtf8Encoding()); + assert(!node.isForcedBinaryEncoding()); + + assert(str.value === "ÿÿÿ"); + assert(str.encoding === "utf-8"); + assert(!str.validEncoding); +}); + +test("ascii string with embedded utf-8 character", () => { + // # encoding: ascii\n"鹿"' + // # encoding: ascii\n"鹿"' + const ascii_str = new Buffer.from([35, 32, 101, 110, 99, 111, 100, 105, 110, 103, 58, 32, 97, 115, 99, 105, 105, 10, 34, 233, 185, 191, 34]); + const result = parse(ascii_str); + const node = result.value.statements.body[0]; + const str = node.unescaped; + + assert(!node.isForcedUtf8Encoding()); + assert(node.isForcedBinaryEncoding()); + + assert(str.value === "鹿"); + assert(str.encoding === "ascii"); + assert(str.validEncoding); +}); + +test("forced binary string", () => { + const result = parse('# encoding: ascii\n"\\xFF\\xFF\\xFF"'); + const node = result.value.statements.body[0]; + const str = node.unescaped; + + assert(!node.isForcedUtf8Encoding()); + assert(node.isForcedBinaryEncoding()); + + assert(str.value === "ÿÿÿ"); + assert(str.encoding === "ascii"); + assert(str.validEncoding); +}); + +test("forced binary string with Unicode character", () => { + // # encoding: us-ascii\n"\\xFF鹿\\xFF" + const ascii_str = Buffer.from([35, 32, 101, 110, 99, 111, 100, 105, 110, 103, 58, 32, 97, 115, 99, 105, 105, 10, 34, 92, 120, 70, 70, 233, 185, 191, 92, 120, 70, 70, 34]); + const result = parse(ascii_str); + const node = result.value.statements.body[0]; + const str = node.unescaped; + + assert(!node.isForcedUtf8Encoding()); + assert(node.isForcedBinaryEncoding()); + + assert(str.value === "ÿ鹿ÿ"); + assert(str.encoding === "ascii"); + assert(str.validEncoding); }); test("constant", () => { diff --git a/lib/prism.rb b/lib/prism.rb index 19774538e7a..50b14a54861 100644 --- a/lib/prism.rb +++ b/lib/prism.rb @@ -13,7 +13,6 @@ module Prism autoload :BasicVisitor, "prism/visitor" autoload :Compiler, "prism/compiler" - autoload :Debug, "prism/debug" autoload :DesugarCompiler, "prism/desugar_compiler" autoload :Dispatcher, "prism/dispatcher" autoload :DotVisitor, "prism/dot_visitor" @@ -26,13 +25,13 @@ module Prism autoload :Pattern, "prism/pattern" autoload :Reflection, "prism/reflection" autoload :Serialize, "prism/serialize" + autoload :StringQuery, "prism/string_query" autoload :Translation, "prism/translation" autoload :Visitor, "prism/visitor" # Some of these constants are not meant to be exposed, so marking them as # private here. - private_constant :Debug private_constant :LexCompat private_constant :LexRipper @@ -71,21 +70,19 @@ def self.load(source, serialized) require_relative "prism/node" require_relative "prism/node_ext" require_relative "prism/parse_result" -require_relative "prism/parse_result/comments" -require_relative "prism/parse_result/newlines" # This is a Ruby implementation of the prism parser. If we're running on CRuby # and we haven't explicitly set the PRISM_FFI_BACKEND environment variable, then # it's going to require the built library. Otherwise, it's going to require a # module that uses FFI to call into the library. if RUBY_ENGINE == "ruby" and !ENV["PRISM_FFI_BACKEND"] - require "prism/prism" - # The C extension is the default backend on CRuby. Prism::BACKEND = :CEXT -else - require_relative "prism/ffi" + require "prism/prism" +else # The FFI backend is used on other Ruby implementations. Prism::BACKEND = :FFI + + require_relative "prism/ffi" end diff --git a/lib/prism/debug.rb b/lib/prism/debug.rb deleted file mode 100644 index 74f824faa70..00000000000 --- a/lib/prism/debug.rb +++ /dev/null @@ -1,249 +0,0 @@ -# frozen_string_literal: true - -module Prism - # This module is used for testing and debugging and is not meant to be used by - # consumers of this library. - module Debug - # A wrapper around a RubyVM::InstructionSequence that provides a more - # convenient interface for accessing parts of the iseq. - class ISeq # :nodoc: - attr_reader :parts - - def initialize(parts) - @parts = parts - end - - def type - parts[0] - end - - def local_table - parts[10] - end - - def instructions - parts[13] - end - - def each_child - instructions.each do |instruction| - # Only look at arrays. Other instructions are line numbers or - # tracepoint events. - next unless instruction.is_a?(Array) - - instruction.each do |opnd| - # Only look at arrays. Other operands are literals. - next unless opnd.is_a?(Array) - - # Only look at instruction sequences. Other operands are literals. - next unless opnd[0] == "YARVInstructionSequence/SimpleDataFormat" - - yield ISeq.new(opnd) - end - end - end - end - - private_constant :ISeq - - # :call-seq: - # Debug::cruby_locals(source) -> Array - # - # For the given source, compiles with CRuby and returns a list of all of the - # sets of local variables that were encountered. - def self.cruby_locals(source) - verbose, $VERBOSE = $VERBOSE, nil - - begin - locals = [] #: Array[Array[Symbol | Integer]] - stack = [ISeq.new(RubyVM::InstructionSequence.compile(source).to_a)] - - while (iseq = stack.pop) - names = [*iseq.local_table] - names.map!.with_index do |name, index| - # When an anonymous local variable is present in the iseq's local - # table, it is represented as the stack offset from the top. - # However, when these are dumped to binary and read back in, they - # are replaced with the symbol :#arg_rest. To consistently handle - # this, we replace them here with their index. - if name == :"#arg_rest" - names.length - index + 1 - else - name - end - end - - locals << names - iseq.each_child { |child| stack << child } - end - - locals - ensure - $VERBOSE = verbose - end - end - - # Used to hold the place of a local that will be in the local table but - # cannot be accessed directly from the source code. For example, the - # iteration variable in a for loop or the positional parameter on a method - # definition that is destructured. - AnonymousLocal = Object.new - private_constant :AnonymousLocal - - # :call-seq: - # Debug::prism_locals(source) -> Array - # - # For the given source, parses with prism and returns a list of all of the - # sets of local variables that were encountered. - def self.prism_locals(source) - locals = [] #: Array[Array[Symbol | Integer]] - stack = [Prism.parse(source).value] #: Array[Prism::node] - - while (node = stack.pop) - case node - when BlockNode, DefNode, LambdaNode - names = node.locals - params = - if node.is_a?(DefNode) - node.parameters - elsif node.parameters.is_a?(NumberedParametersNode) - nil - else - node.parameters&.parameters - end - - # prism places parameters in the same order that they appear in the - # source. CRuby places them in the order that they need to appear - # according to their own internal calling convention. We mimic that - # order here so that we can compare properly. - if params - sorted = [ - *params.requireds.map do |required| - if required.is_a?(RequiredParameterNode) - required.name - else - AnonymousLocal - end - end, - *params.optionals.map(&:name), - *((params.rest.name || :*) if params.rest && !params.rest.is_a?(ImplicitRestNode)), - *params.posts.map do |post| - if post.is_a?(RequiredParameterNode) - post.name - else - AnonymousLocal - end - end, - *params.keywords.grep(RequiredKeywordParameterNode).map(&:name), - *params.keywords.grep(OptionalKeywordParameterNode).map(&:name), - ] - - sorted << AnonymousLocal if params.keywords.any? - - if params.keyword_rest.is_a?(ForwardingParameterNode) - sorted.push(:*, :**, :&, :"...") - elsif params.keyword_rest.is_a?(KeywordRestParameterNode) - sorted << (params.keyword_rest.name || :**) - end - - # Recurse down the parameter tree to find any destructured - # parameters and add them after the other parameters. - param_stack = params.requireds.concat(params.posts).grep(MultiTargetNode).reverse - while (param = param_stack.pop) - case param - when MultiTargetNode - param_stack.concat(param.rights.reverse) - param_stack << param.rest if param.rest&.expression && !sorted.include?(param.rest.expression.name) - param_stack.concat(param.lefts.reverse) - when RequiredParameterNode - sorted << param.name - when SplatNode - sorted << param.expression.name - end - end - - if params.block - sorted << (params.block.name || :&) - end - - names = sorted.concat(names - sorted) - end - - names.map!.with_index do |name, index| - if name == AnonymousLocal - names.length - index + 1 - else - name - end - end - - locals << names - when ClassNode, ModuleNode, ProgramNode, SingletonClassNode - locals << node.locals - when ForNode - locals << [2] - when PostExecutionNode - locals.push([], []) - when InterpolatedRegularExpressionNode - locals << [] if node.once? - end - - stack.concat(node.compact_child_nodes) - end - - locals - end - - # :call-seq: - # Debug::newlines(source) -> Array - # - # For the given source string, return the byte offsets of every newline in - # the source. - def self.newlines(source) - Prism.parse(source).source.offsets - end - - # A wrapping around prism's internal encoding data structures. This is used - # for reflection and debugging purposes. - class Encoding - # The name of the encoding, that can be passed to Encoding.find. - attr_reader :name - - # Initialize a new encoding with the given name and whether or not it is - # a multibyte encoding. - def initialize(name, multibyte) - @name = name - @multibyte = multibyte - end - - # Whether or not the encoding is a multibyte encoding. - def multibyte? - @multibyte - end - - # Returns the number of bytes of the first character in the source string, - # if it is valid for the encoding. Otherwise, returns 0. - def width(source) - Encoding._width(name, source) - end - - # Returns true if the first character in the source string is a valid - # alphanumeric character for the encoding. - def alnum?(source) - Encoding._alnum?(name, source) - end - - # Returns true if the first character in the source string is a valid - # alphabetic character for the encoding. - def alpha?(source) - Encoding._alpha?(name, source) - end - - # Returns true if the first character in the source string is a valid - # uppercase character for the encoding. - def upper?(source) - Encoding._upper?(name, source) - end - end - end -end diff --git a/lib/prism/desugar_compiler.rb b/lib/prism/desugar_compiler.rb index 9b62c00df32..e3b15fc3b06 100644 --- a/lib/prism/desugar_compiler.rb +++ b/lib/prism/desugar_compiler.rb @@ -2,11 +2,13 @@ module Prism class DesugarAndWriteNode # :nodoc: - attr_reader :node, :source, :read_class, :write_class, :arguments + include DSL - def initialize(node, source, read_class, write_class, *arguments) + attr_reader :node, :default_source, :read_class, :write_class, :arguments + + def initialize(node, default_source, read_class, write_class, **arguments) @node = node - @source = source + @default_source = default_source @read_class = read_class @write_class = write_class @arguments = arguments @@ -14,22 +16,30 @@ def initialize(node, source, read_class, write_class, *arguments) # Desugar `x &&= y` to `x && x = y` def compile - AndNode.new( - source, - read_class.new(source, *arguments, node.name_loc), - write_class.new(source, *arguments, node.name_loc, node.value, node.operator_loc, node.location), - node.operator_loc, - node.location + and_node( + location: node.location, + left: public_send(read_class, location: node.name_loc, **arguments), + right: public_send( + write_class, + location: node.location, + **arguments, + name_loc: node.name_loc, + value: node.value, + operator_loc: node.operator_loc + ), + operator_loc: node.operator_loc ) end end class DesugarOrWriteDefinedNode # :nodoc: - attr_reader :node, :source, :read_class, :write_class, :arguments + include DSL + + attr_reader :node, :default_source, :read_class, :write_class, :arguments - def initialize(node, source, read_class, write_class, *arguments) + def initialize(node, default_source, read_class, write_class, **arguments) @node = node - @source = source + @default_source = default_source @read_class = read_class @write_class = write_class @arguments = arguments @@ -37,35 +47,50 @@ def initialize(node, source, read_class, write_class, *arguments) # Desugar `x ||= y` to `defined?(x) ? x : x = y` def compile - IfNode.new( - source, - node.operator_loc, - DefinedNode.new(source, nil, read_class.new(source, *arguments, node.name_loc), nil, node.operator_loc, node.name_loc), - node.operator_loc, - StatementsNode.new(source, [read_class.new(source, *arguments, node.name_loc)], node.location), - ElseNode.new( - source, - node.operator_loc, - StatementsNode.new( - source, - [write_class.new(source, *arguments, node.name_loc, node.value, node.operator_loc, node.location)], - node.location + if_node( + location: node.location, + if_keyword_loc: node.operator_loc, + predicate: defined_node( + location: node.name_loc, + value: public_send(read_class, location: node.name_loc, **arguments), + keyword_loc: node.operator_loc + ), + then_keyword_loc: node.operator_loc, + statements: statements_node( + location: node.location, + body: [public_send(read_class, location: node.name_loc, **arguments)] + ), + subsequent: else_node( + location: node.location, + else_keyword_loc: node.operator_loc, + statements: statements_node( + location: node.location, + body: [ + public_send( + write_class, + location: node.location, + **arguments, + name_loc: node.name_loc, + value: node.value, + operator_loc: node.operator_loc + ) + ] ), - node.operator_loc, - node.location + end_keyword_loc: node.operator_loc ), - node.operator_loc, - node.location + end_keyword_loc: node.operator_loc ) end end class DesugarOperatorWriteNode # :nodoc: - attr_reader :node, :source, :read_class, :write_class, :arguments + include DSL - def initialize(node, source, read_class, write_class, *arguments) + attr_reader :node, :default_source, :read_class, :write_class, :arguments + + def initialize(node, default_source, read_class, write_class, **arguments) @node = node - @source = source + @default_source = default_source @read_class = read_class @write_class = write_class @arguments = arguments @@ -73,37 +98,43 @@ def initialize(node, source, read_class, write_class, *arguments) # Desugar `x += y` to `x = x + y` def compile - operator_loc = node.operator_loc.chop - - write_class.new( - source, - *arguments, - node.name_loc, - CallNode.new( - source, - 0, - read_class.new(source, *arguments, node.name_loc), - nil, - operator_loc.slice.to_sym, - operator_loc, - nil, - ArgumentsNode.new(source, 0, [node.value], node.value.location), - nil, - nil, - node.location + binary_operator_loc = node.binary_operator_loc.chop + + public_send( + write_class, + location: node.location, + **arguments, + name_loc: node.name_loc, + value: call_node( + location: node.location, + receiver: public_send( + read_class, + location: node.name_loc, + **arguments + ), + name: binary_operator_loc.slice.to_sym, + message_loc: binary_operator_loc, + arguments: arguments_node( + location: node.value.location, + arguments: [node.value] + ) ), - node.operator_loc.copy(start_offset: node.operator_loc.end_offset - 1, length: 1), - node.location + operator_loc: node.binary_operator_loc.copy( + start_offset: node.binary_operator_loc.end_offset - 1, + length: 1 + ) ) end end class DesugarOrWriteNode # :nodoc: - attr_reader :node, :source, :read_class, :write_class, :arguments + include DSL - def initialize(node, source, read_class, write_class, *arguments) + attr_reader :node, :default_source, :read_class, :write_class, :arguments + + def initialize(node, default_source, read_class, write_class, **arguments) @node = node - @source = source + @default_source = default_source @read_class = read_class @write_class = write_class @arguments = arguments @@ -111,12 +142,18 @@ def initialize(node, source, read_class, write_class, *arguments) # Desugar `x ||= y` to `x || x = y` def compile - OrNode.new( - source, - read_class.new(source, *arguments, node.name_loc), - write_class.new(source, *arguments, node.name_loc, node.value, node.operator_loc, node.location), - node.operator_loc, - node.location + or_node( + location: node.location, + left: public_send(read_class, location: node.name_loc, **arguments), + right: public_send( + write_class, + location: node.location, + **arguments, + name_loc: node.name_loc, + value: node.value, + operator_loc: node.operator_loc + ), + operator_loc: node.operator_loc ) end end @@ -125,91 +162,91 @@ def compile class ClassVariableAndWriteNode def desugar # :nodoc: - DesugarAndWriteNode.new(self, source, ClassVariableReadNode, ClassVariableWriteNode, name).compile + DesugarAndWriteNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile end end class ClassVariableOrWriteNode def desugar # :nodoc: - DesugarOrWriteDefinedNode.new(self, source, ClassVariableReadNode, ClassVariableWriteNode, name).compile + DesugarOrWriteDefinedNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile end end class ClassVariableOperatorWriteNode def desugar # :nodoc: - DesugarOperatorWriteNode.new(self, source, ClassVariableReadNode, ClassVariableWriteNode, name).compile + DesugarOperatorWriteNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile end end class ConstantAndWriteNode def desugar # :nodoc: - DesugarAndWriteNode.new(self, source, ConstantReadNode, ConstantWriteNode, name).compile + DesugarAndWriteNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile end end class ConstantOrWriteNode def desugar # :nodoc: - DesugarOrWriteDefinedNode.new(self, source, ConstantReadNode, ConstantWriteNode, name).compile + DesugarOrWriteDefinedNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile end end class ConstantOperatorWriteNode def desugar # :nodoc: - DesugarOperatorWriteNode.new(self, source, ConstantReadNode, ConstantWriteNode, name).compile + DesugarOperatorWriteNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile end end class GlobalVariableAndWriteNode def desugar # :nodoc: - DesugarAndWriteNode.new(self, source, GlobalVariableReadNode, GlobalVariableWriteNode, name).compile + DesugarAndWriteNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile end end class GlobalVariableOrWriteNode def desugar # :nodoc: - DesugarOrWriteDefinedNode.new(self, source, GlobalVariableReadNode, GlobalVariableWriteNode, name).compile + DesugarOrWriteDefinedNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile end end class GlobalVariableOperatorWriteNode def desugar # :nodoc: - DesugarOperatorWriteNode.new(self, source, GlobalVariableReadNode, GlobalVariableWriteNode, name).compile + DesugarOperatorWriteNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile end end class InstanceVariableAndWriteNode def desugar # :nodoc: - DesugarAndWriteNode.new(self, source, InstanceVariableReadNode, InstanceVariableWriteNode, name).compile + DesugarAndWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile end end class InstanceVariableOrWriteNode def desugar # :nodoc: - DesugarOrWriteNode.new(self, source, InstanceVariableReadNode, InstanceVariableWriteNode, name).compile + DesugarOrWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile end end class InstanceVariableOperatorWriteNode def desugar # :nodoc: - DesugarOperatorWriteNode.new(self, source, InstanceVariableReadNode, InstanceVariableWriteNode, name).compile + DesugarOperatorWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile end end class LocalVariableAndWriteNode def desugar # :nodoc: - DesugarAndWriteNode.new(self, source, LocalVariableReadNode, LocalVariableWriteNode, name, depth).compile + DesugarAndWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile end end class LocalVariableOrWriteNode def desugar # :nodoc: - DesugarOrWriteNode.new(self, source, LocalVariableReadNode, LocalVariableWriteNode, name, depth).compile + DesugarOrWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile end end class LocalVariableOperatorWriteNode def desugar # :nodoc: - DesugarOperatorWriteNode.new(self, source, LocalVariableReadNode, LocalVariableWriteNode, name, depth).compile + DesugarOperatorWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile end end diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index cec4b9d6306..5caae440f4c 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -72,6 +72,8 @@ def self.load_exported_functions_from(header, *functions, callbacks) end callback :pm_parse_stream_fgets_t, [:pointer, :int, :pointer], :pointer + enum :pm_string_init_result_t, %i[PM_STRING_INIT_SUCCESS PM_STRING_INIT_ERROR_GENERIC PM_STRING_INIT_ERROR_DIRECTORY] + enum :pm_string_query_t, [:PM_STRING_QUERY_ERROR, -1, :PM_STRING_QUERY_FALSE, :PM_STRING_QUERY_TRUE] load_exported_functions_from( "prism.h", @@ -82,6 +84,9 @@ def self.load_exported_functions_from(header, *functions, callbacks) "pm_serialize_lex", "pm_serialize_parse_lex", "pm_parse_success_p", + "pm_string_query_local", + "pm_string_query_constant", + "pm_string_query_method_name", [:pm_parse_stream_fgets_t] ) @@ -176,13 +181,26 @@ def self.with_string(string) def self.with_file(filepath) raise TypeError unless filepath.is_a?(String) + # On Windows and Mac, it's expected that filepaths will be encoded in + # UTF-8. If they are not, we need to convert them to UTF-8 before + # passing them into pm_string_mapped_init. + if RbConfig::CONFIG["host_os"].match?(/bccwin|cygwin|djgpp|mingw|mswin|wince|darwin/i) && + (encoding = filepath.encoding) != Encoding::ASCII_8BIT && encoding != Encoding::UTF_8 + filepath = filepath.encode(Encoding::UTF_8) + end + FFI::MemoryPointer.new(SIZEOF) do |pm_string| - if LibRubyParser.pm_string_mapped_init(pm_string, filepath) + case (result = LibRubyParser.pm_string_mapped_init(pm_string, filepath)) + when :PM_STRING_INIT_SUCCESS pointer = LibRubyParser.pm_string_source(pm_string) length = LibRubyParser.pm_string_length(pm_string) return yield new(pointer, length, false) - else + when :PM_STRING_INIT_ERROR_GENERIC raise SystemCallError.new(filepath, FFI.errno) + when :PM_STRING_INIT_ERROR_DIRECTORY + raise Errno::EISDIR.new(filepath) + else + raise "Unknown error initializing pm_string_t: #{result.inspect}" end ensure LibRubyParser.pm_string_free(pm_string) @@ -200,8 +218,8 @@ def self.with_file(filepath) class << self # Mirror the Prism.dump API by using the serialization API. - def dump(code, **options) - LibRubyParser::PrismString.with_string(code) { |string| dump_common(string, options) } + def dump(source, **options) + LibRubyParser::PrismString.with_string(source) { |string| dump_common(string, options) } end # Mirror the Prism.dump_file API by using the serialization API. @@ -302,6 +320,27 @@ def parse_file_failure?(filepath, **options) !parse_file_success?(filepath, **options) end + # Mirror the Prism.profile API by using the serialization API. + def profile(source, **options) + LibRubyParser::PrismString.with_string(source) do |string| + LibRubyParser::PrismBuffer.with do |buffer| + LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options)) + nil + end + end + end + + # Mirror the Prism.profile_file API by using the serialization API. + def profile_file(filepath, **options) + LibRubyParser::PrismString.with_file(filepath) do |string| + LibRubyParser::PrismBuffer.with do |buffer| + options[:filepath] = filepath + LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options)) + nil + end + end + end + private def dump_common(string, options) # :nodoc: @@ -376,6 +415,20 @@ def dump_options_command_line(options) end end + # Return the value that should be dumped for the version option. + def dump_options_version(version) + case version + when nil, "latest" + 0 + when /\A3\.3(\.\d+)?\z/ + 1 + when /\A3\.4(\.\d+)?\z/ + 0 + else + raise ArgumentError, "invalid version: #{version}" + end + end + # Convert the given options into a serialized options string. def dump_options(options) template = +"" @@ -394,7 +447,7 @@ def dump_options(options) template << "L" if (encoding = options[:encoding]) - name = encoding.name + name = encoding.is_a?(Encoding) ? encoding.name : encoding values.push(name.bytesize, name.b) template << "A*" else @@ -408,7 +461,16 @@ def dump_options(options) values << dump_options_command_line(options) template << "C" - values << { nil => 0, "3.3.0" => 1, "3.4.0" => 0, "latest" => 0 }.fetch(options[:version]) + values << dump_options_version(options[:version]) + + template << "C" + values << (options[:encoding] == false ? 1 : 0) + + template << "C" + values << (options.fetch(:main_script, false) ? 1 : 0) + + template << "C" + values << (options.fetch(:partial_script, false) ? 1 : 0) template << "L" if (scopes = options[:scopes]) @@ -434,4 +496,39 @@ def dump_options(options) values.pack(template) end end + + # Here we are going to patch StringQuery to put in the class-level methods so + # that it can maintain a consistent interface + class StringQuery + class << self + # Mirrors the C extension's StringQuery::local? method. + def local?(string) + query(LibRubyParser.pm_string_query_local(string, string.bytesize, string.encoding.name)) + end + + # Mirrors the C extension's StringQuery::constant? method. + def constant?(string) + query(LibRubyParser.pm_string_query_constant(string, string.bytesize, string.encoding.name)) + end + + # Mirrors the C extension's StringQuery::method_name? method. + def method_name?(string) + query(LibRubyParser.pm_string_query_method_name(string, string.bytesize, string.encoding.name)) + end + + private + + # Parse the enum result and return an appropriate boolean. + def query(result) + case result + when :PM_STRING_QUERY_ERROR + raise ArgumentError, "Invalid or non ascii-compatible encoding" + when :PM_STRING_QUERY_FALSE + false + when :PM_STRING_QUERY_TRUE + true + end + end + end + end end diff --git a/lib/prism/lex_compat.rb b/lib/prism/lex_compat.rb index 4f8e443a3ba..a83c24cb416 100644 --- a/lib/prism/lex_compat.rb +++ b/lib/prism/lex_compat.rb @@ -481,7 +481,7 @@ def to_a embexpr_balance -= 1 when :on_tstring_content if embexpr_balance == 0 - while index < max_index && tokens[index].event == :on_tstring_content + while index < max_index && tokens[index].event == :on_tstring_content && !token.value.match?(/\\\r?\n\z/) token.value << tokens[index].value index += 1 end diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index d4c9b21079e..4dfcebd638b 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -3,11 +3,28 @@ # Here we are reopening the prism module to provide methods on nodes that aren't # templated and are meant as convenience methods. module Prism + class Node + def deprecated(*replacements) # :nodoc: + location = caller_locations(1, 1) + location = location[0].label if location + suggest = replacements.map { |replacement| "#{self.class}##{replacement}" } + + warn(<<~MSG, category: :deprecated) + [deprecation]: #{self.class}##{location} is deprecated and will be \ + removed in the next major version. Use #{suggest.join("/")} instead. + #{(caller(1, 3) || []).join("\n")} + MSG + end + end + module RegularExpressionOptions # :nodoc: # Returns a numeric value that represents the flags that were used to create # the regular expression. def options - o = flags & (RegularExpressionFlags::IGNORE_CASE | RegularExpressionFlags::EXTENDED | RegularExpressionFlags::MULTI_LINE) + o = 0 + o |= Regexp::IGNORECASE if flags.anybits?(RegularExpressionFlags::IGNORE_CASE) + o |= Regexp::EXTENDED if flags.anybits?(RegularExpressionFlags::EXTENDED) + o |= Regexp::MULTILINE if flags.anybits?(RegularExpressionFlags::MULTI_LINE) o |= Regexp::FIXEDENCODING if flags.anybits?(RegularExpressionFlags::EUC_JP | RegularExpressionFlags::WINDOWS_31J | RegularExpressionFlags::UTF_8) o |= Regexp::NOENCODING if flags.anybits?(RegularExpressionFlags::ASCII_8BIT) o @@ -55,11 +72,12 @@ class StringNode < Node def to_interpolated InterpolatedStringNode.new( source, + -1, + location, frozen? ? InterpolatedStringNodeFlags::FROZEN : 0, opening_loc, - [copy(opening_loc: nil, closing_loc: nil, location: content_loc)], - closing_loc, - location + [copy(location: content_loc, opening_loc: nil, closing_loc: nil)], + closing_loc ) end end @@ -72,10 +90,12 @@ class XStringNode < Node def to_interpolated InterpolatedXStringNode.new( source, + -1, + location, + flags, opening_loc, - [StringNode.new(source, 0, nil, content_loc, nil, unescaped, content_loc)], - closing_loc, - location + [StringNode.new(source, node_id, content_loc, 0, nil, content_loc, nil, unescaped)], + closing_loc ) end end @@ -92,7 +112,19 @@ def value class RationalNode < Node # Returns the value of the node as a Ruby Rational. def value - Rational(numeric.is_a?(IntegerNode) ? numeric.value : slice.chomp("r")) + Rational(numerator, denominator) + end + + # Returns the value of the node as an IntegerNode or a FloatNode. This + # method is deprecated in favor of #value or #numerator/#denominator. + def numeric + deprecated("value", "numerator", "denominator") + + if denominator == 1 + IntegerNode.new(source, -1, location.chop, flags, numerator) + else + FloatNode.new(source, -1, location.chop, 0, numerator.to_f / denominator) + end end end @@ -168,14 +200,13 @@ def full_name # constant read or a missing node. To not cause a breaking change, we # continue to supply that API. def child - warn(<<~MSG, category: :deprecated) - DEPRECATED: ConstantPathNode#child is deprecated and will be removed \ - in the next major version. Use \ - ConstantPathNode#name/ConstantPathNode#name_loc instead. Called from \ - #{caller(1, 1)&.first}. - MSG + deprecated("name", "name_loc") - name ? ConstantReadNode.new(source, name, name_loc) : MissingNode.new(source, location) + if name + ConstantReadNode.new(source, -1, name_loc, 0, name) + else + MissingNode.new(source, -1, location, 0) + end end end @@ -210,14 +241,13 @@ def full_name # constant read or a missing node. To not cause a breaking change, we # continue to supply that API. def child - warn(<<~MSG, category: :deprecated) - DEPRECATED: ConstantPathTargetNode#child is deprecated and will be \ - removed in the next major version. Use \ - ConstantPathTargetNode#name/ConstantPathTargetNode#name_loc instead. \ - Called from #{caller(1, 1)&.first}. - MSG + deprecated("name", "name_loc") - name ? ConstantReadNode.new(source, name, name_loc) : MissingNode.new(source, location) + if name + ConstantReadNode.new(source, -1, name_loc, 0, name) + else + MissingNode.new(source, -1, location, 0) + end end end @@ -250,9 +280,10 @@ def signature end posts.each do |param| - if param.is_a?(MultiTargetNode) + case param + when MultiTargetNode names << [:req] - elsif param.is_a?(NoKeywordsParameterNode) + when NoKeywordsParameterNode, KeywordRestParameterNode, ForwardingParameterNode # Invalid syntax, e.g. "def f(**nil, ...)" moves the NoKeywordsParameterNode to posts raise "Invalid syntax" else @@ -286,4 +317,192 @@ def signature names end end + + class CallNode < Node + # When a call node has the attribute_write flag set, it means that the call + # is using the attribute write syntax. This is either a method call to []= + # or a method call to a method that ends with =. Either way, the = sign is + # present in the source. + # + # Prism returns the message_loc _without_ the = sign attached, because there + # can be any amount of space between the message and the = sign. However, + # sometimes you want the location of the full message including the inner + # space and the = sign. This method provides that. + def full_message_loc + attribute_write? ? message_loc&.adjoin("=") : message_loc + end + end + + class CallOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class ClassVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class ConstantOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class ConstantPathOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class GlobalVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class IndexOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class InstanceVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class LocalVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class CaseMatchNode < Node + # Returns the else clause of the case match node. This method is deprecated + # in favor of #else_clause. + def consequent + deprecated("else_clause") + else_clause + end + end + + class CaseNode < Node + # Returns the else clause of the case node. This method is deprecated in + # favor of #else_clause. + def consequent + deprecated("else_clause") + else_clause + end + end + + class IfNode < Node + # Returns the subsequent if/elsif/else clause of the if node. This method is + # deprecated in favor of #subsequent. + def consequent + deprecated("subsequent") + subsequent + end + end + + class RescueNode < Node + # Returns the subsequent rescue clause of the rescue node. This method is + # deprecated in favor of #subsequent. + def consequent + deprecated("subsequent") + subsequent + end + end + + class UnlessNode < Node + # Returns the else clause of the unless node. This method is deprecated in + # favor of #else_clause. + def consequent + deprecated("else_clause") + else_clause + end + end end diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 63cc72a9664..46bd33d1db4 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -10,7 +10,26 @@ class Source # specialized and more performant `ASCIISource` if no multibyte characters # are present in the source code. def self.for(source, start_line = 1, offsets = []) - source.ascii_only? ? ASCIISource.new(source, start_line, offsets): new(source, start_line, offsets) + if source.ascii_only? + ASCIISource.new(source, start_line, offsets) + elsif source.encoding == Encoding::BINARY + source.force_encoding(Encoding::UTF_8) + + if source.valid_encoding? + new(source, start_line, offsets) + else + # This is an extremely niche use case where the file is marked as + # binary, contains multi-byte characters, and those characters are not + # valid UTF-8. In this case we'll mark it as binary and fall back to + # treating everything as a single-byte character. This _may_ cause + # problems when asking for code units, but it appears to be the + # cleanest solution at the moment. + source.force_encoding(Encoding::BINARY) + ASCIISource.new(source, start_line, offsets) + end + else + new(source, start_line, offsets) + end end # The source code that this source object represents. @@ -85,9 +104,26 @@ def character_column(byte_offset) # This method is tested with UTF-8, UTF-16, and UTF-32. If there is the # concept of code units that differs from the number of characters in other # encodings, it is not captured here. + # + # We purposefully replace invalid and undefined characters with replacement + # characters in this conversion. This happens for two reasons. First, it's + # possible that the given byte offset will not occur on a character + # boundary. Second, it's possible that the source code will contain a + # character that has no equivalent in the given encoding. def code_units_offset(byte_offset, encoding) - byteslice = (source.byteslice(0, byte_offset) or raise).encode(encoding) - (encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE) ? (byteslice.bytesize / 2) : byteslice.length + byteslice = (source.byteslice(0, byte_offset) or raise).encode(encoding, invalid: :replace, undef: :replace) + + if encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE + byteslice.bytesize / 2 + else + byteslice.length + end + end + + # Generate a cache that targets a specific encoding for calculating code + # unit offsets. + def code_units_cache(encoding) + CodeUnitsCache.new(source, encoding) end # Returns the column number in code units for the given encoding for the @@ -119,10 +155,84 @@ def find_line(byte_offset) end end + # A cache that can be used to quickly compute code unit offsets from byte + # offsets. It purposefully provides only a single #[] method to access the + # cache in order to minimize surface area. + # + # Note that there are some known issues here that may or may not be addressed + # in the future: + # + # * The first is that there are issues when the cache computes values that are + # not on character boundaries. This can result in subsequent computations + # being off by one or more code units. + # * The second is that this cache is currently unbounded. In theory we could + # introduce some kind of LRU cache to limit the number of entries, but this + # has not yet been implemented. + # + class CodeUnitsCache + class UTF16Counter # :nodoc: + def initialize(source, encoding) + @source = source + @encoding = encoding + end + + def count(byte_offset, byte_length) + @source.byteslice(byte_offset, byte_length).encode(@encoding, invalid: :replace, undef: :replace).bytesize / 2 + end + end + + class LengthCounter # :nodoc: + def initialize(source, encoding) + @source = source + @encoding = encoding + end + + def count(byte_offset, byte_length) + @source.byteslice(byte_offset, byte_length).encode(@encoding, invalid: :replace, undef: :replace).length + end + end + + private_constant :UTF16Counter, :LengthCounter + + # Initialize a new cache with the given source and encoding. + def initialize(source, encoding) + @source = source + @counter = + if encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE + UTF16Counter.new(source, encoding) + else + LengthCounter.new(source, encoding) + end + + @cache = {} + @offsets = [] + end + + # Retrieve the code units offset from the given byte offset. + def [](byte_offset) + @cache[byte_offset] ||= + if (index = @offsets.bsearch_index { |offset| offset > byte_offset }).nil? + @offsets << byte_offset + @counter.count(0, byte_offset) + elsif index == 0 + @offsets.unshift(byte_offset) + @counter.count(0, byte_offset) + else + @offsets.insert(index, byte_offset) + offset = @offsets[index - 1] + @cache[offset] + @counter.count(offset, byte_offset - offset) + end + end + end + # Specialized version of Prism::Source for source code that includes ASCII # characters only. This class is used to apply performance optimizations that - # cannot be applied to sources that include multibyte characters. Sources that - # include multibyte characters are represented by the Prism::Source class. + # cannot be applied to sources that include multibyte characters. + # + # In the extremely rare case that a source includes multi-byte characters but + # is marked as binary because of a magic encoding comment and it cannot be + # eagerly converted to UTF-8, this class will be used as well. This is because + # at that point we will treat everything as single-byte characters. class ASCIISource < Source # Return the character offset for the given byte offset. def character_offset(byte_offset) @@ -144,9 +254,16 @@ def code_units_offset(byte_offset, encoding) byte_offset end + # Returns a cache that is the identity function in order to maintain the + # same interface. We can do this because code units are always equivalent to + # byte offsets for ASCII-only sources. + def code_units_cache(encoding) + ->(byte_offset) { byte_offset } + end + # Specialized version of `code_units_column` that does not depend on # `code_units_offset`, which is a more expensive operation. This is - # essentialy the same as `Prism::Source#column`. + # essentially the same as `Prism::Source#column`. def code_units_column(byte_offset, encoding) byte_offset - line_start(byte_offset) end @@ -253,6 +370,12 @@ def start_code_units_offset(encoding = Encoding::UTF_16LE) source.code_units_offset(start_offset, encoding) end + # The start offset from the start of the file in code units using the given + # cache to fetch or calculate the value. + def cached_start_code_units_offset(cache) + cache[start_offset] + end + # The byte offset from the beginning of the source where this location ends. def end_offset start_offset + length @@ -269,6 +392,12 @@ def end_code_units_offset(encoding = Encoding::UTF_16LE) source.code_units_offset(end_offset, encoding) end + # The end offset from the start of the file in code units using the given + # cache to fetch or calculate the value. + def cached_end_code_units_offset(cache) + cache[end_offset] + end + # The line number where this location starts. def start_line source.line(start_offset) @@ -303,6 +432,12 @@ def start_code_units_column(encoding = Encoding::UTF_16LE) source.code_units_column(start_offset, encoding) end + # The start column in code units using the given cache to fetch or calculate + # the value. + def cached_start_code_units_column(cache) + cache[start_offset] - cache[source.line_start(start_offset)] + end + # The column number in bytes where this location ends from the start of the # line. def end_column @@ -321,6 +456,12 @@ def end_code_units_column(encoding = Encoding::UTF_16LE) source.code_units_column(end_offset, encoding) end + # The end column in code units using the given cache to fetch or calculate + # the value. + def cached_end_code_units_column(cache) + cache[end_offset] - cache[source.line_start(end_offset)] + end + # Implement the hash pattern matching interface for Location. def deconstruct_keys(keys) { start_offset: start_offset, end_offset: end_offset } @@ -570,10 +711,23 @@ def success? def failure? !success? end + + # Create a code units cache for the given encoding. + def code_units_cache(encoding) + source.code_units_cache(encoding) + end end # This is a result specific to the `parse` and `parse_file` methods. class ParseResult < Result + autoload :Comments, "prism/parse_result/comments" + autoload :Errors, "prism/parse_result/errors" + autoload :Newlines, "prism/parse_result/newlines" + + private_constant :Comments + private_constant :Errors + private_constant :Newlines + # The syntax tree that was parsed from the source code. attr_reader :value @@ -587,6 +741,23 @@ def initialize(value, comments, magic_comments, data_loc, errors, warnings, sour def deconstruct_keys(keys) super.merge!(value: value) end + + # Attach the list of comments to their respective locations in the tree. + def attach_comments! + Comments.new(self).attach! # steep:ignore + end + + # Walk the tree and mark nodes that are on a new line, loosely emulating + # the behavior of CRuby's `:line` tracepoint event. + def mark_newlines! + value.accept(Newlines.new(source.offsets.size)) # steep:ignore + end + + # Returns a string representation of the syntax tree with the errors + # displayed inline. + def errors_format + Errors.new(self).format + end end # This is a result specific to the `lex` and `lex_file` methods. @@ -677,5 +848,11 @@ def ==(other) other.type == type && other.value == value end + + # Returns a string representation of this token. + def inspect + location + super + end end end diff --git a/lib/prism/parse_result/comments.rb b/lib/prism/parse_result/comments.rb index f8f74d25032..22c4148b2c1 100644 --- a/lib/prism/parse_result/comments.rb +++ b/lib/prism/parse_result/comments.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Prism - class ParseResult + class ParseResult < Result # When we've parsed the source, we have both the syntax tree and the list of # comments that we found in the source. This class is responsible for # walking the tree and finding the nearest location to attach each comment. @@ -183,12 +183,5 @@ def nearest_targets(node, comment) [preceding, NodeTarget.new(node), following] end end - - private_constant :Comments - - # Attach the list of comments to their respective locations in the tree. - def attach_comments! - Comments.new(self).attach! # steep:ignore - end end end diff --git a/lib/prism/parse_result/errors.rb b/lib/prism/parse_result/errors.rb new file mode 100644 index 00000000000..847a8442fed --- /dev/null +++ b/lib/prism/parse_result/errors.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require "stringio" + +module Prism + class ParseResult < Result + # An object to represent the set of errors on a parse result. This object + # can be used to format the errors in a human-readable way. + class Errors + # The parse result that contains the errors. + attr_reader :parse_result + + # Initialize a new set of errors from the given parse result. + def initialize(parse_result) + @parse_result = parse_result + end + + # Formats the errors in a human-readable way and return them as a string. + def format + error_lines = {} + parse_result.errors.each do |error| + location = error.location + (location.start_line..location.end_line).each do |line| + error_lines[line] ||= [] + error_lines[line] << error + end + end + + source_lines = parse_result.source.source.lines + source_lines << "" if error_lines.key?(source_lines.size + 1) + + io = StringIO.new + source_lines.each.with_index(1) do |line, line_number| + io.puts(line) + + (error_lines.delete(line_number) || []).each do |error| + location = error.location + + case line_number + when location.start_line + io.print(" " * location.start_column + "^") + + if location.start_line == location.end_line + if location.start_column != location.end_column + io.print("~" * (location.end_column - location.start_column - 1)) + end + + io.puts(" " + error.message) + else + io.puts("~" * (line.bytesize - location.start_column)) + end + when location.end_line + io.puts("~" * location.end_column + " " + error.message) + else + io.puts("~" * line.bytesize) + end + end + end + + io.puts + io.string + end + end + end +end diff --git a/lib/prism/parse_result/newlines.rb b/lib/prism/parse_result/newlines.rb index 927c17fe2f7..a04fa78a75c 100644 --- a/lib/prism/parse_result/newlines.rb +++ b/lib/prism/parse_result/newlines.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Prism - class ParseResult + class ParseResult < Result # The :line tracepoint event gets fired whenever the Ruby VM encounters an # expression on a new line. The types of expressions that can trigger this # event are: @@ -17,21 +17,27 @@ class ParseResult # Note that the logic in this file should be kept in sync with the Java # MarkNewlinesVisitor, since that visitor is responsible for marking the # newlines for JRuby/TruffleRuby. + # + # This file is autoloaded only when `mark_newlines!` is called, so the + # re-opening of the various nodes in this file will only be performed in + # that case. We do that to avoid storing the extra `@newline` instance + # variable on every node if we don't need it. class Newlines < Visitor # Create a new Newlines visitor with the given newline offsets. - def initialize(newline_marked) - @newline_marked = newline_marked + def initialize(lines) + # @type var lines: Integer + @lines = Array.new(1 + lines, false) end # Permit block/lambda nodes to mark newlines within themselves. def visit_block_node(node) - old_newline_marked = @newline_marked - @newline_marked = Array.new(old_newline_marked.size, false) + old_lines = @lines + @lines = Array.new(old_lines.size, false) begin super(node) ensure - @newline_marked = old_newline_marked + @lines = old_lines end end @@ -39,7 +45,7 @@ def visit_block_node(node) # Mark if/unless nodes as newlines. def visit_if_node(node) - node.set_newline_flag(@newline_marked) + node.newline_flag!(@lines) super(node) end @@ -48,17 +54,101 @@ def visit_if_node(node) # Permit statements lists to mark newlines within themselves. def visit_statements_node(node) node.body.each do |child| - child.set_newline_flag(@newline_marked) + child.newline_flag!(@lines) end super(node) end end + end + + class Node + def newline_flag? # :nodoc: + @newline_flag ? true : false + end + + def newline_flag!(lines) # :nodoc: + line = location.start_line + unless lines[line] + lines[line] = true + @newline_flag = true + end + end + end + + class BeginNode < Node + def newline_flag!(lines) # :nodoc: + # Never mark BeginNode with a newline flag, mark children instead. + end + end + + class ParenthesesNode < Node + def newline_flag!(lines) # :nodoc: + # Never mark ParenthesesNode with a newline flag, mark children instead. + end + end + + class IfNode < Node + def newline_flag!(lines) # :nodoc: + predicate.newline_flag!(lines) + end + end + + class UnlessNode < Node + def newline_flag!(lines) # :nodoc: + predicate.newline_flag!(lines) + end + end + + class UntilNode < Node + def newline_flag!(lines) # :nodoc: + predicate.newline_flag!(lines) + end + end + + class WhileNode < Node + def newline_flag!(lines) # :nodoc: + predicate.newline_flag!(lines) + end + end + + class RescueModifierNode < Node + def newline_flag!(lines) # :nodoc: + expression.newline_flag!(lines) + end + end + + class InterpolatedMatchLastLineNode < Node + def newline_flag!(lines) # :nodoc: + first = parts.first + first.newline_flag!(lines) if first + end + end + + class InterpolatedRegularExpressionNode < Node + def newline_flag!(lines) # :nodoc: + first = parts.first + first.newline_flag!(lines) if first + end + end + + class InterpolatedStringNode < Node + def newline_flag!(lines) # :nodoc: + first = parts.first + first.newline_flag!(lines) if first + end + end - private_constant :Newlines + class InterpolatedSymbolNode < Node + def newline_flag!(lines) # :nodoc: + first = parts.first + first.newline_flag!(lines) if first + end + end - # Walk the tree and mark nodes that are on a new line. - def mark_newlines! - value.accept(Newlines.new(Array.new(1 + source.offsets.size, false))) # steep:ignore + class InterpolatedXStringNode < Node + def newline_flag!(lines) # :nodoc: + first = parts.first + first.newline_flag!(lines) if first end end end diff --git a/lib/prism/string_query.rb b/lib/prism/string_query.rb new file mode 100644 index 00000000000..9011051d2b1 --- /dev/null +++ b/lib/prism/string_query.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module Prism + # Query methods that allow categorizing strings based on their context for + # where they could be valid in a Ruby syntax tree. + class StringQuery + # The string that this query is wrapping. + attr_reader :string + + # Initialize a new query with the given string. + def initialize(string) + @string = string + end + + # Whether or not this string is a valid local variable name. + def local? + StringQuery.local?(string) + end + + # Whether or not this string is a valid constant name. + def constant? + StringQuery.constant?(string) + end + + # Whether or not this string is a valid method name. + def method_name? + StringQuery.method_name?(string) + end + end +end diff --git a/lib/prism/translation/parser.rb b/lib/prism/translation/parser.rb index 2d769302c3f..969f2b95b0e 100644 --- a/lib/prism/translation/parser.rb +++ b/lib/prism/translation/parser.rb @@ -1,6 +1,11 @@ # frozen_string_literal: true -require "parser" +begin + require "parser" +rescue LoadError + warn(%q{Error: Unable to load parser. Add `gem "parser"` to your Gemfile.}) + exit(1) +end module Prism module Translation @@ -46,7 +51,7 @@ def parse(source_buffer) source = source_buffer.source offset_cache = build_offset_cache(source) - result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version), scopes: [[]]), offset_cache) + result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version), partial_script: true, encoding: false), offset_cache) build_ast(result.value, offset_cache) ensure @@ -59,7 +64,7 @@ def parse_with_comments(source_buffer) source = source_buffer.source offset_cache = build_offset_cache(source) - result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version), scopes: [[]]), offset_cache) + result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version), partial_script: true, encoding: false), offset_cache) [ build_ast(result.value, offset_cache), @@ -78,7 +83,7 @@ def tokenize(source_buffer, recover = false) offset_cache = build_offset_cache(source) result = begin - unwrap(Prism.parse_lex(source, filepath: source_buffer.name, version: convert_for_prism(version), scopes: [[]]), offset_cache) + unwrap(Prism.parse_lex(source, filepath: source_buffer.name, version: convert_for_prism(version), partial_script: true, encoding: false), offset_cache) rescue ::Parser::SyntaxError raise if !recover end @@ -284,7 +289,7 @@ def build_range(location, offset_cache) def convert_for_prism(version) case version when 33 - "3.3.0" + "3.3.1" when 34 "3.4.0" else diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb index c3116133889..d57b5757d71 100644 --- a/lib/prism/translation/parser/compiler.rb +++ b/lib/prism/translation/parser/compiler.rb @@ -90,7 +90,11 @@ def visit_array_pattern_node(node) end if node.constant - builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(nil, visited, nil), token(node.closing_loc)) + if visited.empty? + builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(token(node.opening_loc), visited, token(node.closing_loc)), token(node.closing_loc)) + else + builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(nil, visited, nil), token(node.closing_loc)) + end else builder.array_pattern(token(node.opening_loc), visited, token(node.closing_loc)) end @@ -105,38 +109,46 @@ def visit_arguments_node(node) # { a: 1 } # ^^^^ def visit_assoc_node(node) + key = node.key + if in_pattern if node.value.is_a?(ImplicitNode) - if node.key.is_a?(SymbolNode) - builder.match_hash_var([node.key.unescaped, srange(node.key.location)]) + if key.is_a?(SymbolNode) + if key.opening.nil? + builder.match_hash_var([key.unescaped, srange(key.location)]) + else + builder.match_hash_var_from_str(token(key.opening_loc), [builder.string_internal([key.unescaped, srange(key.value_loc)])], token(key.closing_loc)) + end else - builder.match_hash_var_from_str(token(node.key.opening_loc), visit_all(node.key.parts), token(node.key.closing_loc)) + builder.match_hash_var_from_str(token(key.opening_loc), visit_all(key.parts), token(key.closing_loc)) end + elsif key.opening.nil? + builder.pair_keyword([key.unescaped, srange(key.location)], visit(node.value)) else - builder.pair_keyword([node.key.unescaped, srange(node.key.location)], visit(node.value)) + builder.pair_quoted(token(key.opening_loc), [builder.string_internal([key.unescaped, srange(key.value_loc)])], token(key.closing_loc), visit(node.value)) end elsif node.value.is_a?(ImplicitNode) if (value = node.value.value).is_a?(LocalVariableReadNode) builder.pair_keyword( - [node.key.unescaped, srange(node.key)], - builder.ident([value.name, srange(node.key.value_loc)]).updated(:lvar) + [key.unescaped, srange(key)], + builder.ident([value.name, srange(key.value_loc)]).updated(:lvar) ) else - builder.pair_label([node.key.unescaped, srange(node.key.location)]) + builder.pair_label([key.unescaped, srange(key.location)]) end elsif node.operator_loc - builder.pair(visit(node.key), token(node.operator_loc), visit(node.value)) - elsif node.key.is_a?(SymbolNode) && node.key.opening_loc.nil? - builder.pair_keyword([node.key.unescaped, srange(node.key.location)], visit(node.value)) + builder.pair(visit(key), token(node.operator_loc), visit(node.value)) + elsif key.is_a?(SymbolNode) && key.opening_loc.nil? + builder.pair_keyword([key.unescaped, srange(key.location)], visit(node.value)) else parts = - if node.key.is_a?(SymbolNode) - [builder.string_internal([node.key.unescaped, srange(node.key.value_loc)])] + if key.is_a?(SymbolNode) + [builder.string_internal([key.unescaped, srange(key.value_loc)])] else - visit_all(node.key.parts) + visit_all(key.parts) end - builder.pair_quoted(token(node.key.opening_loc), parts, token(node.key.closing_loc), visit(node.value)) + builder.pair_quoted(token(key.opening_loc), parts, token(key.closing_loc), visit(node.value)) end end @@ -146,7 +158,9 @@ def visit_assoc_node(node) # { **foo } # ^^^^^ def visit_assoc_splat_node(node) - if node.value.nil? && forwarding.include?(:**) + if in_pattern + builder.match_rest(token(node.operator_loc), token(node.value&.location)) + elsif node.value.nil? && forwarding.include?(:**) builder.forwarded_kwrestarg(token(node.operator_loc)) else builder.kwsplat(token(node.operator_loc), visit(node.value)) @@ -167,7 +181,7 @@ def visit_begin_node(node) if (rescue_clause = node.rescue_clause) begin find_start_offset = (rescue_clause.reference&.location || rescue_clause.exceptions.last&.location || rescue_clause.keyword_loc).end_offset - find_end_offset = (rescue_clause.statements&.location&.start_offset || rescue_clause.consequent&.location&.start_offset || (find_start_offset + 1)) + find_end_offset = (rescue_clause.statements&.location&.start_offset || rescue_clause.subsequent&.location&.start_offset || (find_start_offset + 1)) rescue_bodies << builder.rescue_body( token(rescue_clause.keyword_loc), @@ -177,7 +191,7 @@ def visit_begin_node(node) srange_find(find_start_offset, find_end_offset, [";"]), visit(rescue_clause.statements) ) - end until (rescue_clause = rescue_clause.consequent).nil? + end until (rescue_clause = rescue_clause.subsequent).nil? end begin_body = @@ -328,18 +342,48 @@ def visit_call_operator_write_node(node) [], nil ), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # foo.bar &&= baz # ^^^^^^^^^^^^^^^ - alias visit_call_and_write_node visit_call_operator_write_node + def visit_call_and_write_node(node) + call_operator_loc = node.call_operator_loc + + builder.op_assign( + builder.call_method( + visit(node.receiver), + call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)], + node.message_loc ? [node.read_name, srange(node.message_loc)] : nil, + nil, + [], + nil + ), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # foo.bar ||= baz # ^^^^^^^^^^^^^^^ - alias visit_call_or_write_node visit_call_operator_write_node + def visit_call_or_write_node(node) + call_operator_loc = node.call_operator_loc + + builder.op_assign( + builder.call_method( + visit(node.receiver), + call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)], + node.message_loc ? [node.read_name, srange(node.message_loc)] : nil, + nil, + [], + nil + ), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # foo.bar, = 1 # ^^^^^^^ @@ -366,8 +410,8 @@ def visit_case_node(node) token(node.case_keyword_loc), visit(node.predicate), visit_all(node.conditions), - token(node.consequent&.else_keyword_loc), - visit(node.consequent), + token(node.else_clause&.else_keyword_loc), + visit(node.else_clause), token(node.end_keyword_loc) ) end @@ -379,8 +423,8 @@ def visit_case_match_node(node) token(node.case_keyword_loc), visit(node.predicate), visit_all(node.conditions), - token(node.consequent&.else_keyword_loc), - visit(node.consequent), + token(node.else_clause&.else_keyword_loc), + visit(node.else_clause), token(node.end_keyword_loc) ) end @@ -419,18 +463,30 @@ def visit_class_variable_write_node(node) def visit_class_variable_operator_write_node(node) builder.op_assign( builder.assignable(builder.cvar(token(node.name_loc))), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # @@foo &&= bar # ^^^^^^^^^^^^^ - alias visit_class_variable_and_write_node visit_class_variable_operator_write_node + def visit_class_variable_and_write_node(node) + builder.op_assign( + builder.assignable(builder.cvar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # @@foo ||= bar # ^^^^^^^^^^^^^ - alias visit_class_variable_or_write_node visit_class_variable_operator_write_node + def visit_class_variable_or_write_node(node) + builder.op_assign( + builder.assignable(builder.cvar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # @@foo, = bar # ^^^^^ @@ -458,18 +514,30 @@ def visit_constant_write_node(node) def visit_constant_operator_write_node(node) builder.op_assign( builder.assignable(builder.const([node.name, srange(node.name_loc)])), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # Foo &&= bar # ^^^^^^^^^^^^ - alias visit_constant_and_write_node visit_constant_operator_write_node + def visit_constant_and_write_node(node) + builder.op_assign( + builder.assignable(builder.const([node.name, srange(node.name_loc)])), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # Foo ||= bar # ^^^^^^^^^^^^ - alias visit_constant_or_write_node visit_constant_operator_write_node + def visit_constant_or_write_node(node) + builder.op_assign( + builder.assignable(builder.const([node.name, srange(node.name_loc)])), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # Foo, = bar # ^^^ @@ -512,18 +580,30 @@ def visit_constant_path_write_node(node) def visit_constant_path_operator_write_node(node) builder.op_assign( builder.assignable(visit(node.target)), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # Foo::Bar &&= baz # ^^^^^^^^^^^^^^^^ - alias visit_constant_path_and_write_node visit_constant_path_operator_write_node + def visit_constant_path_and_write_node(node) + builder.op_assign( + builder.assignable(visit(node.target)), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # Foo::Bar ||= baz # ^^^^^^^^^^^^^^^^ - alias visit_constant_path_or_write_node visit_constant_path_operator_write_node + def visit_constant_path_or_write_node(node) + builder.op_assign( + builder.assignable(visit(node.target)), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # Foo::Bar, = baz # ^^^^^^^^ @@ -711,18 +791,30 @@ def visit_global_variable_write_node(node) def visit_global_variable_operator_write_node(node) builder.op_assign( builder.assignable(builder.gvar(token(node.name_loc))), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # $foo &&= bar # ^^^^^^^^^^^^ - alias visit_global_variable_and_write_node visit_global_variable_operator_write_node + def visit_global_variable_and_write_node(node) + builder.op_assign( + builder.assignable(builder.gvar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # $foo ||= bar # ^^^^^^^^^^^^ - alias visit_global_variable_or_write_node visit_global_variable_operator_write_node + def visit_global_variable_or_write_node(node) + builder.op_assign( + builder.assignable(builder.gvar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # $foo, = bar # ^^^^ @@ -766,8 +858,8 @@ def visit_if_node(node) visit(node.predicate), token(node.then_keyword_loc), visit(node.statements), - token(node.consequent.else_keyword_loc), - visit(node.consequent) + token(node.subsequent.else_keyword_loc), + visit(node.subsequent) ) elsif node.if_keyword_loc.start_offset == node.location.start_offset builder.condition( @@ -776,16 +868,16 @@ def visit_if_node(node) if node.then_keyword_loc token(node.then_keyword_loc) else - srange_find(node.predicate.location.end_offset, (node.statements&.location || node.consequent&.location || node.end_keyword_loc).start_offset, [";"]) + srange_find(node.predicate.location.end_offset, (node.statements&.location || node.subsequent&.location || node.end_keyword_loc).start_offset, [";"]) end, visit(node.statements), - case node.consequent + case node.subsequent when IfNode - token(node.consequent.if_keyword_loc) + token(node.subsequent.if_keyword_loc) when ElseNode - token(node.consequent.else_keyword_loc) + token(node.subsequent.else_keyword_loc) end, - visit(node.consequent), + visit(node.subsequent), if node.if_keyword != "elsif" token(node.end_keyword_loc) end @@ -793,7 +885,7 @@ def visit_if_node(node) else builder.condition_mod( visit(node.statements), - visit(node.consequent), + visit(node.subsequent), token(node.if_keyword_loc), visit(node.predicate) ) @@ -803,7 +895,7 @@ def visit_if_node(node) # 1i # ^^ def visit_imaginary_node(node) - visit_numeric(node, builder.complex([imaginary_value(node), srange(node.location)])) + visit_numeric(node, builder.complex([Complex(0, node.numeric.value), srange(node.location)])) end # { foo: } @@ -857,18 +949,46 @@ def visit_index_operator_write_node(node) visit_all(arguments), token(node.closing_loc) ), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # foo[bar] &&= baz # ^^^^^^^^^^^^^^^^ - alias visit_index_and_write_node visit_index_operator_write_node + def visit_index_and_write_node(node) + arguments = node.arguments&.arguments || [] + arguments << node.block if node.block + + builder.op_assign( + builder.index( + visit(node.receiver), + token(node.opening_loc), + visit_all(arguments), + token(node.closing_loc) + ), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # foo[bar] ||= baz # ^^^^^^^^^^^^^^^^ - alias visit_index_or_write_node visit_index_operator_write_node + def visit_index_or_write_node(node) + arguments = node.arguments&.arguments || [] + arguments << node.block if node.block + + builder.op_assign( + builder.index( + visit(node.receiver), + token(node.opening_loc), + visit_all(arguments), + token(node.closing_loc) + ), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # foo[bar], = 1 # ^^^^^^^^ @@ -902,18 +1022,30 @@ def visit_instance_variable_write_node(node) def visit_instance_variable_operator_write_node(node) builder.op_assign( builder.assignable(builder.ivar(token(node.name_loc))), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # @foo &&= bar # ^^^^^^^^^^^^ - alias visit_instance_variable_and_write_node visit_instance_variable_operator_write_node + def visit_instance_variable_and_write_node(node) + builder.op_assign( + builder.assignable(builder.ivar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # @foo ||= bar # ^^^^^^^^^^^^ - alias visit_instance_variable_or_write_node visit_instance_variable_operator_write_node + def visit_instance_variable_or_write_node(node) + builder.op_assign( + builder.assignable(builder.ivar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # @foo, = bar # ^^^^ @@ -946,36 +1078,7 @@ def visit_interpolated_regular_expression_node(node) # ^^^^^^^^^^^^ def visit_interpolated_string_node(node) if node.heredoc? - children, closing = visit_heredoc(node) - opening = token(node.opening_loc) - - start_offset = node.opening_loc.end_offset + 1 - end_offset = node.parts.first.location.start_offset - - # In the below case, the offsets should be the same: - # - # <<~HEREDOC - # a #{b} - # HEREDOC - # - # But in this case, the end_offset would be greater than the start_offset: - # - # <<~HEREDOC - # #{b} - # HEREDOC - # - # So we need to make sure the result node's heredoc range is correct, without updating the children - result = if start_offset < end_offset - # We need to add a padding string to ensure that the heredoc has correct range for its body - padding_string_node = builder.string_internal(["", srange_offsets(start_offset, end_offset)]) - node_with_correct_location = builder.string_compose(opening, [padding_string_node, *children], closing) - # But the padding string should not be included in the final AST, so we need to update the result's children - node_with_correct_location.updated(:dstr, children) - else - builder.string_compose(opening, children, closing) - end - - return result + return visit_heredoc(node) { |children, closing| builder.string_compose(token(node.opening_loc), children, closing) } end parts = if node.parts.one? { |part| part.type == :string_node } @@ -1019,8 +1122,7 @@ def visit_interpolated_symbol_node(node) # ^^^^^^^^^^^^ def visit_interpolated_x_string_node(node) if node.heredoc? - children, closing = visit_heredoc(node) - builder.xstring_compose(token(node.opening_loc), children, closing) + visit_heredoc(node) { |children, closing| builder.xstring_compose(token(node.opening_loc), children, closing) } else builder.xstring_compose( token(node.opening_loc), @@ -1030,6 +1132,12 @@ def visit_interpolated_x_string_node(node) end end + # -> { it } + # ^^ + def visit_it_local_variable_read_node(node) + builder.ident([:it, srange(node.location)]).updated(:lvar) + end + # -> { it } # ^^^^^^^^^ def visit_it_parameters_node(node) @@ -1083,14 +1191,7 @@ def visit_lambda_node(node) # foo # ^^^ def visit_local_variable_read_node(node) - name = node.name - - # This is just a guess. parser doesn't have support for the implicit - # `it` variable yet, so we'll probably have to visit this once it - # does. - name = :it if name == :"0it" - - builder.ident([name, srange(node.location)]).updated(:lvar) + builder.ident([node.name, srange(node.location)]).updated(:lvar) end # foo = 1 @@ -1108,18 +1209,30 @@ def visit_local_variable_write_node(node) def visit_local_variable_operator_write_node(node) builder.op_assign( builder.assignable(builder.ident(token(node.name_loc))), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # foo &&= bar # ^^^^^^^^^^^ - alias visit_local_variable_and_write_node visit_local_variable_operator_write_node + def visit_local_variable_and_write_node(node) + builder.op_assign( + builder.assignable(builder.ident(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # foo ||= bar # ^^^^^^^^^^^ - alias visit_local_variable_or_write_node visit_local_variable_operator_write_node + def visit_local_variable_or_write_node(node) + builder.op_assign( + builder.assignable(builder.ident(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # foo, = bar # ^^^ @@ -1182,13 +1295,9 @@ def visit_module_node(node) # foo, bar = baz # ^^^^^^^^ def visit_multi_target_node(node) - elements = [*node.lefts] - elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) - elements.concat(node.rights) - builder.multi_lhs( token(node.lparen_loc), - visit_all(elements), + visit_all(multi_target_elements(node)), token(node.rparen_loc) ) end @@ -1196,9 +1305,11 @@ def visit_multi_target_node(node) # foo, bar = baz # ^^^^^^^^^^^^^^ def visit_multi_write_node(node) - elements = [*node.lefts] - elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) - elements.concat(node.rights) + elements = multi_target_elements(node) + + if elements.length == 1 && elements.first.is_a?(MultiTargetNode) + elements = multi_target_elements(elements.first) + end builder.multi_assign( builder.multi_lhs( @@ -1279,12 +1390,12 @@ def visit_parameters_node(node) if node.requireds.any? node.requireds.each do |required| - if required.is_a?(RequiredParameterNode) - params << visit(required) - else - compiler = copy_compiler(in_destructure: true) - params << required.accept(compiler) - end + params << + if required.is_a?(RequiredParameterNode) + visit(required) + else + required.accept(copy_compiler(in_destructure: true)) + end end end @@ -1293,12 +1404,12 @@ def visit_parameters_node(node) if node.posts.any? node.posts.each do |post| - if post.is_a?(RequiredParameterNode) - params << visit(post) - else - compiler = copy_compiler(in_destructure: true) - params << post.accept(compiler) - end + params << + if post.is_a?(RequiredParameterNode) + visit(post) + else + post.accept(copy_compiler(in_destructure: true)) + end end end @@ -1384,7 +1495,7 @@ def visit_range_node(node) # 1r # ^^ def visit_rational_node(node) - visit_numeric(node, builder.rational([rational_value(node), srange(node.location)])) + visit_numeric(node, builder.rational([node.value, srange(node.location)])) end # redo @@ -1396,9 +1507,20 @@ def visit_redo_node(node) # /foo/ # ^^^^^ def visit_regular_expression_node(node) + content = node.content + parts = + if content.include?("\n") + offset = node.content_loc.start_offset + content.lines.map do |line| + builder.string_internal([line, srange_offsets(offset, offset += line.bytesize)]) + end + else + [builder.string_internal(token(node.content_loc))] + end + builder.regexp_compose( token(node.opening_loc), - [builder.string_internal(token(node.content_loc))], + parts, [node.closing[0], srange_offsets(node.closing_loc.start_offset, node.closing_loc.start_offset + 1)], builder.regexp_options([node.closing[1..], srange_offsets(node.closing_loc.start_offset + 1, node.closing_loc.end_offset)]) ) @@ -1544,10 +1666,11 @@ def visit_statements_node(node) # ^^^^^ def visit_string_node(node) if node.heredoc? - children, closing = visit_heredoc(node.to_interpolated) - builder.string_compose(token(node.opening_loc), children, closing) + visit_heredoc(node.to_interpolated) { |children, closing| builder.string_compose(token(node.opening_loc), children, closing) } elsif node.opening == "?" builder.character([node.unescaped, srange(node.location)]) + elsif node.opening&.start_with?("%") && node.unescaped.empty? + builder.string_compose(token(node.opening_loc), [], token(node.closing_loc)) else content_lines = node.content.lines unescaped_lines = node.unescaped.lines @@ -1661,16 +1784,16 @@ def visit_unless_node(node) if node.then_keyword_loc token(node.then_keyword_loc) else - srange_find(node.predicate.location.end_offset, (node.statements&.location || node.consequent&.location || node.end_keyword_loc).start_offset, [";"]) + srange_find(node.predicate.location.end_offset, (node.statements&.location || node.else_clause&.location || node.end_keyword_loc).start_offset, [";"]) end, - visit(node.consequent), - token(node.consequent&.else_keyword_loc), + visit(node.else_clause), + token(node.else_clause&.else_keyword_loc), visit(node.statements), token(node.end_keyword_loc) ) else builder.condition_mod( - visit(node.consequent), + visit(node.else_clause), visit(node.statements), token(node.keyword_loc), visit(node.predicate) @@ -1747,8 +1870,7 @@ def visit_while_node(node) # ^^^^^ def visit_x_string_node(node) if node.heredoc? - children, closing = visit_heredoc(node.to_interpolated) - builder.xstring_compose(token(node.opening_loc), children, closing) + visit_heredoc(node.to_interpolated) { |children, closing| builder.xstring_compose(token(node.opening_loc), children, closing) } else parts = if node.unescaped.lines.one? [builder.string_internal([node.unescaped, srange(node.content_loc)])] @@ -1810,10 +1932,12 @@ def find_forwarding(node) forwarding end - # Because we have mutated the AST to allow for newlines in the middle of - # a rational, we need to manually handle the value here. - def imaginary_value(node) - Complex(0, node.numeric.is_a?(RationalNode) ? rational_value(node.numeric) : node.numeric.value) + # Returns the set of targets for a MultiTargetNode or a MultiWriteNode. + def multi_target_elements(node) + elements = [*node.lefts] + elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) + elements.concat(node.rights) + elements end # Negate the value of a numeric node. This is a special case where you @@ -1825,7 +1949,9 @@ def numeric_negate(message_loc, receiver) case receiver.type when :integer_node, :float_node receiver.copy(value: -receiver.value, location: message_loc.join(receiver.location)) - when :rational_node, :imaginary_node + when :rational_node + receiver.copy(numerator: -receiver.numerator, location: message_loc.join(receiver.location)) + when :imaginary_node receiver.copy(numeric: numeric_negate(message_loc, receiver.numeric), location: message_loc.join(receiver.location)) end end @@ -1844,16 +1970,6 @@ def procarg0?(parameters) parameters.block.nil? end - # Because we have mutated the AST to allow for newlines in the middle of - # a rational, we need to manually handle the value here. - def rational_value(node) - if node.numeric.is_a?(IntegerNode) - Rational(node.numeric.value) - else - Rational(node.slice.gsub(/\s/, "").chomp("r")) - end - end - # Locations in the parser gem AST are generated using this class. We # store a reference to its constant to make it slightly faster to look # up. @@ -1876,7 +1992,7 @@ def srange_offsets(start_offset, end_offset) # Note that end_offset is allowed to be nil, in which case this will # search until the end of the string. def srange_find(start_offset, end_offset, tokens) - if (match = source_buffer.source.byteslice(start_offset...end_offset).match(/(\s*)(#{tokens.join("|")})/)) + if (match = source_buffer.source.byteslice(start_offset...end_offset).match(/\A(\s*)(#{tokens.join("|")})/)) _, whitespace, token = *match token_offset = start_offset + whitespace.bytesize @@ -1907,7 +2023,8 @@ def visit_block(call, block) token(parameters.opening_loc), if procarg0?(parameters.parameters) parameter = parameters.parameters.requireds.first - [builder.procarg0(visit(parameter))].concat(visit_all(parameters.locals)) + visited = parameter.is_a?(RequiredParameterNode) ? visit(parameter) : parameter.accept(copy_compiler(in_destructure: true)) + [builder.procarg0(visited)].concat(visit_all(parameters.locals)) else visit(parameters) end, @@ -1923,29 +2040,55 @@ def visit_block(call, block) end end + # The parser gem automatically converts \r\n to \n, meaning our offsets + # need to be adjusted to always subtract 1 from the length. + def chomped_bytesize(line) + chomped = line.chomp + chomped.bytesize + (chomped == line ? 0 : 1) + end + # Visit a heredoc that can be either a string or an xstring. def visit_heredoc(node) children = Array.new + indented = false + + # If this is a dedenting heredoc, then we need to insert the opening + # content into the children as well. + if node.opening.start_with?("<<~") && node.parts.length > 0 && !node.parts.first.is_a?(StringNode) + location = node.parts.first.location + location = location.copy(start_offset: location.start_offset - location.start_line_slice.bytesize) + children << builder.string_internal(token(location)) + indented = true + end + node.parts.each do |part| pushing = if part.is_a?(StringNode) && part.unescaped.include?("\n") - unescaped = part.unescaped.lines(chomp: true) - escaped = part.content.lines(chomp: true) + unescaped = part.unescaped.lines + escaped = part.content.lines - escaped_lengths = - if node.opening.end_with?("'") - escaped.map { |line| line.bytesize + 1 } - else - escaped.chunk_while { |before, after| before.match?(/(? (foo = -> (bar) {}) do end`, please note that `kDO` is still returned + # instead of `kDO_LAMBDA`, which is expected: https://github.com/ruby/prism/pull/3046 + LAMBDA_TOKEN_TYPES = [:kDO_LAMBDA, :tLAMBDA, :tLAMBEG] + + # The `PARENTHESIS_LEFT` token in Prism is classified as either `tLPAREN` or `tLPAREN2` in the Parser gem. + # The following token types are listed as those classified as `tLPAREN`. + LPAREN_CONVERSION_TOKEN_TYPES = [ + :kBREAK, :kCASE, :tDIVIDE, :kFOR, :kIF, :kNEXT, :kRETURN, :kUNTIL, :kWHILE, :tAMPER, :tANDOP, :tBANG, :tCOMMA, :tDOT2, :tDOT3, + :tEQL, :tLPAREN, :tLPAREN2, :tLSHFT, :tNL, :tOP_ASGN, :tOROP, :tPIPE, :tSEMI, :tSTRING_DBEG, :tUMINUS, :tUPLUS + ] + + private_constant :TYPES, :EXPR_BEG, :EXPR_LABEL, :LAMBDA_TOKEN_TYPES, :LPAREN_CONVERSION_TOKEN_TYPES # The Parser::Source::Buffer that the tokens were lexed from. attr_reader :source_buffer @@ -229,6 +242,13 @@ def to_a location = Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[token.location.end_offset]) case type + when :kDO + types = tokens.map(&:first) + nearest_lambda_token_type = types.reverse.find { |type| LAMBDA_TOKEN_TYPES.include?(type) } + + if nearest_lambda_token_type == :tLAMBDA + type = :kDO_LAMBDA + end when :tCHARACTER value.delete_prefix!("?") when :tCOMMENT @@ -268,6 +288,8 @@ def to_a value.chomp!(":") when :tLCURLY type = :tLBRACE if state == EXPR_BEG | EXPR_LABEL + when :tLPAREN2 + type = :tLPAREN if tokens.empty? || LPAREN_CONVERSION_TOKEN_TYPES.include?(tokens.dig(-1, 0)) when :tNTH_REF value = parse_integer(value.delete_prefix("$")) when :tOP_ASGN @@ -339,7 +361,7 @@ def to_a location = Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[token.location.start_offset + 1]) end when :tSYMBEG - if (next_token = lexed[index][0]) && next_token.type != :STRING_CONTENT && next_token.type != :EMBEXPR_BEGIN && next_token.type != :EMBVAR + if (next_token = lexed[index][0]) && next_token.type != :STRING_CONTENT && next_token.type != :EMBEXPR_BEGIN && next_token.type != :EMBVAR && next_token.type != :STRING_END next_location = token.location.join(next_token.location) type = :tSYMBOL value = next_token.value diff --git a/lib/prism/translation/parser/rubocop.rb b/lib/prism/translation/parser/rubocop.rb deleted file mode 100644 index 6c9687a5cc0..00000000000 --- a/lib/prism/translation/parser/rubocop.rb +++ /dev/null @@ -1,73 +0,0 @@ -# frozen_string_literal: true -# typed: ignore - -warn "WARN: Prism is directly supported since RuboCop 1.62. The `prism/translation/parser/rubocop` file is deprecated." - -require "parser" -require "rubocop" - -require_relative "../../prism" -require_relative "../parser" - -module Prism - module Translation - class Parser - # This is the special version numbers that should be used in RuboCop - # configuration files to trigger using prism. - - # For Ruby 3.3 - VERSION_3_3 = 80_82_73_83_77.33 - - # For Ruby 3.4 - VERSION_3_4 = 80_82_73_83_77.34 - - # This module gets prepended into RuboCop::AST::ProcessedSource. - module ProcessedSource - # This condition is compatible with rubocop-ast versions up to 1.30.0. - if RuboCop::AST::ProcessedSource.instance_method(:parser_class).arity == 1 - # Redefine parser_class so that we can inject the prism parser into the - # list of known parsers. - def parser_class(ruby_version) - if ruby_version == Prism::Translation::Parser::VERSION_3_3 - warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.33` is deprecated. " \ - "Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.3` instead." - require_relative "../parser33" - Prism::Translation::Parser33 - elsif ruby_version == Prism::Translation::Parser::VERSION_3_4 - warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.34` is deprecated. " \ - "Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.4` instead." - require_relative "../parser34" - Prism::Translation::Parser34 - else - super - end - end - else - # Redefine parser_class so that we can inject the prism parser into the - # list of known parsers. - def parser_class(ruby_version, _parser_engine) - if ruby_version == Prism::Translation::Parser::VERSION_3_3 - warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.33` is deprecated. " \ - "Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.3` instead." - require_relative "../parser33" - Prism::Translation::Parser33 - elsif ruby_version == Prism::Translation::Parser::VERSION_3_4 - warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.34` is deprecated. " \ - "Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.4` instead." - require_relative "../parser34" - Prism::Translation::Parser34 - else - super - end - end - end - end - end - end -end - -# :stopdoc: -RuboCop::AST::ProcessedSource.prepend(Prism::Translation::Parser::ProcessedSource) -known_rubies = RuboCop::TargetRuby.const_get(:KNOWN_RUBIES) -RuboCop::TargetRuby.send(:remove_const, :KNOWN_RUBIES) -RuboCop::TargetRuby::KNOWN_RUBIES = [*known_rubies, Prism::Translation::Parser::VERSION_3_3].freeze diff --git a/lib/prism/translation/ripper.rb b/lib/prism/translation/ripper.rb index d226bb58df7..018842715b0 100644 --- a/lib/prism/translation/ripper.rb +++ b/lib/prism/translation/ripper.rb @@ -1181,8 +1181,8 @@ def visit_call_operator_write_node(node) bounds(node.location) target = on_field(receiver, call_operator, message) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) @@ -1273,8 +1273,8 @@ def visit_capture_pattern_node(node) def visit_case_node(node) predicate = visit(node.predicate) clauses = - node.conditions.reverse_each.inject(visit(node.consequent)) do |consequent, condition| - on_when(*visit(condition), consequent) + node.conditions.reverse_each.inject(visit(node.else_clause)) do |current, condition| + on_when(*visit(condition), current) end bounds(node.location) @@ -1286,8 +1286,8 @@ def visit_case_node(node) def visit_case_match_node(node) predicate = visit(node.predicate) clauses = - node.conditions.reverse_each.inject(visit(node.consequent)) do |consequent, condition| - on_in(*visit(condition), consequent) + node.conditions.reverse_each.inject(visit(node.else_clause)) do |current, condition| + on_in(*visit(condition), current) end bounds(node.location) @@ -1339,8 +1339,8 @@ def visit_class_variable_operator_write_node(node) bounds(node.name_loc) target = on_var_field(on_cvar(node.name.to_s)) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) @@ -1409,8 +1409,8 @@ def visit_constant_operator_write_node(node) bounds(node.name_loc) target = on_var_field(on_const(node.name.to_s)) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) @@ -1510,8 +1510,8 @@ def visit_constant_path_operator_write_node(node) target = visit_constant_path_write_node_target(node.target) value = visit(node.value) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) @@ -1802,8 +1802,8 @@ def visit_global_variable_operator_write_node(node) bounds(node.name_loc) target = on_var_field(on_gvar(node.name.to_s)) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) @@ -1908,7 +1908,7 @@ def visit_if_node(node) if node.then_keyword == "?" predicate = visit(node.predicate) truthy = visit(node.statements.body.first) - falsy = visit(node.consequent.statements.body.first) + falsy = visit(node.subsequent.statements.body.first) bounds(node.location) on_ifop(predicate, truthy, falsy) @@ -1921,13 +1921,13 @@ def visit_if_node(node) else visit(node.statements) end - consequent = visit(node.consequent) + subsequent = visit(node.subsequent) bounds(node.location) if node.if_keyword == "if" - on_if(predicate, statements, consequent) + on_if(predicate, statements, subsequent) else - on_elsif(predicate, statements, consequent) + on_elsif(predicate, statements, subsequent) end else statements = visit(node.statements.body.first) @@ -1960,7 +1960,7 @@ def visit_implicit_rest_node(node) # ^^^^^^^^^^^^^^^^^^^^^ def visit_in_node(node) # This is a special case where we're not going to call on_in directly - # because we don't have access to the consequent. Instead, we'll return + # because we don't have access to the subsequent. Instead, we'll return # the component parts and let the parent node handle it. pattern = visit_pattern_node(node.pattern) statements = @@ -1983,8 +1983,8 @@ def visit_index_operator_write_node(node) bounds(node.location) target = on_aref_field(receiver, arguments) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) @@ -2059,8 +2059,8 @@ def visit_instance_variable_operator_write_node(node) bounds(node.name_loc) target = on_var_field(on_ivar(node.name.to_s)) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) @@ -2217,6 +2217,13 @@ def visit_interpolated_x_string_node(node) end end + # -> { it } + # ^^ + def visit_it_local_variable_read_node(node) + bounds(node.location) + on_vcall(on_ident(node.slice)) + end + # -> { it } # ^^^^^^^^^ def visit_it_parameters_node(node) @@ -2312,12 +2319,7 @@ def visit_lambda_node(node) # ^^^ def visit_local_variable_read_node(node) bounds(node.location) - - if node.name == :"0it" - on_vcall(on_ident(node.slice)) - else - on_var_ref(on_ident(node.slice)) - end + on_var_ref(on_ident(node.slice)) end # foo = 1 @@ -2337,8 +2339,8 @@ def visit_local_variable_operator_write_node(node) bounds(node.name_loc) target = on_var_field(on_ident(node.name_loc.slice)) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) @@ -2806,10 +2808,10 @@ def visit_rescue_node(node) visit(node.statements) end - consequent = visit(node.consequent) + subsequent = visit(node.subsequent) bounds(node.location) - on_rescue(exceptions, reference, statements, consequent) + on_rescue(exceptions, reference, statements, subsequent) end # def foo(*bar); end @@ -3130,10 +3132,10 @@ def visit_unless_node(node) else visit(node.statements) end - consequent = visit(node.consequent) + else_clause = visit(node.else_clause) bounds(node.location) - on_unless(predicate, statements, consequent) + on_unless(predicate, statements, else_clause) else statements = visit(node.statements.body.first) predicate = visit(node.predicate) @@ -3174,7 +3176,7 @@ def visit_until_node(node) # ^^^^^^^^^^^^^ def visit_when_node(node) # This is a special case where we're not going to call on_when directly - # because we don't have access to the consequent. Instead, we'll return + # because we don't have access to the subsequent. Instead, we'll return # the component parts and let the parent node handle it. conditions = visit_arguments(node.conditions) statements = @@ -3267,11 +3269,7 @@ def visit_yield_node(node) # Lazily initialize the parse result. def result - @result ||= - begin - scopes = RUBY_VERSION >= "3.3.0" ? [] : [[]] - Prism.parse(source, scopes: scopes) - end + @result ||= Prism.parse(source, partial_script: true) end ########################################################################## diff --git a/lib/prism/translation/ruby_parser.rb b/lib/prism/translation/ruby_parser.rb index c6f741c8e53..189038d008d 100644 --- a/lib/prism/translation/ruby_parser.rb +++ b/lib/prism/translation/ruby_parser.rb @@ -1,6 +1,11 @@ # frozen_string_literal: true -require "ruby_parser" +begin + require "ruby_parser" +rescue LoadError + warn(%q{Error: Unable to load ruby_parser. Add `gem "ruby_parser"` to your Gemfile.}) + exit(1) +end module Prism module Translation @@ -50,7 +55,19 @@ def visit_alternation_pattern_node(node) # a and b # ^^^^^^^ def visit_and_node(node) - s(node, :and, visit(node.left), visit(node.right)) + left = visit(node.left) + + if left[0] == :and + # ruby_parser has the and keyword as right-associative as opposed to + # prism which has it as left-associative. We reverse that + # associativity here. + nest = left + nest = nest[2] while nest[2][0] == :and + nest[2] = s(node, :and, nest[2], visit(node.right)) + left + else + s(node, :and, left, visit(node.right)) + end end # [] @@ -130,7 +147,7 @@ def visit_begin_node(node) end current = node.rescue_clause - until (current = current.consequent).nil? + until (current = current.subsequent).nil? result << visit(current) end end @@ -246,6 +263,11 @@ def visit_call_node(node) when RegularExpressionNode, InterpolatedRegularExpressionNode return s(node, :match2, visit(node.receiver), visit(node.arguments.arguments.first)) end + + case node.arguments.arguments.first + when RegularExpressionNode, InterpolatedRegularExpressionNode + return s(node, :match3, visit(node.arguments.arguments.first), visit(node.receiver)) + end end end @@ -271,9 +293,9 @@ def visit_call_node(node) # ^^^^^^^^^^^^^^^ def visit_call_operator_write_node(node) if op_asgn?(node) - s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, node.operator) + s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, node.binary_operator) else - s(node, op_asgn_type(node, :op_asgn2), visit(node.receiver), node.write_name, node.operator, visit_write_value(node.value)) + s(node, op_asgn_type(node, :op_asgn2), visit(node.receiver), node.write_name, node.binary_operator, visit_write_value(node.value)) end end @@ -325,13 +347,13 @@ def visit_capture_pattern_node(node) # case foo; when bar; end # ^^^^^^^^^^^^^^^^^^^^^^^ def visit_case_node(node) - s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.consequent) + s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.else_clause) end # case foo; in bar; end # ^^^^^^^^^^^^^^^^^^^^^ def visit_case_match_node(node) - s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.consequent) + s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.else_clause) end # class Foo; end @@ -372,7 +394,7 @@ def visit_class_variable_write_node(node) # @@foo += bar # ^^^^^^^^^^^^ def visit_class_variable_operator_write_node(node) - s(node, class_variable_write_type, node.name, s(node, :call, s(node, :cvar, node.name), node.operator, visit_write_value(node.value))) + s(node, class_variable_write_type, node.name, s(node, :call, s(node, :cvar, node.name), node.binary_operator, visit_write_value(node.value))) end # @@foo &&= bar @@ -417,7 +439,7 @@ def visit_constant_write_node(node) # Foo += bar # ^^^^^^^^^^^ def visit_constant_operator_write_node(node) - s(node, :cdecl, node.name, s(node, :call, s(node, :const, node.name), node.operator, visit_write_value(node.value))) + s(node, :cdecl, node.name, s(node, :call, s(node, :const, node.name), node.binary_operator, visit_write_value(node.value))) end # Foo &&= bar @@ -460,7 +482,7 @@ def visit_constant_path_write_node(node) # Foo::Bar += baz # ^^^^^^^^^^^^^^^ def visit_constant_path_operator_write_node(node) - s(node, :op_asgn, visit(node.target), node.operator, visit_write_value(node.value)) + s(node, :op_asgn, visit(node.target), node.binary_operator, visit_write_value(node.value)) end # Foo::Bar &&= baz @@ -480,9 +502,9 @@ def visit_constant_path_or_write_node(node) def visit_constant_path_target_node(node) inner = if node.parent.nil? - s(node, :colon3, node.child.name) + s(node, :colon3, node.name) else - s(node, :colon2, visit(node.parent), node.child.name) + s(node, :colon2, visit(node.parent), node.name) end s(node, :const, inner) @@ -627,7 +649,7 @@ def visit_global_variable_write_node(node) # $foo += bar # ^^^^^^^^^^^ def visit_global_variable_operator_write_node(node) - s(node, :gasgn, node.name, s(node, :call, s(node, :gvar, node.name), node.operator, visit(node.value))) + s(node, :gasgn, node.name, s(node, :call, s(node, :gvar, node.name), node.binary_operator, visit(node.value))) end # $foo &&= bar @@ -678,7 +700,7 @@ def visit_hash_pattern_node(node) # foo ? bar : baz # ^^^^^^^^^^^^^^^ def visit_if_node(node) - s(node, :if, visit(node.predicate), visit(node.statements), visit(node.consequent)) + s(node, :if, visit(node.predicate), visit(node.statements), visit(node.subsequent)) end # 1i @@ -719,7 +741,7 @@ def visit_index_operator_write_node(node) arglist << visit(node.block) if !node.block.nil? end - s(node, :op_asgn1, visit(node.receiver), arglist, node.operator, visit_write_value(node.value)) + s(node, :op_asgn1, visit(node.receiver), arglist, node.binary_operator, visit_write_value(node.value)) end # foo[bar] &&= baz @@ -775,7 +797,7 @@ def visit_instance_variable_write_node(node) # @foo += bar # ^^^^^^^^^^^ def visit_instance_variable_operator_write_node(node) - s(node, :iasgn, node.name, s(node, :call, s(node, :ivar, node.name), node.operator, visit_write_value(node.value))) + s(node, :iasgn, node.name, s(node, :call, s(node, :ivar, node.name), node.binary_operator, visit_write_value(node.value))) end # @foo &&= bar @@ -870,6 +892,15 @@ def visit_interpolated_x_string_node(node) else visited << result end + elsif result[0] == :dstr + if !visited.empty? && part.parts[0].is_a?(StringNode) + # If we are in the middle of an implicitly concatenated string, + # we should not have a bare string as the first part. In this + # case we need to visit just that first part and then we can + # push the rest of the parts onto the visited array. + result[1] = visit(part.parts[0]) + end + visited.concat(result[1..-1]) else visited << result end @@ -900,12 +931,23 @@ def visit_interpolated_x_string_node(node) results << result state = :interpolated_content end - else - results << result + when :interpolated_content + if result.is_a?(Array) && result[0] == :str && results[-1][0] == :str && (results[-1].line_max == result.line) + results[-1][1] << result[1] + results[-1].line_max = result.line_max + else + results << result + end end end end + # -> { it } + # ^^ + def visit_it_local_variable_read_node(node) + s(node, :call, nil, :it) + end + # foo(bar: baz) # ^^^^^^^^ def visit_keyword_hash_node(node) @@ -960,7 +1002,7 @@ def visit_local_variable_write_node(node) # foo += bar # ^^^^^^^^^^ def visit_local_variable_operator_write_node(node) - s(node, :lasgn, node.name, s(node, :call, s(node, :lvar, node.name), node.operator, visit_write_value(node.value))) + s(node, :lasgn, node.name, s(node, :call, s(node, :lvar, node.name), node.binary_operator, visit_write_value(node.value))) end # foo &&= bar @@ -1118,7 +1160,19 @@ def visit_optional_parameter_node(node) # a or b # ^^^^^^ def visit_or_node(node) - s(node, :or, visit(node.left), visit(node.right)) + left = visit(node.left) + + if left[0] == :or + # ruby_parser has the or keyword as right-associative as opposed to + # prism which has it as left-associative. We reverse that + # associativity here. + nest = left + nest = nest[2] while nest[2][0] == :or + nest[2] = s(node, :or, nest[2], visit(node.right)) + left + else + s(node, :or, left, visit(node.right)) + end end # def foo(bar, *baz); end @@ -1374,7 +1428,13 @@ def visit_statements_node(node) # "foo" # ^^^^^ def visit_string_node(node) - s(node, :str, node.unescaped) + unescaped = node.unescaped + + if node.forced_binary_encoding? + unescaped.force_encoding(Encoding::BINARY) + end + + s(node, :str, unescaped) end # super(foo) @@ -1416,7 +1476,7 @@ def visit_undef_node(node) # bar unless foo # ^^^^^^^^^^^^^^ def visit_unless_node(node) - s(node, :if, visit(node.predicate), visit(node.consequent), visit(node.statements)) + s(node, :if, visit(node.predicate), visit(node.else_clause), visit(node.statements)) end # until foo; bar end @@ -1536,13 +1596,13 @@ def visit_write_value(node) # Parse the given source and translate it into the seattlerb/ruby_parser # gem's Sexp format. def parse(source, filepath = "(string)") - translate(Prism.parse(source, filepath: filepath, scopes: [[]]), filepath) + translate(Prism.parse(source, filepath: filepath, partial_script: true), filepath) end # Parse the given file and translate it into the seattlerb/ruby_parser # gem's Sexp format. def parse_file(filepath) - translate(Prism.parse_file(filepath, scopes: [[]]), filepath) + translate(Prism.parse_file(filepath, partial_script: true), filepath) end class << self diff --git a/prism.gemspec b/prism.gemspec index d23b6a65cb2..3c8910d3b72 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -2,7 +2,7 @@ Gem::Specification.new do |spec| spec.name = "prism" - spec.version = "0.28.0" + spec.version = "1.2.0" spec.authors = ["Shopify"] spec.email = ["ruby@shopify.com"] @@ -65,12 +65,10 @@ Gem::Specification.new do |spec| "include/prism/util/pm_newline_list.h", "include/prism/util/pm_strncasecmp.h", "include/prism/util/pm_string.h", - "include/prism/util/pm_string_list.h", "include/prism/util/pm_strpbrk.h", "include/prism/version.h", "lib/prism.rb", "lib/prism/compiler.rb", - "lib/prism/debug.rb", "lib/prism/desugar_compiler.rb", "lib/prism/dispatcher.rb", "lib/prism/dot_visitor.rb", @@ -84,19 +82,20 @@ Gem::Specification.new do |spec| "lib/prism/pack.rb", "lib/prism/parse_result.rb", "lib/prism/parse_result/comments.rb", + "lib/prism/parse_result/errors.rb", "lib/prism/parse_result/newlines.rb", "lib/prism/pattern.rb", "lib/prism/polyfill/byteindex.rb", "lib/prism/polyfill/unpack1.rb", "lib/prism/reflection.rb", "lib/prism/serialize.rb", + "lib/prism/string_query.rb", "lib/prism/translation.rb", "lib/prism/translation/parser.rb", "lib/prism/translation/parser33.rb", "lib/prism/translation/parser34.rb", "lib/prism/translation/parser/compiler.rb", "lib/prism/translation/parser/lexer.rb", - "lib/prism/translation/parser/rubocop.rb", "lib/prism/translation/ripper.rb", "lib/prism/translation/ripper/sexp.rb", "lib/prism/translation/ripper/shim.rb", @@ -105,11 +104,13 @@ Gem::Specification.new do |spec| "prism.gemspec", "rbi/prism.rbi", "rbi/prism/compiler.rbi", + "rbi/prism/dsl.rbi", "rbi/prism/inspect_visitor.rbi", "rbi/prism/node_ext.rbi", "rbi/prism/node.rbi", "rbi/prism/parse_result.rbi", "rbi/prism/reflection.rbi", + "rbi/prism/string_query.rbi", "rbi/prism/translation/parser.rbi", "rbi/prism/translation/parser33.rbi", "rbi/prism/translation/parser34.rbi", @@ -121,6 +122,7 @@ Gem::Specification.new do |spec| "sig/prism/dot_visitor.rbs", "sig/prism/dsl.rbs", "sig/prism/inspect_visitor.rbs", + "sig/prism/lex_compat.rbs", "sig/prism/mutation_compiler.rbs", "sig/prism/node_ext.rbs", "sig/prism/node.rbs", @@ -129,6 +131,7 @@ Gem::Specification.new do |spec| "sig/prism/pattern.rbs", "sig/prism/reflection.rbs", "sig/prism/serialize.rbs", + "sig/prism/string_query.rbs", "sig/prism/visitor.rbs", "src/diagnostic.c", "src/encoding.c", @@ -148,7 +151,6 @@ Gem::Specification.new do |spec| "src/util/pm_list.c", "src/util/pm_memchr.c", "src/util/pm_newline_list.c", - "src/util/pm_string_list.c", "src/util/pm_string.c", "src/util/pm_strncasecmp.c", "src/util/pm_strpbrk.c" diff --git a/rakelib/cargo.rake b/rakelib/cargo.rake index e7e98afbb16..8f5d5266a99 100644 --- a/rakelib/cargo.rake +++ b/rakelib/cargo.rake @@ -8,7 +8,7 @@ namespace :cargo do prism_sys_dir = Pathname(File.expand_path(File.join(__dir__, "../rust", "ruby-prism-sys"))) prism_sys_vendor_dir = prism_sys_dir.join("vendor/prism-#{gemspec.version}") - rm_rf(prism_sys_vendor_dir) + rm_rf(prism_sys_dir.join("vendor")) mkdir_p(prism_sys_vendor_dir) cp_r("./include", prism_sys_vendor_dir.join("include")) cp_r("./src", prism_sys_vendor_dir.join("src")) @@ -16,7 +16,7 @@ namespace :cargo do prism_dir = Pathname(File.expand_path(File.join(__dir__, "../rust", "ruby-prism"))) prism_vendor_dir = prism_dir.join("vendor/prism-#{gemspec.version}") - rm_rf(prism_vendor_dir) + rm_rf(prism_dir.join("vendor")) mkdir_p(prism_vendor_dir) cp(File.expand_path("../config.yml", __dir__), prism_vendor_dir.join("config.yml")) diff --git a/rakelib/check_manifest.rake b/rakelib/check_manifest.rake index 50a88569e3f..81398fbd245 100644 --- a/rakelib/check_manifest.rake +++ b/rakelib/check_manifest.rake @@ -13,6 +13,7 @@ task check_manifest: :templates do autom4te.cache bin build + cpp doc fuzz gemfiles @@ -22,7 +23,9 @@ task check_manifest: :templates do pkg rakelib rust + sample sorbet + suppressions templates test top-100-gems diff --git a/rakelib/lint.rake b/rakelib/lint.rake index 58b39f5adf9..89d5a01ba5a 100644 --- a/rakelib/lint.rake +++ b/rakelib/lint.rake @@ -28,6 +28,12 @@ task :lint do exit(1) end + if (operators = nodes.select { |node| node.fetch("fields", []).any? { |field| field["name"] == "operator" } }).any? + names = operators.map { |node| node.fetch("name") } + warn("Nodes cannot have fields named 'operator' because it is a C++ reserved keyword, found in #{names.join(", ")}") + exit(1) + end + if (uncommented = nodes.select { |node| !node.key?("comment") }).any? names = uncommented.map { |node| node.fetch("name") } warn("Expected all nodes to be commented, missing comments for #{names.join(", ")}") diff --git a/rakelib/seattlerb.rake b/rakelib/seattlerb.rake index 15aebe4693f..217d64ef4b3 100644 --- a/rakelib/seattlerb.rake +++ b/rakelib/seattlerb.rake @@ -98,5 +98,6 @@ namespace :seattlerb do task :clean do rm_rf "tmp/seattlerb" rm_rf "test/prism/fixtures/seattlerb" + rm_rf "test/prism/snapshots/seattlerb" end end diff --git a/rakelib/test.rake b/rakelib/test.rake index 0198659b9d3..4257202bc88 100644 --- a/rakelib/test.rake +++ b/rakelib/test.rake @@ -10,36 +10,7 @@ end Rake::TestTask.new(:test, &config) -# If we're on JRuby or TruffleRuby, we don't want to bother to configure -# memcheck or debug tests. -return if RUBY_ENGINE == "jruby" || RUBY_ENGINE == "truffleruby" - -# Don't bother trying to configure memcheck on old versions of Ruby. -return if RUBY_VERSION < "3.0" - -begin - require "ruby_memcheck" - have_memcheck = true -rescue LoadError - have_memcheck = false -end - namespace :test do - if have_memcheck - RubyMemcheck::TestTask.new(valgrind_internal: :compile, &config) - - # Hide test:valgrind_internal from rake -T - Rake::Task["test:valgrind_internal"].clear_comments - - desc "Run tests under valgrind" - task :valgrind do - # Recompile with PRISM_BUILD_DEBUG=1 - ENV["PRISM_BUILD_DEBUG"] = "1" - Rake::Task["clobber"].invoke - Rake::Task["test:valgrind_internal"].invoke - end - end - class GdbTestTask < Rake::TestTask def ruby(*args, **options, &block) command = "gdb --args #{RUBY} #{args.join(" ")}" @@ -67,3 +38,33 @@ namespace :test do end end end + +# If we're on JRuby or TruffleRuby, we don't want to bother to configure +# memcheck or debug tests. +return if RUBY_ENGINE == "jruby" || RUBY_ENGINE == "truffleruby" + +# Don't bother trying to configure memcheck on old versions of Ruby. +return if RUBY_VERSION < "3.0" + +# Only attempt to configure memcheck if the gem is installed. +begin + require "ruby_memcheck" +rescue LoadError + return +end + +namespace :test do + RubyMemcheck.config(use_only_ruby_free_at_exit: false) + RubyMemcheck::TestTask.new(valgrind_internal: :compile, &config) + + # Hide test:valgrind_internal from rake -T + Rake::Task["test:valgrind_internal"].clear_comments + + desc "Run tests under valgrind" + task :valgrind do + # Recompile with PRISM_BUILD_DEBUG=1 + ENV["PRISM_BUILD_DEBUG"] = "1" + Rake::Task["clobber"].invoke + Rake::Task["test:valgrind_internal"].invoke + end +end diff --git a/rakelib/typecheck.rake b/rakelib/typecheck.rake index bc76c34e54a..052a20327e5 100644 --- a/rakelib/typecheck.rake +++ b/rakelib/typecheck.rake @@ -2,6 +2,8 @@ namespace :typecheck do task tapioca: :templates do + Rake::Task["compile:prism"].invoke + # Yard crashes parsing steep, which is all run because of tapioca. So to # avoid this, we're going to monkey patch yard to ignore these kinds of # crashes so tapioca can keep running. @@ -31,13 +33,11 @@ namespace :typecheck do File.write("sorbet/typed_overrides.yml", ERB.new(<<~YAML, trim_mode: "-").result_with_hash(locals)) false: - - ./lib/prism/debug.rb - ./lib/prism/lex_compat.rb - ./lib/prism/node_ext.rb - ./lib/prism/parse_result.rb - ./lib/prism/visitor.rb - ./lib/prism/translation/ripper.rb - - ./lib/prism/translation/ripper/ripper_compiler.rb - ./lib/prism/translation/ripper/sexp.rb - ./lib/prism/translation/ruby_parser.rb - ./lib/prism/inspect_visitor.rb @@ -59,6 +59,7 @@ namespace :typecheck do --ignore=test/ --ignore=rakelib/ --ignore=Rakefile + --ignore=top-100-gems/ # Treat all files as "typed: true" by default --typed=true # Use the typed-override file to revert some files to "typed: false" @@ -71,13 +72,11 @@ namespace :typecheck do --suppress-error-code=7001 CONFIG - Process.wait(fork do - exec "#{::Gem::Specification.find_by_name("sorbet-static").full_gem_path}/libexec/sorbet" - end) + exec "#{::Gem::Specification.find_by_name("sorbet-static").full_gem_path}/libexec/sorbet" end desc "Typecheck with Steep" task steep: :templates do - Process.wait(fork { exec Gem.bin_path("steep", "steep"), "check" }) + exec Gem.bin_path("steep", "steep"), "check" end end diff --git a/rakelib/unparser.rake b/rakelib/unparser.rake index 531296f6faa..44904e9096c 100644 --- a/rakelib/unparser.rake +++ b/rakelib/unparser.rake @@ -40,5 +40,6 @@ namespace :unparser do task :clean do rm_rf "tmp/unparser" rm_rf "test/prism/fixtures/unparser" + rm_rf "test/prism/snapshots/unparser" end end diff --git a/rakelib/whitequark.rake b/rakelib/whitequark.rake index f5ad8ffdc9c..6eb2daef7ea 100644 --- a/rakelib/whitequark.rake +++ b/rakelib/whitequark.rake @@ -92,7 +92,6 @@ namespace :whitequark do test/prism/fixtures/whitequark/class_definition_in_while_cond.txt test/prism/fixtures/whitequark/control_meta_escape_chars_in_regexp__since_31.txt test/prism/fixtures/whitequark/if_while_after_class__since_32.txt - test/prism/fixtures/whitequark/method_definition_in_while_cond.txt test/prism/fixtures/whitequark/next_block.txt test/prism/fixtures/whitequark/next.txt test/prism/fixtures/whitequark/pattern_match.txt @@ -111,5 +110,6 @@ namespace :whitequark do task :clean do rm_rf "tmp/whitequark" rm_rf "test/prism/fixtures/whitequark" + rm_rf "test/prism/snapshots/whitequark" end end diff --git a/rbi/prism.rbi b/rbi/prism.rbi index e1f55e5001e..d7838a8279c 100644 --- a/rbi/prism.rbi +++ b/rbi/prism.rbi @@ -1,17 +1,17 @@ # typed: strict module Prism - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(String) } - def self.dump(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end + sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(String) } + def self.dump(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(String) } - def self.dump_file(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end + sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(String) } + def self.dump_file(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::LexResult) } - def self.lex(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end + sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::LexResult) } + def self.lex(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::LexResult) } - def self.lex_file(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end + sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::LexResult) } + def self.lex_file(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end sig { params(source: String, options: T::Hash[Symbol, T.untyped]).returns(Prism::LexCompat::Result) } def self.lex_compat(source, **options); end @@ -22,36 +22,42 @@ module Prism sig { params(source: String, serialized: String).returns(Prism::ParseResult) } def self.load(source, serialized); end - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseResult) } - def self.parse(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end + sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseResult) } + def self.parse(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseResult) } - def self.parse_file(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end + sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseResult) } + def self.parse_file(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - sig { params(stream: T.any(IO, StringIO), command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseResult) } - def self.parse_stream(stream, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end + sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).void } + def self.profile(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Array[Prism::Comment]) } - def self.parse_comments(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end + sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).void } + def self.profile_file(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Array[Prism::Comment]) } - def self.parse_file_comments(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end + sig { params(stream: T.any(IO, StringIO), command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseResult) } + def self.parse_stream(stream, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseLexResult) } - def self.parse_lex(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end + sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Array[Prism::Comment]) } + def self.parse_comments(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseLexResult) } - def self.parse_lex_file(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end + sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Array[Prism::Comment]) } + def self.parse_file_comments(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Boolean) } - def self.parse_success?(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end + sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseLexResult) } + def self.parse_lex(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Boolean) } - def self.parse_failure?(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end + sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseLexResult) } + def self.parse_lex_file(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Boolean) } - def self.parse_file_success?(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end + sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Boolean) } + def self.parse_success?(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Boolean) } - def self.parse_file_failure?(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end + sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Boolean) } + def self.parse_failure?(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end + + sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Boolean) } + def self.parse_file_success?(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end + + sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Boolean) } + def self.parse_file_failure?(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end end diff --git a/rbi/prism/node_ext.rbi b/rbi/prism/node_ext.rbi index 7b037763f45..e5cf7376cc6 100644 --- a/rbi/prism/node_ext.rbi +++ b/rbi/prism/node_ext.rbi @@ -100,3 +100,8 @@ class Prism::ParametersNode < Prism::Node sig { returns(T::Array[T.any([Symbol, Symbol], [Symbol])]) } def signature; end end + +class Prism::CallNode < Prism::Node + sig { returns(T.nilable(Prism::Location)) } + def full_message_loc; end +end diff --git a/rbi/prism/parse_result.rbi b/rbi/prism/parse_result.rbi index 73e0be1bc70..ef1f051e766 100644 --- a/rbi/prism/parse_result.rbi +++ b/rbi/prism/parse_result.rbi @@ -16,7 +16,7 @@ class Prism::Source sig { returns(Encoding) } def encoding; end - sig { returns(T::Array[Integer]) } + sig { returns(T::Array[String]) } def lines; end sig { params(byte_offset: Integer, length: Integer).returns(String) } @@ -40,10 +40,21 @@ class Prism::Source sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } def code_units_offset(byte_offset, encoding); end + sig { params(encoding: Encoding).returns(T.any(Prism::CodeUnitsCache, T.proc.params(byte_offset: Integer).returns(Integer))) } + def code_units_cache(encoding); end + sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } def code_units_column(byte_offset, encoding); end end +class Prism::CodeUnitsCache + sig { params(source: String, encoding: Encoding).void } + def initialize(source, encoding); end + + sig { params(byte_offset: Integer).returns(Integer) } + def [](byte_offset); end +end + class Prism::ASCIISource < Prism::Source sig { params(byte_offset: Integer).returns(Integer) } def character_offset(byte_offset); end @@ -54,6 +65,9 @@ class Prism::ASCIISource < Prism::Source sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } def code_units_offset(byte_offset, encoding); end + sig { params(encoding: Encoding).returns(T.any(Prism::CodeUnitsCache, T.proc.params(byte_offset: Integer).returns(Integer))) } + def code_units_cache(encoding); end + sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } def code_units_column(byte_offset, encoding); end end @@ -107,6 +121,9 @@ class Prism::Location sig { params(encoding: Encoding).returns(Integer) } def start_code_units_offset(encoding = Encoding::UTF_16LE); end + sig { params(cache: T.any(Prism::CodeUnitsCache, T.proc.params(byte_offset: Integer).returns(Integer))).returns(Integer) } + def cached_start_code_units_offset(cache); end + sig { returns(Integer) } def end_offset; end @@ -116,6 +133,9 @@ class Prism::Location sig { params(encoding: Encoding).returns(Integer) } def end_code_units_offset(encoding = Encoding::UTF_16LE); end + sig { params(cache: T.any(Prism::CodeUnitsCache, T.proc.params(byte_offset: Integer).returns(Integer))).returns(Integer) } + def cached_end_code_units_offset(cache); end + sig { returns(Integer) } def start_line; end @@ -134,6 +154,9 @@ class Prism::Location sig { params(encoding: Encoding).returns(Integer) } def start_code_units_column(encoding = Encoding::UTF_16LE); end + sig { params(cache: T.any(Prism::CodeUnitsCache, T.proc.params(byte_offset: Integer).returns(Integer))).returns(Integer) } + def cached_start_code_units_column(cache); end + sig { returns(Integer) } def end_column; end @@ -143,6 +166,9 @@ class Prism::Location sig { params(encoding: Encoding).returns(Integer) } def end_code_units_column(encoding = Encoding::UTF_16LE); end + sig { params(cache: T.any(Prism::CodeUnitsCache, T.proc.params(byte_offset: Integer).returns(Integer))).returns(Integer) } + def cached_end_code_units_column(cache); end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -296,6 +322,9 @@ class Prism::Result sig { returns(T::Boolean) } def failure?; end + + sig { params(encoding: Encoding).returns(T.any(Prism::CodeUnitsCache, T.proc.params(byte_offset: Integer).returns(Integer))) } + def code_units_cache(encoding); end end class Prism::ParseResult < Prism::Result diff --git a/rbi/prism/string_query.rbi b/rbi/prism/string_query.rbi new file mode 100644 index 00000000000..3e5bae1572b --- /dev/null +++ b/rbi/prism/string_query.rbi @@ -0,0 +1,12 @@ +# typed: strict + +class Prism::StringQuery + sig { params(string: String).returns(T::Boolean) } + def self.local?(string); end + + sig { params(string: String).returns(T::Boolean) } + def self.constant?(string); end + + sig { params(string: String).returns(T::Boolean) } + def self.method_name?(string); end +end diff --git a/rust/Cargo.lock b/rust/Cargo.lock index b10780e111e..f115b3be1ae 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -267,7 +267,7 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "ruby-prism" -version = "0.28.0" +version = "1.2.0" dependencies = [ "ruby-prism-sys", "serde", @@ -276,7 +276,7 @@ dependencies = [ [[package]] name = "ruby-prism-sys" -version = "0.28.0" +version = "1.2.0" dependencies = [ "bindgen", "cc", diff --git a/rust/ruby-prism-sys/Cargo.toml b/rust/ruby-prism-sys/Cargo.toml index fddbac66ea0..264dc6e5ca6 100644 --- a/rust/ruby-prism-sys/Cargo.toml +++ b/rust/ruby-prism-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ruby-prism-sys" -version = "0.28.0" +version = "1.2.0" edition = "2021" license-file = "../../LICENSE.md" repository = "https://github.com/ruby/prism" diff --git a/rust/ruby-prism-sys/build/vendored.rs b/rust/ruby-prism-sys/build/vendored.rs index 122fd3e265c..670df42d50a 100644 --- a/rust/ruby-prism-sys/build/vendored.rs +++ b/rust/ruby-prism-sys/build/vendored.rs @@ -74,6 +74,11 @@ fn version() -> &'static str { env!("CARGO_PKG_VERSION") } +/// Generated by running the following command: +/// +/// ```sh +/// bundle exec rake cargo:build +/// ``` fn vendor_dir() -> PathBuf { let prism_dir = format!("prism-{}", version()); Path::new(env!("CARGO_MANIFEST_DIR")).join("vendor").join(prism_dir) diff --git a/rust/ruby-prism-sys/tests/parser_tests.rs b/rust/ruby-prism-sys/tests/parser_tests.rs index 39991797686..cd5308dd547 100644 --- a/rust/ruby-prism-sys/tests/parser_tests.rs +++ b/rust/ruby-prism-sys/tests/parser_tests.rs @@ -85,7 +85,7 @@ fn diagnostics_test() { let message = CStr::from_ptr((*error).message); assert_eq!( message.to_string_lossy(), - "unexpected end of file, assuming it is closing the parent top level context" + "unexpected end-of-input, assuming it is closing the parent top level context" ); let location = { diff --git a/rust/ruby-prism-sys/tests/utils_tests.rs b/rust/ruby-prism-sys/tests/utils_tests.rs index 25c09ce4b31..3a750685791 100644 --- a/rust/ruby-prism-sys/tests/utils_tests.rs +++ b/rust/ruby-prism-sys/tests/utils_tests.rs @@ -12,7 +12,7 @@ fn version_test() { CStr::from_ptr(version) }; - assert_eq!(&cstring.to_string_lossy(), "0.28.0"); + assert_eq!(&cstring.to_string_lossy(), "1.2.0"); } #[test] diff --git a/rust/ruby-prism/Cargo.toml b/rust/ruby-prism/Cargo.toml index 6bf280ccce7..d3497dec3db 100644 --- a/rust/ruby-prism/Cargo.toml +++ b/rust/ruby-prism/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ruby-prism" -version = "0.28.0" +version = "1.2.0" edition = "2021" license-file = "../../LICENSE.md" repository = "https://github.com/ruby/prism" @@ -26,7 +26,7 @@ serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.9" [dependencies] -ruby-prism-sys = { version = "0.28.0", path = "../ruby-prism-sys" } +ruby-prism-sys = { version = "1.2.0", path = "../ruby-prism-sys" } [features] default = ["vendored"] diff --git a/rust/ruby-prism/build.rs b/rust/ruby-prism/build.rs index 958b658191c..0164a118d0d 100644 --- a/rust/ruby-prism/build.rs +++ b/rust/ruby-prism/build.rs @@ -40,9 +40,6 @@ enum NodeFieldType { #[serde(rename = "uint32")] UInt32, - #[serde(rename = "flags")] - Flags, - #[serde(rename = "integer")] Integer, @@ -50,11 +47,27 @@ enum NodeFieldType { Double, } +#[derive(Debug, Deserialize)] +#[allow(dead_code)] +struct OnErrorType { + #[serde(rename = "on error")] + kind: String, +} + +#[derive(Debug, Deserialize)] +#[serde(untagged)] +#[allow(dead_code)] +enum UnionKind { + OnSuccess(String), + OnError(OnErrorType), +} + #[derive(Debug, Deserialize)] #[serde(untagged)] +#[allow(dead_code)] enum NodeFieldKind { Concrete(String), - Union(Vec), + Union(Vec), } #[derive(Debug, Deserialize)] @@ -85,6 +98,8 @@ struct Flags { struct Node { name: String, + flags: Option, + #[serde(default)] fields: Vec, @@ -127,6 +142,13 @@ fn struct_name(name: &str) -> String { result } +fn kind_to_type(kind: &String) -> String { + match kind.as_str() { + "non-void expression" | "pattern expression" | "Node" => String::new(), + _ => kind.to_string(), + } +} + /// Returns the name of the C type from the given node name. fn type_name(name: &str) -> String { let mut result = String::with_capacity(8 + name.len()); @@ -235,6 +257,28 @@ fn write_node(file: &mut File, flags: &[Flags], node: &Node) -> Result<(), Box pm_node_flags_t {{")?; + writeln!(file, " unsafe {{ (*self.pointer).base.flags }}")?; + writeln!(file, " }}")?; + + if let Some(kind) = &node.flags { + let our_flags = flags.iter().filter(|f| &f.name == kind).collect::>(); + assert!(our_flags.len() == 1); + + for flag in our_flags { + for value in &flag.values { + writeln!(file)?; + writeln!(file, " /// {}", value.comment)?; + writeln!(file, " #[must_use]")?; + writeln!(file, " pub fn {}(&self) -> bool {{", accessor_func_name(&value.name))?; + writeln!(file, " (self.flags() & {}) != 0", enum_const_name(&flag.name, &value.name))?; + writeln!(file, " }}")?; + } + } + } for field in &node.fields { writeln!(file)?; @@ -242,30 +286,34 @@ fn write_node(file: &mut File, flags: &[Flags], node: &Node) -> Result<(), Box { - if let Some(NodeFieldKind::Concrete(kind)) = &field.kind { + NodeFieldType::Node => match &field.kind { + Some(NodeFieldKind::Concrete(raw_kind)) if !kind_to_type(raw_kind).is_empty() => { + let kind = kind_to_type(raw_kind); writeln!(file, " pub fn {}(&self) -> {}<'pr> {{", field.name, kind)?; - writeln!(file, " let node: *mut pm{}_t = unsafe {{ (*self.pointer).{} }};", struct_name(kind), field.name)?; + writeln!(file, " let node: *mut pm{}_t = unsafe {{ (*self.pointer).{} }};", struct_name(&kind), field.name)?; writeln!(file, " {} {{ parser: self.parser, pointer: node, marker: PhantomData }}", kind)?; writeln!(file, " }}")?; - } else { + }, + _ => { writeln!(file, " pub fn {}(&self) -> Node<'pr> {{", field.name)?; writeln!(file, " let node: *mut pm_node_t = unsafe {{ (*self.pointer).{} }};", field.name)?; writeln!(file, " Node::new(self.parser, node)")?; writeln!(file, " }}")?; - } + }, }, - NodeFieldType::OptionalNode => { - if let Some(NodeFieldKind::Concrete(kind)) = &field.kind { + NodeFieldType::OptionalNode => match &field.kind { + Some(NodeFieldKind::Concrete(raw_kind)) if !kind_to_type(raw_kind).is_empty() => { + let kind = kind_to_type(raw_kind); writeln!(file, " pub fn {}(&self) -> Option<{}<'pr>> {{", field.name, kind)?; - writeln!(file, " let node: *mut pm{}_t = unsafe {{ (*self.pointer).{} }};", struct_name(kind), field.name)?; + writeln!(file, " let node: *mut pm{}_t = unsafe {{ (*self.pointer).{} }};", struct_name(&kind), field.name)?; writeln!(file, " if node.is_null() {{")?; writeln!(file, " None")?; writeln!(file, " }} else {{")?; writeln!(file, " Some({} {{ parser: self.parser, pointer: node, marker: PhantomData }})", kind)?; writeln!(file, " }}")?; writeln!(file, " }}")?; - } else { + }, + _ => { writeln!(file, " pub fn {}(&self) -> Option> {{", field.name)?; writeln!(file, " let node: *mut pm_node_t = unsafe {{ (*self.pointer).{} }};", field.name)?; writeln!(file, " if node.is_null() {{")?; @@ -274,7 +322,7 @@ fn write_node(file: &mut File, flags: &[Flags], node: &Node) -> Result<(), Box { writeln!(file, " pub fn {}(&self) -> NodeList<'pr> {{", field.name)?; @@ -283,8 +331,12 @@ fn write_node(file: &mut File, flags: &[Flags], node: &Node) -> Result<(), Box { - writeln!(file, " pub const fn {}(&self) -> &str {{", field.name)?; - writeln!(file, " \"\"")?; + writeln!(file, " pub fn {}(&self) -> &[u8] {{", field.name)?; + writeln!(file, " unsafe {{")?; + writeln!(file, " let source = (*self.pointer).{}.source;", field.name)?; + writeln!(file, " let length = (*self.pointer).{}.length;", field.name)?; + writeln!(file, " std::slice::from_raw_parts(source, length)")?; + writeln!(file, " }}")?; writeln!(file, " }}")?; }, NodeFieldType::Constant => { @@ -335,27 +387,6 @@ fn write_node(file: &mut File, flags: &[Flags], node: &Node) -> Result<(), Box { - let Some(NodeFieldKind::Concrete(kind)) = &field.kind else { - panic!("Flag fields must have a concrete kind"); - }; - let our_flags = flags.iter().filter(|f| &f.name == kind).collect::>(); - assert!(our_flags.len() == 1); - - writeln!(file, " fn {}(&self) -> pm_node_flags_t {{", field.name)?; - writeln!(file, " unsafe {{ (*self.pointer).base.flags }}")?; - writeln!(file, " }}")?; - - for flag in our_flags { - for value in &flag.values { - writeln!(file, " /// {}", value.comment)?; - writeln!(file, " #[must_use]")?; - writeln!(file, " pub fn {}(&self) -> bool {{", accessor_func_name(&value.name))?; - writeln!(file, " (self.{}() & {}) != 0", field.name, enum_const_name(&flag.name, &value.name))?; - writeln!(file, " }}")?; - } - } - }, NodeFieldType::Integer => { writeln!(file, " pub fn {}(&self) -> Integer<'pr> {{", field.name)?; writeln!(file, " Integer::new(unsafe {{ &(*self.pointer).{} }})", field.name)?; @@ -469,16 +500,18 @@ fn write_visit(file: &mut File, config: &Config) -> Result<(), Box { - if let Some(NodeFieldKind::Concrete(kind)) = &field.kind { - writeln!(file, " visitor.visit{}(&node.{}());", struct_name(kind), field.name)?; + if let Some(NodeFieldKind::Concrete(raw_kind)) = &field.kind { + let kind = kind_to_type(raw_kind); + writeln!(file, " visitor.visit{}(&node.{}());", struct_name(&kind), field.name)?; } else { writeln!(file, " visitor.visit(&node.{}());", field.name)?; } }, NodeFieldType::OptionalNode => { - if let Some(NodeFieldKind::Concrete(kind)) = &field.kind { + if let Some(NodeFieldKind::Concrete(raw_kind)) = &field.kind { + let kind = kind_to_type(raw_kind); writeln!(file, " if let Some(node) = node.{}() {{", field.name)?; - writeln!(file, " visitor.visit{}(&node);", struct_name(kind))?; + writeln!(file, " visitor.visit{}(&node);", struct_name(&kind))?; writeln!(file, " }}")?; } else { writeln!(file, " if let Some(node) = node.{}() {{", field.name)?; @@ -758,7 +791,7 @@ impl TryInto for Integer<'_> {{ let length = unsafe {{ (*self.pointer).length }}; if length == 0 {{ - i32::try_from(unsafe {{ (*self.pointer).value }}).map_or(Err(()), |value| + i32::try_from(unsafe {{ (*self.pointer).value }}).map_or(Err(()), |value| if negative {{ Ok(-value) }} else {{ diff --git a/rust/ruby-prism/src/lib.rs b/rust/ruby-prism/src/lib.rs index 03d6ca7e09f..64cc6f9d95f 100644 --- a/rust/ruby-prism/src/lib.rs +++ b/rust/ruby-prism/src/lib.rs @@ -198,6 +198,17 @@ impl<'pr> ParseResult<'pr> { } } + /// Returns an optional location of the __END__ marker and the rest of the content of the file. + #[must_use] + pub fn data_loc(&self) -> Option> { + let location = unsafe { &(*self.parser.as_ptr()).data_loc }; + if location.start.is_null() { + None + } else { + Some(Location::new(self.parser, location)) + } + } + /// Returns the root node of the parse result. #[must_use] pub fn node(&self) -> Node<'_> { @@ -254,6 +265,26 @@ mod tests { } } + #[test] + fn data_loc_test() { + let source = "1"; + let result = parse(source.as_ref()); + let data_loc = result.data_loc(); + assert!(data_loc.is_none()); + + let source = "__END__\nabc\n"; + let result = parse(source.as_ref()); + let data_loc = result.data_loc().unwrap(); + let slice = std::str::from_utf8(result.as_slice(&data_loc)).unwrap(); + assert_eq!(slice, "__END__\nabc\n"); + + let source = "1\n2\n3\n__END__\nabc\ndef\n"; + let result = parse(source.as_ref()); + let data_loc = result.data_loc().unwrap(); + let slice = std::str::from_utf8(result.as_slice(&data_loc)).unwrap(); + assert_eq!(slice, "__END__\nabc\ndef\n"); + } + #[test] fn location_test() { let source = "111 + 222 + 333"; diff --git a/sample/prism/find_calls.rb b/sample/prism/find_calls.rb new file mode 100644 index 00000000000..30af56c719d --- /dev/null +++ b/sample/prism/find_calls.rb @@ -0,0 +1,105 @@ +# This script finds calls to a specific method with a certain keyword parameter +# within a given source file. + +require "prism" +require "pp" + +# For deprecation or refactoring purposes, it's often useful to find all of the +# places that call a specific method with a specific k eyword parameter. This is +# easily accomplished with a visitor such as this one. +class QuxParameterVisitor < Prism::Visitor + def initialize(calls) + @calls = calls + end + + def visit_call_node(node) + @calls << node if qux?(node) + super + end + + private + + def qux?(node) + # All nodes implement pattern matching, so you can use the `in` operator to + # pull out all of their individual fields. As you can see by this extensive + # pattern match, this is quite a powerful feature. + node in { + # This checks that the receiver is the constant Qux or the constant path + # ::Qux. We are assuming relative constants are fine in this case. + receiver: ( + Prism::ConstantReadNode[name: :Qux] | + Prism::ConstantPathNode[parent: nil, name: :Qux] + ), + # This checks that the name of the method is qux. We purposefully are not + # checking the call operator (., ::, or &.) because we want all of them. + # In other ASTs, this would be multiple node types, but prism combines + # them all into one for convenience. + name: :qux, + arguments: Prism::ArgumentsNode[ + # Here we're going to use the "find" pattern to find the keyword hash + # node that has the correct key. + arguments: [ + *, + Prism::KeywordHashNode[ + # Here we'll use another "find" pattern to find the key that we are + # specifically looking for. + elements: [ + *, + # Finally, we can assert against the key itself. Note that we are + # not looking at the value of hash pair, because we are only + # specifically looking for a key. + Prism::AssocNode[key: Prism::SymbolNode[unescaped: "qux"]], + * + ] + ], + * + ] + ] + } + end +end + +calls = [] +Prism.parse_stream(DATA).value.accept(QuxParameterVisitor.new(calls)) + +calls.each do |call| + print "CallNode " + puts PP.pp(call.location, +"") + print " " + puts call.slice +end + +# => +# CallNode (5,6)-(5,29) +# Qux.qux(222, qux: true) +# CallNode (9,6)-(9,30) +# Qux&.qux(333, qux: true) +# CallNode (20,6)-(20,51) +# Qux::qux(888, qux: ::Qux.qux(999, qux: true)) +# CallNode (20,25)-(20,50) +# ::Qux.qux(999, qux: true) + +__END__ +module Foo + class Bar + def baz1 + Qux.qux(111) + Qux.qux(222, qux: true) + end + + def baz2 + Qux&.qux(333, qux: true) + Qux&.qux(444) + end + + def baz3 + qux(555, qux: false) + 666.qux(666) + end + + def baz4 + Qux::qux(777) + Qux::qux(888, qux: ::Qux.qux(999, qux: true)) + end + end +end diff --git a/sample/prism/find_comments.rb b/sample/prism/find_comments.rb new file mode 100644 index 00000000000..6a26cd32b7c --- /dev/null +++ b/sample/prism/find_comments.rb @@ -0,0 +1,100 @@ +# This script finds all of the comments within a given source file for a method. + +require "prism" + +class FindMethodComments < Prism::Visitor + def initialize(target, comments, nesting = []) + @target = target + @comments = comments + @nesting = nesting + end + + # These visit methods are specific to each class. Defining a visitor allows + # you to group functionality that applies to all node types into a single + # class. You can find which method corresponds to which node type by looking + # at the class name, calling #type on the node, or by looking at the #accept + # method definition on the node. + def visit_module_node(node) + visitor = FindMethodComments.new(@target, @comments, [*@nesting, node.name]) + node.compact_child_nodes.each { |child| child.accept(visitor) } + end + + def visit_class_node(node) + # We could keep track of an internal state where we push the class name here + # and then pop it after the visit is complete. However, it is often simpler + # and cleaner to generate a new visitor instance when the state changes, + # because then the state is immutable and it's easier to reason about. This + # also provides for more debugging opportunity in the initializer. + visitor = FindMethodComments.new(@target, @comments, [*@nesting, node.name]) + node.compact_child_nodes.each { |child| child.accept(visitor) } + end + + def visit_def_node(node) + if [*@nesting, node.name] == @target + # Comments are always attached to locations (either inner locations on a + # node like the location of a keyword or the location on the node itself). + # Nodes are considered either "leading" or "trailing", which means that + # they occur before or after the location, respectively. In this case of + # documentation, we only want to consider leading comments. You can also + # fetch all of the comments on a location with #comments. + @comments.concat(node.location.leading_comments) + else + super + end + end +end + +# Most of the time, the concept of "finding" something in the AST can be +# accomplished either with a queue or with a visitor. In this case we will use a +# visitor, but a queue would work just as well. +def find_comments(result, path) + target = path.split(/::|#/).map(&:to_sym) + comments = [] + + result.value.accept(FindMethodComments.new(target, comments)) + comments +end + +result = Prism.parse_stream(DATA) +result.attach_comments! + +find_comments(result, "Foo#foo").each do |comment| + puts comment.inspect + puts comment.slice +end + +# => +# #> +# # This is the documentation +# #> +# # for the foo method. + +find_comments(result, "Foo::Bar#bar").each do |comment| + puts comment.inspect + puts comment.slice +end + +# => +# #> +# # This is documentation +# #> +# # for the bar method. + +__END__ +# This is the documentation +# for the Foo module. +module Foo + # This is documentation + # for the Bar class. + class Bar + # This is documentation + # for the bar method. + def bar + end + end + + # This is the documentation + # for the foo method. + def foo + end +end diff --git a/sample/prism/locate_nodes.rb b/sample/prism/locate_nodes.rb new file mode 100644 index 00000000000..7a51db43675 --- /dev/null +++ b/sample/prism/locate_nodes.rb @@ -0,0 +1,84 @@ +# This script locates a set of nodes determined by a line and column (in bytes). + +require "prism" +require "pp" + +# This method determines if the given location covers the given line and column. +# It's important to note that columns (and offsets) in prism are always in +# bytes. This is because prism supports all 90 source encodings that Ruby +# supports. You can always retrieve the column (or offset) of a location in +# other units with other provided APIs, like #start_character_column or +# #start_code_units_column. +def covers?(location, line:, column:) + start_line = location.start_line + end_line = location.end_line + + if start_line == end_line + # If the location only spans one line, then we only check if the line + # matches and that the column is covered by the column range. + line == start_line && (location.start_column...location.end_column).cover?(column) + else + # Otherwise, we check that it is on the start line and the column is greater + # than or equal to the start column, or that it is on the end line and the + # column is less than the end column, or that it is between the start and + # end lines. + (line == start_line && column >= location.start_column) || + (line == end_line && column < location.end_column) || + (line > start_line && line < end_line) + end +end + +# This method descends down into the AST whose root is `node` and returns the +# array of all of the nodes that cover the given line and column. +def locate(node, line:, column:) + queue = [node] + result = [] + + # We could use a recursive method here instead if we wanted, but it's + # important to note that that will not work for ASTs that are nested deeply + # enough to cause a stack overflow. + while (node = queue.shift) + result << node + + # Nodes have `child_nodes` and `compact_child_nodes`. `child_nodes` have + # consistent indices but include `nil` for optional fields that are not + # present, whereas `compact_child_nodes` has inconsistent indices but does + # not include `nil` for optional fields that are not present. + node.compact_child_nodes.find do |child| + queue << child if covers?(child.location, line: line, column: column) + end + end + + result +end + +result = Prism.parse_stream(DATA) +locate(result.value, line: 4, column: 14).each_with_index do |node, index| + print " " * index + print node.class.name.split("::", 2).last + print " " + puts PP.pp(node.location, +"") +end + +# => +# ProgramNode (1,0)-(7,3) +# StatementsNode (1,0)-(7,3) +# ModuleNode (1,0)-(7,3) +# StatementsNode (2,2)-(6,5) +# ClassNode (2,2)-(6,5) +# StatementsNode (3,4)-(5,7) +# DefNode (3,4)-(5,7) +# StatementsNode (4,6)-(4,21) +# CallNode (4,6)-(4,21) +# CallNode (4,6)-(4,15) +# ArgumentsNode (4,12)-(4,15) +# IntegerNode (4,12)-(4,15) + +__END__ +module Foo + class Bar + def baz + 111 + 222 + 333 + end + end +end diff --git a/sample/prism/make_tags.rb b/sample/prism/make_tags.rb new file mode 100644 index 00000000000..dc770ab1b08 --- /dev/null +++ b/sample/prism/make_tags.rb @@ -0,0 +1,302 @@ +# This script generates a tags file using Prism to parse the Ruby files. + +require "prism" + +# This visitor is responsible for visiting the nodes in the AST and generating +# the appropriate tags. The tags are stored in the entries array as strings. +class TagsVisitor < Prism::Visitor + # This represents an entry in the tags file, which is a tab-separated line. It + # houses the logic for how an entry is constructed. + class Entry + attr_reader :parts + + def initialize(name, filepath, pattern, type) + @parts = [name, filepath, pattern, type] + end + + def attribute(key, value) + parts << "#{key}:#{value}" + end + + def attribute_class(nesting, names) + return if nesting.empty? && names.length == 1 + attribute("class", [*nesting, names].flatten.tap(&:pop).join(".")) + end + + def attribute_inherits(names) + attribute("inherits", names.join(".")) if names + end + + def to_line + parts.join("\t") + end + end + + private_constant :Entry + + attr_reader :entries, :filepath, :lines, :nesting, :singleton + + # Initialize the visitor with the given parameters. The first three parameters + # are constant throughout the visit, while the last two are controlled by the + # visitor as it traverses the AST. These are treated as immutable by virtue of + # the visit methods constructing new visitors when they need to change. + def initialize(entries, filepath, lines, nesting = [], singleton = false) + @entries = entries + @filepath = filepath + @lines = lines + @nesting = nesting + @singleton = singleton + end + + # Visit a method alias node and generate the appropriate tags. + # + # alias m2 m1 + # + def visit_alias_method_node(node) + enter(node.new_name.unescaped.to_sym, node, "a") do |entry| + entry.attribute_class(nesting, [nil]) + end + + super + end + + # Visit a method call to attr_reader, attr_writer, or attr_accessor without a + # receiver and generate the appropriate tags. Note that this ignores the fact + # that these methods could be overridden, which is a limitation of this + # script. + # + # attr_accessor :m1 + # + def visit_call_node(node) + if !node.receiver && %i[attr_reader attr_writer attr_accessor].include?(name = node.name) + (node.arguments&.arguments || []).grep(Prism::SymbolNode).each do |argument| + if name != :attr_writer + enter(:"#{argument.unescaped}", argument, singleton ? "F" : "f") do |entry| + entry.attribute_class(nesting, [nil]) + end + end + + if name != :attr_reader + enter(:"#{argument.unescaped}=", argument, singleton ? "F" : "f") do |entry| + entry.attribute_class(nesting, [nil]) + end + end + end + end + + super + end + + # Visit a class node and generate the appropriate tags. + # + # class C1 + # end + # + def visit_class_node(node) + if (names = names_for(node.constant_path)) + enter(names.last, node, "c") do |entry| + entry.attribute_class(nesting, names) + entry.attribute_inherits(names_for(node.superclass)) + end + + node.body&.accept(copy_visitor([*nesting, names], singleton)) + end + end + + # Visit a constant path write node and generate the appropriate tags. + # + # C1::C2 = 1 + # + def visit_constant_path_write_node(node) + if (names = names_for(node.target)) + enter(names.last, node, "C") do |entry| + entry.attribute_class(nesting, names) + end + end + + super + end + + # Visit a constant write node and generate the appropriate tags. + # + # C1 = 1 + # + def visit_constant_write_node(node) + enter(node.name, node, "C") do |entry| + entry.attribute_class(nesting, [nil]) + end + + super + end + + # Visit a method definition node and generate the appropriate tags. + # + # def m1; end + # + def visit_def_node(node) + enter(node.name, node, (node.receiver || singleton) ? "F" : "f") do |entry| + entry.attribute_class(nesting, [nil]) + end + + super + end + + # Visit a module node and generate the appropriate tags. + # + # module M1 + # end + # + def visit_module_node(node) + if (names = names_for(node.constant_path)) + enter(names.last, node, "m") do |entry| + entry.attribute_class(nesting, names) + end + + node.body&.accept(copy_visitor([*nesting, names], singleton)) + end + end + + # Visit a singleton class node and generate the appropriate tags. + # + # class << self + # end + # + def visit_singleton_class_node(node) + case node.expression + when Prism::SelfNode + node.body&.accept(copy_visitor(nesting, true)) + when Prism::ConstantReadNode, Prism::ConstantPathNode + if (names = names_for(node.expression)) + node.body&.accept(copy_visitor([*nesting, names], true)) + end + else + node.body&.accept(copy_visitor([*nesting, nil], true)) + end + end + + private + + # Generate a new visitor with the given dynamic options. The static options + # are copied over automatically. + def copy_visitor(nesting, singleton) + TagsVisitor.new(entries, filepath, lines, nesting, singleton) + end + + # Generate a new entry for the given name, node, and type and add it into the + # list of entries. The block is used to add additional attributes to the + # entry. + def enter(name, node, type) + line = lines[node.location.start_line - 1].chomp + pattern = "/^#{line.gsub("\\", "\\\\\\\\").gsub("/", "\\/")}$/;\"" + + entry = Entry.new(name, filepath, pattern, type) + yield entry + + entries << entry.to_line + end + + # Retrieve the names for the given node. This is used to construct the class + # attribute for the tags. + def names_for(node) + case node + when Prism::ConstantPathNode + names = names_for(node.parent) + return unless names + + names << node.name + when Prism::ConstantReadNode + [node.name] + when Prism::SelfNode + [:self] + else + # dynamic + end + end +end + +# Parse the Ruby file and visit all of the nodes in the resulting AST. Once all +# of the nodes have been visited, the entries array should be populated with the +# tags. +result = Prism.parse_stream(DATA) +result.value.accept(TagsVisitor.new(entries = [], __FILE__, result.source.lines)) + +# Print the tags to STDOUT. +puts "!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;\" to lines/" +puts "!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/" +puts entries.sort + +# => +# !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +# !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +# C1 sample/prism/make_tags.rb /^ class C1$/;" c class:M1.M2 +# C2 sample/prism/make_tags.rb /^ class C2 < Object$/;" c class:M1.M2.C1 inherits:Object +# C6 sample/prism/make_tags.rb /^ C6 = 1$/;" C class:M1 +# C7 sample/prism/make_tags.rb /^ C7 = 2$/;" C class:M1 +# C9 sample/prism/make_tags.rb /^ C8::C9 = 3$/;" C class:M1.C8 +# M1 sample/prism/make_tags.rb /^module M1$/;" m +# M2 sample/prism/make_tags.rb /^ module M2$/;" m class:M1 +# M4 sample/prism/make_tags.rb /^ module M3::M4$/;" m class:M1.M3 +# M5 sample/prism/make_tags.rb /^ module self::M5$/;" m class:M1.self +# m1 sample/prism/make_tags.rb /^ def m1; end$/;" f class:M1.M2.C1.C2 +# m10 sample/prism/make_tags.rb /^ attr_accessor :m10, :m11$/;" f class:M1.M3.M4 +# m10= sample/prism/make_tags.rb /^ attr_accessor :m10, :m11$/;" f class:M1.M3.M4 +# m11 sample/prism/make_tags.rb /^ attr_accessor :m10, :m11$/;" f class:M1.M3.M4 +# m11= sample/prism/make_tags.rb /^ attr_accessor :m10, :m11$/;" f class:M1.M3.M4 +# m12 sample/prism/make_tags.rb /^ attr_reader :m12, :m13, :m14$/;" f class:M1.M3.M4 +# m13 sample/prism/make_tags.rb /^ attr_reader :m12, :m13, :m14$/;" f class:M1.M3.M4 +# m14 sample/prism/make_tags.rb /^ attr_reader :m12, :m13, :m14$/;" f class:M1.M3.M4 +# m15= sample/prism/make_tags.rb /^ attr_writer :m15$/;" f class:M1.M3.M4 +# m2 sample/prism/make_tags.rb /^ def m2; end$/;" f class:M1.M2.C1.C2 +# m3 sample/prism/make_tags.rb /^ alias m3 m1$/;" a class:M1.M2.C1.C2 +# m4 sample/prism/make_tags.rb /^ alias :m4 :m2$/;" a class:M1.M2.C1.C2 +# m5 sample/prism/make_tags.rb /^ def self.m5; end$/;" F class:M1.M2.C1.C2 +# m6 sample/prism/make_tags.rb /^ def m6; end$/;" F class:M1.M2.C1.C2 +# m7 sample/prism/make_tags.rb /^ def m7; end$/;" F class:M1.M2.C1.C2.C3 +# m8 sample/prism/make_tags.rb /^ def m8; end$/;" F class:M1.M2.C1.C2.C4.C5 +# m9 sample/prism/make_tags.rb /^ def m9; end$/;" F class:M1.M2.C1.C2. + +__END__ +module M1 + module M2 + class C1 + class C2 < Object + def m1; end + def m2; end + + alias m3 m1 + alias :m4 :m2 + + def self.m5; end + + class << self + def m6; end + end + + class << C3 + def m7; end + end + + class << C4::C5 + def m8; end + end + + class << c + def m9; end + end + end + end + end + + module M3::M4 + attr_accessor :m10, :m11 + attr_reader :m12, :m13, :m14 + attr_writer :m15 + end + + module self::M5 + end + + C6 = 1 + C7 = 2 + C8::C9 = 3 +end diff --git a/sample/prism/visit_nodes.rb b/sample/prism/visit_nodes.rb new file mode 100644 index 00000000000..5ba703b0a36 --- /dev/null +++ b/sample/prism/visit_nodes.rb @@ -0,0 +1,63 @@ +# This script visits all of the nodes of a specific type within a given source +# file. It uses the visitor class to traverse the AST. + +require "prism" +require "pp" + +class CaseInsensitiveRegularExpressionVisitor < Prism::Visitor + def initialize(regexps) + @regexps = regexps + end + + # As the visitor is walking the tree, this method will only be called when it + # encounters a regular expression node. We can then call any regular + # expression -specific APIs. In this case, we are only interested in the + # regular expressions that are case-insensitive, which we can retrieve with + # the #ignore_case? method. + def visit_regular_expression_node(node) + @regexps << node if node.ignore_case? + super + end + + def visit_interpolated_regular_expression_node(node) + @regexps << node if node.ignore_case? + + # The default behavior of the visitor is to continue visiting the children + # of the node. Because Ruby is so dynamic, it's actually possible for + # another regular expression to be interpolated in statements contained + # within the #{} contained in this interpolated regular expression node. By + # calling `super`, we ensure the visitor will continue. Failing to call + # `super` will cause the visitor to stop the traversal of the tree, which + # can also be useful in some cases. + super + end +end + +result = Prism.parse_stream(DATA) +regexps = [] + +result.value.accept(CaseInsensitiveRegularExpressionVisitor.new(regexps)) +regexps.each do |node| + print node.class.name.split("::", 2).last + print " " + puts PP.pp(node.location, +"") + + if node.is_a?(Prism::RegularExpressionNode) + print " " + p node.unescaped + end +end + +# => +# InterpolatedRegularExpressionNode (3,9)-(3,47) +# RegularExpressionNode (3,16)-(3,22) +# "bar" +# RegularExpressionNode (4,9)-(4,15) +# "bar" + +__END__ +class Foo + REG1 = /foo/ + REG2 = /foo #{/bar/i =~ "" ? "bar" : "baz"}/i + REG3 = /bar/i +end diff --git a/sig/prism/_private/node.rbs b/sig/prism/_private/node.rbs index 9a30e802df9..b5918a71333 100644 --- a/sig/prism/_private/node.rbs +++ b/sig/prism/_private/node.rbs @@ -1,8 +1,8 @@ module Prism class Node - @newline: bool + @newline_flag: bool - def newline?: () -> bool - def set_newline_flag: (Array[bool]) -> void + def newline_flag?: () -> bool + def newline_flag!: (Array[bool] lines) -> void end end diff --git a/sig/prism/_private/parse_result.rbs b/sig/prism/_private/parse_result.rbs index 9a1eb0ac1c9..659bedcfe34 100644 --- a/sig/prism/_private/parse_result.rbs +++ b/sig/prism/_private/parse_result.rbs @@ -5,6 +5,18 @@ module Prism def find_line: (Integer) -> Integer end + class CodeUnitsCache + class UTF16Counter + def initialize: (String source, Encoding encoding) -> void + def count: (Integer byte_offset, Integer byte_length) -> Integer + end + + class LengthCounter + def initialize: (String source, Encoding encoding) -> void + def count: (Integer byte_offset, Integer byte_length) -> Integer + end + end + class Location private @@ -49,6 +61,13 @@ module Prism def nearest_targets: (Prism::node, comment) -> (untyped | ::Array[untyped]) end + class Errors + attr_reader parse_result: ParseResult + + def initialize: (ParseResult parse_result) -> void + def format: () -> String + end + class Newlines < Visitor @newline_marked: Array[bool] diff --git a/sig/prism/_private/string_query.rbs b/sig/prism/_private/string_query.rbs new file mode 100644 index 00000000000..47ea2ca1a07 --- /dev/null +++ b/sig/prism/_private/string_query.rbs @@ -0,0 +1,7 @@ +module Prism + class StringQuery + def self.local?: (String string) -> bool + def self.constant?: (String string) -> bool + def self.method_name?: (String string) -> bool + end +end diff --git a/sig/prism/_private/lex_compat.rbs b/sig/prism/lex_compat.rbs similarity index 100% rename from sig/prism/_private/lex_compat.rbs rename to sig/prism/lex_compat.rbs diff --git a/sig/prism/node_ext.rbs b/sig/prism/node_ext.rbs index 92898d36509..d485092f1ae 100644 --- a/sig/prism/node_ext.rbs +++ b/sig/prism/node_ext.rbs @@ -75,4 +75,8 @@ module Prism class ParametersNode < Node def signature: () -> Array[[Symbol, Symbol] | [Symbol]] end + + class CallNode < Node + def full_message_loc: () -> Location? + end end diff --git a/sig/prism/parse_result.rbs b/sig/prism/parse_result.rbs index 3487d5412ca..d81fe90966b 100644 --- a/sig/prism/parse_result.rbs +++ b/sig/prism/parse_result.rbs @@ -1,4 +1,8 @@ module Prism + interface _CodeUnitsCache + def []: (Integer byte_offset) -> Integer + end + class Source attr_reader source: String attr_reader start_line: Integer @@ -16,13 +20,22 @@ module Prism def character_offset: (Integer byte_offset) -> Integer def character_column: (Integer byte_offset) -> Integer def code_units_offset: (Integer byte_offset, Encoding encoding) -> Integer + def code_units_cache: (Encoding encoding) -> _CodeUnitsCache def code_units_column: (Integer byte_offset, Encoding encoding) -> Integer + + def self.for: (String source) -> Source + end + + class CodeUnitsCache + def initialize: (String source, Encoding encoding) -> void + def []: (Integer byte_offset) -> Integer end class ASCIISource < Source def character_offset: (Integer byte_offset) -> Integer def character_column: (Integer byte_offset) -> Integer def code_units_offset: (Integer byte_offset, Encoding encoding) -> Integer + def code_units_cache: (Encoding encoding) -> _CodeUnitsCache def code_units_column: (Integer byte_offset, Encoding encoding) -> Integer end @@ -43,15 +56,23 @@ module Prism def slice: () -> String def slice_lines: () -> String def start_character_offset: () -> Integer + def start_code_units_offset: (Encoding encoding) -> Integer + def cached_start_code_units_offset: (_CodeUnitsCache cache) -> Integer def end_offset: () -> Integer def end_character_offset: () -> Integer + def end_code_units_offset: (Encoding encoding) -> Integer + def cached_end_code_units_offset: (_CodeUnitsCache cache) -> Integer def start_line: () -> Integer def start_line_slice: () -> String def end_line: () -> Integer def start_column: () -> Integer def start_character_column: () -> Integer + def start_code_units_column: (Encoding encoding) -> Integer + def cached_start_code_units_column: (_CodeUnitsCache cache) -> Integer def end_column: () -> Integer def end_character_column: () -> Integer + def end_code_units_column: (Encoding encoding) -> Integer + def cached_end_code_units_column: (_CodeUnitsCache cache) -> Integer def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] def pretty_print: (untyped q) -> untyped def join: (Location other) -> Location @@ -123,6 +144,7 @@ module Prism def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] def success?: () -> bool def failure?: () -> bool + def code_units_cache: (Encoding encoding) -> _CodeUnitsCache end class ParseResult < Result diff --git a/sig/prism/string_query.rbs b/sig/prism/string_query.rbs new file mode 100644 index 00000000000..098746e5529 --- /dev/null +++ b/sig/prism/string_query.rbs @@ -0,0 +1,11 @@ +module Prism + class StringQuery + attr_reader string: String + + def initialize: (String string) -> void + + def local?: () -> bool + def constant?: () -> bool + def method_name?: () -> bool + end +end diff --git a/src/options.c b/src/options.c index 664db4f061b..6b52b2f2960 100644 --- a/src/options.c +++ b/src/options.c @@ -1,5 +1,14 @@ #include "prism/options.h" +/** + * Set the shebang callback option on the given options struct. + */ +PRISM_EXPORTED_FUNCTION void +pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callback_t shebang_callback, void *shebang_callback_data) { + options->shebang_callback = shebang_callback; + options->shebang_callback_data = shebang_callback_data; +} + /** * Set the filepath option on the given options struct. */ @@ -16,6 +25,14 @@ pm_options_encoding_set(pm_options_t *options, const char *encoding) { pm_string_constant_init(&options->encoding, encoding, strlen(encoding)); } +/** + * Set the encoding_locked option on the given options struct. + */ +PRISM_EXPORTED_FUNCTION void +pm_options_encoding_locked_set(pm_options_t *options, bool encoding_locked) { + options->encoding_locked = encoding_locked; +} + /** * Set the line option on the given options struct. */ @@ -40,6 +57,14 @@ pm_options_command_line_set(pm_options_t *options, uint8_t command_line) { options->command_line = command_line; } +/** + * Checks if the given slice represents a number. + */ +static inline bool +is_number(const char *string, size_t length) { + return pm_strspn_decimal_digit((const uint8_t *) string, (ptrdiff_t) length) == length; +} + /** * Set the version option on the given options struct by parsing the given * string. If the string contains an invalid option, this returns false. @@ -47,40 +72,61 @@ pm_options_command_line_set(pm_options_t *options, uint8_t command_line) { */ PRISM_EXPORTED_FUNCTION bool pm_options_version_set(pm_options_t *options, const char *version, size_t length) { - switch (length) { - case 0: - if (version == NULL) { - options->version = PM_OPTIONS_VERSION_LATEST; - return true; - } + if (version == NULL) { + options->version = PM_OPTIONS_VERSION_LATEST; + return true; + } - return false; - case 5: - assert(version != NULL); + if (length == 3) { + if (strncmp(version, "3.3", 3) == 0) { + options->version = PM_OPTIONS_VERSION_CRUBY_3_3; + return true; + } - if ((strncmp(version, "3.3.0", length) == 0) || (strncmp(version, "3.3.1", length) == 0)) { - options->version = PM_OPTIONS_VERSION_CRUBY_3_3; - return true; - } + if (strncmp(version, "3.4", 3) == 0) { + options->version = PM_OPTIONS_VERSION_LATEST; + return true; + } - if (strncmp(version, "3.4.0", length) == 0) { - options->version = PM_OPTIONS_VERSION_LATEST; - return true; - } + return false; + } - return false; - case 6: - assert(version != NULL); + if (length >= 4) { + if (strncmp(version, "3.3.", 4) == 0 && is_number(version + 4, length - 4)) { + options->version = PM_OPTIONS_VERSION_CRUBY_3_3; + return true; + } - if (strncmp(version, "latest", length) == 0) { - options->version = PM_OPTIONS_VERSION_LATEST; - return true; - } + if (strncmp(version, "3.4.", 4) == 0 && is_number(version + 4, length - 4)) { + options->version = PM_OPTIONS_VERSION_LATEST; + return true; + } + } - return false; - default: - return false; + if (length >= 6) { + if (strncmp(version, "latest", 7) == 0) { // 7 to compare the \0 as well + options->version = PM_OPTIONS_VERSION_LATEST; + return true; + } } + + return false; +} + +/** + * Set the main script option on the given options struct. + */ +PRISM_EXPORTED_FUNCTION void +pm_options_main_script_set(pm_options_t *options, bool main_script) { + options->main_script = main_script; +} + +/** + * Set the partial script option on the given options struct. + */ +PRISM_EXPORTED_FUNCTION void +pm_options_partial_script_set(pm_options_t *options, bool partial_script) { + options->partial_script = partial_script; } // For some reason, GCC analyzer thinks we're leaking allocated scopes and @@ -215,6 +261,9 @@ pm_options_read(pm_options_t *options, const char *data) { options->frozen_string_literal = (int8_t) *data++; options->command_line = (uint8_t) *data++; options->version = (pm_options_version_t) *data++; + options->encoding_locked = ((uint8_t) *data++) > 0; + options->main_script = ((uint8_t) *data++) > 0; + options->partial_script = ((uint8_t) *data++) > 0; uint32_t scopes_count = pm_options_read_u32(data); data += 4; diff --git a/src/prism.c b/src/prism.c index 9395e462875..ff5fd933f68 100644 --- a/src/prism.c +++ b/src/prism.c @@ -14,180 +14,6 @@ pm_version(void) { */ #define PM_TAB_WHITESPACE_SIZE 8 -#ifndef PM_DEBUG_LOGGING -/** - * Debugging logging will provide you with additional debugging functions as - * well as automatically replace some functions with their debugging - * counterparts. - */ -#define PM_DEBUG_LOGGING 0 -#endif - -#if PM_DEBUG_LOGGING - -/******************************************************************************/ -/* Debugging */ -/******************************************************************************/ - -PRISM_ATTRIBUTE_UNUSED static const char * -debug_context(pm_context_t context) { - switch (context) { - case PM_CONTEXT_BEGIN: return "BEGIN"; - case PM_CONTEXT_BEGIN_ENSURE: return "BEGIN_ENSURE"; - case PM_CONTEXT_BEGIN_ELSE: return "BEGIN_ELSE"; - case PM_CONTEXT_BEGIN_RESCUE: return "BEGIN_RESCUE"; - case PM_CONTEXT_BLOCK_BRACES: return "BLOCK_BRACES"; - case PM_CONTEXT_BLOCK_KEYWORDS: return "BLOCK_KEYWORDS"; - case PM_CONTEXT_BLOCK_ENSURE: return "BLOCK_ENSURE"; - case PM_CONTEXT_BLOCK_ELSE: return "BLOCK_ELSE"; - case PM_CONTEXT_BLOCK_RESCUE: return "BLOCK_RESCUE"; - case PM_CONTEXT_CASE_IN: return "CASE_IN"; - case PM_CONTEXT_CASE_WHEN: return "CASE_WHEN"; - case PM_CONTEXT_CLASS: return "CLASS"; - case PM_CONTEXT_CLASS_ELSE: return "CLASS_ELSE"; - case PM_CONTEXT_CLASS_ENSURE: return "CLASS_ENSURE"; - case PM_CONTEXT_CLASS_RESCUE: return "CLASS_RESCUE"; - case PM_CONTEXT_DEF: return "DEF"; - case PM_CONTEXT_DEF_PARAMS: return "DEF_PARAMS"; - case PM_CONTEXT_DEF_ENSURE: return "DEF_ENSURE"; - case PM_CONTEXT_DEF_ELSE: return "DEF_ELSE"; - case PM_CONTEXT_DEF_RESCUE: return "DEF_RESCUE"; - case PM_CONTEXT_DEFAULT_PARAMS: return "DEFAULT_PARAMS"; - case PM_CONTEXT_DEFINED: return "DEFINED"; - case PM_CONTEXT_ELSE: return "ELSE"; - case PM_CONTEXT_ELSIF: return "ELSIF"; - case PM_CONTEXT_EMBEXPR: return "EMBEXPR"; - case PM_CONTEXT_FOR_INDEX: return "FOR_INDEX"; - case PM_CONTEXT_FOR: return "FOR"; - case PM_CONTEXT_IF: return "IF"; - case PM_CONTEXT_LAMBDA_BRACES: return "LAMBDA_BRACES"; - case PM_CONTEXT_LAMBDA_DO_END: return "LAMBDA_DO_END"; - case PM_CONTEXT_LAMBDA_ENSURE: return "LAMBDA_ENSURE"; - case PM_CONTEXT_LAMBDA_ELSE: return "LAMBDA_ELSE"; - case PM_CONTEXT_LAMBDA_RESCUE: return "LAMBDA_RESCUE"; - case PM_CONTEXT_MAIN: return "MAIN"; - case PM_CONTEXT_MODULE: return "MODULE"; - case PM_CONTEXT_MODULE_ELSE: return "MODULE_ELSE"; - case PM_CONTEXT_MODULE_ENSURE: return "MODULE_ENSURE"; - case PM_CONTEXT_MODULE_RESCUE: return "MODULE_RESCUE"; - case PM_CONTEXT_NONE: return "NONE"; - case PM_CONTEXT_PARENS: return "PARENS"; - case PM_CONTEXT_POSTEXE: return "POSTEXE"; - case PM_CONTEXT_PREDICATE: return "PREDICATE"; - case PM_CONTEXT_PREEXE: return "PREEXE"; - case PM_CONTEXT_RESCUE_MODIFIER: return "RESCUE_MODIFIER"; - case PM_CONTEXT_SCLASS: return "SCLASS"; - case PM_CONTEXT_SCLASS_ENSURE: return "SCLASS_ENSURE"; - case PM_CONTEXT_SCLASS_ELSE: return "SCLASS_ELSE"; - case PM_CONTEXT_SCLASS_RESCUE: return "SCLASS_RESCUE"; - case PM_CONTEXT_TERNARY: return "TERNARY"; - case PM_CONTEXT_UNLESS: return "UNLESS"; - case PM_CONTEXT_UNTIL: return "UNTIL"; - case PM_CONTEXT_WHILE: return "WHILE"; - } - return NULL; -} - -PRISM_ATTRIBUTE_UNUSED static void -debug_contexts(pm_parser_t *parser) { - pm_context_node_t *context_node = parser->current_context; - fprintf(stderr, "CONTEXTS: "); - - if (context_node != NULL) { - while (context_node != NULL) { - fprintf(stderr, "%s", debug_context(context_node->context)); - context_node = context_node->prev; - if (context_node != NULL) { - fprintf(stderr, " <- "); - } - } - } else { - fprintf(stderr, "NONE"); - } - - fprintf(stderr, "\n"); -} - -PRISM_ATTRIBUTE_UNUSED static void -debug_node(const pm_parser_t *parser, const pm_node_t *node) { - pm_buffer_t output_buffer = { 0 }; - pm_prettyprint(&output_buffer, parser, node); - - fprintf(stderr, "%.*s", (int) output_buffer.length, output_buffer.value); - pm_buffer_free(&output_buffer); -} - -PRISM_ATTRIBUTE_UNUSED static void -debug_lex_mode(pm_parser_t *parser) { - pm_lex_mode_t *lex_mode = parser->lex_modes.current; - bool first = true; - - while (lex_mode != NULL) { - if (first) { - first = false; - } else { - fprintf(stderr, " <- "); - } - - switch (lex_mode->mode) { - case PM_LEX_DEFAULT: fprintf(stderr, "DEFAULT"); break; - case PM_LEX_EMBEXPR: fprintf(stderr, "EMBEXPR"); break; - case PM_LEX_EMBVAR: fprintf(stderr, "EMBVAR"); break; - case PM_LEX_HEREDOC: fprintf(stderr, "HEREDOC"); break; - case PM_LEX_LIST: fprintf(stderr, "LIST (terminator=%c, interpolation=%d)", lex_mode->as.list.terminator, lex_mode->as.list.interpolation); break; - case PM_LEX_REGEXP: fprintf(stderr, "REGEXP (terminator=%c)", lex_mode->as.regexp.terminator); break; - case PM_LEX_STRING: fprintf(stderr, "STRING (terminator=%c, interpolation=%d)", lex_mode->as.string.terminator, lex_mode->as.string.interpolation); break; - } - - lex_mode = lex_mode->prev; - } - - fprintf(stderr, "\n"); -} - -PRISM_ATTRIBUTE_UNUSED static void -debug_state(pm_parser_t *parser) { - fprintf(stderr, "STATE: "); - bool first = true; - - if (parser->lex_state == PM_LEX_STATE_NONE) { - fprintf(stderr, "NONE\n"); - return; - } - -#define CHECK_STATE(state) \ - if (parser->lex_state & state) { \ - if (!first) fprintf(stderr, "|"); \ - fprintf(stderr, "%s", #state); \ - first = false; \ - } - - CHECK_STATE(PM_LEX_STATE_BEG) - CHECK_STATE(PM_LEX_STATE_END) - CHECK_STATE(PM_LEX_STATE_ENDARG) - CHECK_STATE(PM_LEX_STATE_ENDFN) - CHECK_STATE(PM_LEX_STATE_ARG) - CHECK_STATE(PM_LEX_STATE_CMDARG) - CHECK_STATE(PM_LEX_STATE_MID) - CHECK_STATE(PM_LEX_STATE_FNAME) - CHECK_STATE(PM_LEX_STATE_DOT) - CHECK_STATE(PM_LEX_STATE_CLASS) - CHECK_STATE(PM_LEX_STATE_LABEL) - CHECK_STATE(PM_LEX_STATE_LABELED) - CHECK_STATE(PM_LEX_STATE_FITEM) - -#undef CHECK_STATE - - fprintf(stderr, "\n"); -} - -PRISM_ATTRIBUTE_UNUSED static void -debug_token(pm_token_t * token) { - fprintf(stderr, "%s: \"%.*s\"\n", pm_token_type_human(token->type), (int) (token->end - token->start), token->start); -} - -#endif - // Macros for min/max. #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) @@ -342,6 +168,7 @@ lex_mode_push_regexp(pm_parser_t *parser, uint8_t incrementor, uint8_t terminato breakpoints[index++] = incrementor; } + parser->explicit_encoding = NULL; return lex_mode_push(parser, lex_mode); } @@ -423,7 +250,7 @@ lex_mode_pop(pm_parser_t *parser) { * This is the equivalent of IS_lex_state is CRuby. */ static inline bool -lex_state_p(pm_parser_t *parser, pm_lex_state_t state) { +lex_state_p(const pm_parser_t *parser, pm_lex_state_t state) { return parser->lex_state & state; } @@ -451,11 +278,6 @@ lex_state_beg_p(pm_parser_t *parser) { return lex_state_p(parser, PM_LEX_STATE_BEG_ANY) || ((parser->lex_state & (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED)) == (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED)); } -static inline bool -lex_state_arg_labeled_p(pm_parser_t *parser) { - return (parser->lex_state & (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED)) == (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED); -} - static inline bool lex_state_arg_p(pm_parser_t *parser) { return lex_state_p(parser, PM_LEX_STATE_ARG_ANY); @@ -491,8 +313,52 @@ lex_state_set(pm_parser_t *parser, pm_lex_state_t state) { parser->lex_state = state; } +#ifndef PM_DEBUG_LOGGING +/** + * Debugging logging will print additional information to stdout whenever the + * lexer state changes. + */ +#define PM_DEBUG_LOGGING 0 +#endif + #if PM_DEBUG_LOGGING -static inline void +PRISM_ATTRIBUTE_UNUSED static void +debug_state(pm_parser_t *parser) { + fprintf(stderr, "STATE: "); + bool first = true; + + if (parser->lex_state == PM_LEX_STATE_NONE) { + fprintf(stderr, "NONE\n"); + return; + } + +#define CHECK_STATE(state) \ + if (parser->lex_state & state) { \ + if (!first) fprintf(stderr, "|"); \ + fprintf(stderr, "%s", #state); \ + first = false; \ + } + + CHECK_STATE(PM_LEX_STATE_BEG) + CHECK_STATE(PM_LEX_STATE_END) + CHECK_STATE(PM_LEX_STATE_ENDARG) + CHECK_STATE(PM_LEX_STATE_ENDFN) + CHECK_STATE(PM_LEX_STATE_ARG) + CHECK_STATE(PM_LEX_STATE_CMDARG) + CHECK_STATE(PM_LEX_STATE_MID) + CHECK_STATE(PM_LEX_STATE_FNAME) + CHECK_STATE(PM_LEX_STATE_DOT) + CHECK_STATE(PM_LEX_STATE_CLASS) + CHECK_STATE(PM_LEX_STATE_LABEL) + CHECK_STATE(PM_LEX_STATE_LABELED) + CHECK_STATE(PM_LEX_STATE_FITEM) + +#undef CHECK_STATE + + fprintf(stderr, "\n"); +} + +static void debug_lex_state_set(pm_parser_t *parser, pm_lex_state_t state, char const * caller_name, int line_number) { fprintf(stderr, "Caller: %s:%d\nPrevious: ", caller_name, line_number); debug_state(parser); @@ -678,10 +544,7 @@ pm_parser_warn_node(pm_parser_t *parser, const pm_node_t *node, pm_diagnostic_id * token. */ static void -pm_parser_err_heredoc_term(pm_parser_t *parser, pm_lex_mode_t *lex_mode) { - const uint8_t *ident_start = lex_mode->as.heredoc.ident_start; - size_t ident_length = lex_mode->as.heredoc.ident_length; - +pm_parser_err_heredoc_term(pm_parser_t *parser, const uint8_t *ident_start, size_t ident_length) { PM_PARSER_ERR_FORMAT( parser, ident_start, @@ -708,8 +571,8 @@ pm_parser_scope_push(pm_parser_t *parser, bool closed) { .previous = parser->current_scope, .locals = { 0 }, .parameters = PM_SCOPE_PARAMETERS_NONE, - .numbered_parameters = PM_SCOPE_NUMBERED_PARAMETERS_NONE, - .shareable_constant = (closed || parser->current_scope == NULL) ? PM_SCOPE_SHAREABLE_CONSTANT_NONE : parser->current_scope->shareable_constant, + .implicit_parameters = { 0 }, + .shareable_constant = parser->current_scope == NULL ? PM_SCOPE_SHAREABLE_CONSTANT_NONE : parser->current_scope->shareable_constant, .closed = closed }; @@ -749,42 +612,97 @@ pm_parser_scope_find(pm_parser_t *parser, uint32_t depth) { return scope; } -static void -pm_parser_scope_forwarding_param_check(pm_parser_t *parser, const pm_token_t * token, const uint8_t mask, pm_diagnostic_id_t diag) { +typedef enum { + PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_PASS, + PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_CONFLICT, + PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_FAIL +} pm_scope_forwarding_param_check_result_t; + +static pm_scope_forwarding_param_check_result_t +pm_parser_scope_forwarding_param_check(pm_parser_t *parser, const uint8_t mask) { pm_scope_t *scope = parser->current_scope; - while (scope) { + bool conflict = false; + + while (scope != NULL) { if (scope->parameters & mask) { - if (!scope->closed) { - pm_parser_err_token(parser, token, diag); - return; + if (scope->closed) { + if (conflict) { + return PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_CONFLICT; + } else { + return PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_PASS; + } } - return; + + conflict = true; } + if (scope->closed) break; scope = scope->previous; } - pm_parser_err_token(parser, token, diag); + return PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_FAIL; } -static inline void +static void pm_parser_scope_forwarding_block_check(pm_parser_t *parser, const pm_token_t * token) { - pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_BLOCK, PM_ERR_ARGUMENT_NO_FORWARDING_AMP); + switch (pm_parser_scope_forwarding_param_check(parser, PM_SCOPE_PARAMETERS_FORWARDING_BLOCK)) { + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_PASS: + // Pass. + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_CONFLICT: + pm_parser_err_token(parser, token, PM_ERR_ARGUMENT_CONFLICT_AMPERSAND); + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_FAIL: + pm_parser_err_token(parser, token, PM_ERR_ARGUMENT_NO_FORWARDING_AMPERSAND); + break; + } } -static inline void +static void pm_parser_scope_forwarding_positionals_check(pm_parser_t *parser, const pm_token_t * token) { - pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS, PM_ERR_ARGUMENT_NO_FORWARDING_STAR); + switch (pm_parser_scope_forwarding_param_check(parser, PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS)) { + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_PASS: + // Pass. + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_CONFLICT: + pm_parser_err_token(parser, token, PM_ERR_ARGUMENT_CONFLICT_STAR); + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_FAIL: + pm_parser_err_token(parser, token, PM_ERR_ARGUMENT_NO_FORWARDING_STAR); + break; + } } -static inline void -pm_parser_scope_forwarding_all_check(pm_parser_t *parser, const pm_token_t * token) { - pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_ALL, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES); +static void +pm_parser_scope_forwarding_all_check(pm_parser_t *parser, const pm_token_t *token) { + switch (pm_parser_scope_forwarding_param_check(parser, PM_SCOPE_PARAMETERS_FORWARDING_ALL)) { + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_PASS: + // Pass. + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_CONFLICT: + // This shouldn't happen, because ... is not allowed in the + // declaration of blocks. If we get here, we assume we already have + // an error for this. + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_FAIL: + pm_parser_err_token(parser, token, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES); + break; + } } -static inline void +static void pm_parser_scope_forwarding_keywords_check(pm_parser_t *parser, const pm_token_t * token) { - pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS, PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR); + switch (pm_parser_scope_forwarding_param_check(parser, PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS)) { + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_PASS: + // Pass. + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_CONFLICT: + pm_parser_err_token(parser, token, PM_ERR_ARGUMENT_CONFLICT_STAR_STAR); + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_FAIL: + pm_parser_err_token(parser, token, PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR); + break; + } } /** @@ -1043,7 +961,7 @@ pm_locals_order(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, pm_locals_t *locals, if (local->name != PM_CONSTANT_ID_UNSET) { pm_constant_id_list_insert(list, (size_t) local->index, local->name); - if (warn_unused && local->reads == 0) { + if (warn_unused && local->reads == 0 && ((parser->start_line >= 0) || (pm_newline_list_line(&parser->newline_list, local->location.start, parser->start_line) >= 0))) { pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, local->name); if (constant->length >= 1 && *constant->start != '_') { @@ -1111,9 +1029,9 @@ pm_parser_optional_constant_id_token(pm_parser_t *parser, const pm_token_t *toke * If the node is value node, it returns NULL. * If not, it returns the pointer to the node to be inspected as "void expression". */ -static pm_node_t* -pm_check_value_expression(pm_node_t *node) { - pm_node_t* void_node = NULL; +static pm_node_t * +pm_check_value_expression(pm_parser_t *parser, pm_node_t *node) { + pm_node_t *void_node = NULL; while (node != NULL) { switch (PM_NODE_TYPE(node)) { @@ -1128,6 +1046,50 @@ pm_check_value_expression(pm_node_t *node) { return NULL; case PM_BEGIN_NODE: { pm_begin_node_t *cast = (pm_begin_node_t *) node; + + if (cast->ensure_clause != NULL) { + if (cast->rescue_clause != NULL) { + pm_node_t *vn = pm_check_value_expression(parser, (pm_node_t *) cast->rescue_clause); + if (vn != NULL) return vn; + } + + if (cast->statements != NULL) { + pm_node_t *vn = pm_check_value_expression(parser, (pm_node_t *) cast->statements); + if (vn != NULL) return vn; + } + + node = (pm_node_t *) cast->ensure_clause; + } else if (cast->rescue_clause != NULL) { + if (cast->statements == NULL) return NULL; + + pm_node_t *vn = pm_check_value_expression(parser, (pm_node_t *) cast->statements); + if (vn == NULL) return NULL; + if (void_node == NULL) void_node = vn; + + for (pm_rescue_node_t *rescue_clause = cast->rescue_clause; rescue_clause != NULL; rescue_clause = rescue_clause->subsequent) { + pm_node_t *vn = pm_check_value_expression(parser, (pm_node_t *) rescue_clause->statements); + if (vn == NULL) { + void_node = NULL; + break; + } + if (void_node == NULL) { + void_node = vn; + } + } + + if (cast->else_clause != NULL) { + node = (pm_node_t *) cast->else_clause; + } else { + return void_node; + } + } else { + node = (pm_node_t *) cast->statements; + } + + break; + } + case PM_ENSURE_NODE: { + pm_ensure_node_t *cast = (pm_ensure_node_t *) node; node = (pm_node_t *) cast->statements; break; } @@ -1143,32 +1105,32 @@ pm_check_value_expression(pm_node_t *node) { } case PM_IF_NODE: { pm_if_node_t *cast = (pm_if_node_t *) node; - if (cast->statements == NULL || cast->consequent == NULL) { + if (cast->statements == NULL || cast->subsequent == NULL) { return NULL; } - pm_node_t *vn = pm_check_value_expression((pm_node_t *) cast->statements); + pm_node_t *vn = pm_check_value_expression(parser, (pm_node_t *) cast->statements); if (vn == NULL) { return NULL; } if (void_node == NULL) { void_node = vn; } - node = cast->consequent; + node = cast->subsequent; break; } case PM_UNLESS_NODE: { pm_unless_node_t *cast = (pm_unless_node_t *) node; - if (cast->statements == NULL || cast->consequent == NULL) { + if (cast->statements == NULL || cast->else_clause == NULL) { return NULL; } - pm_node_t *vn = pm_check_value_expression((pm_node_t *) cast->statements); + pm_node_t *vn = pm_check_value_expression(parser, (pm_node_t *) cast->statements); if (vn == NULL) { return NULL; } if (void_node == NULL) { void_node = vn; } - node = (pm_node_t *) cast->consequent; + node = (pm_node_t *) cast->else_clause; break; } case PM_ELSE_NODE: { @@ -1186,6 +1148,15 @@ pm_check_value_expression(pm_node_t *node) { node = cast->left; break; } + case PM_LOCAL_VARIABLE_WRITE_NODE: { + pm_local_variable_write_node_t *cast = (pm_local_variable_write_node_t *) node; + + pm_scope_t *scope = parser->current_scope; + for (uint32_t depth = 0; depth < cast->depth; depth++) scope = scope->previous; + + pm_locals_read(&scope->locals, cast->name); + return NULL; + } default: return NULL; } @@ -1196,7 +1167,7 @@ pm_check_value_expression(pm_node_t *node) { static inline void pm_assert_value_expression(pm_parser_t *parser, pm_node_t *node) { - pm_node_t *void_node = pm_check_value_expression(node); + pm_node_t *void_node = pm_check_value_expression(parser, node); if (void_node != NULL) { pm_parser_err_node(parser, void_node, PM_ERR_VOID_EXPRESSION); } @@ -1345,9 +1316,10 @@ pm_void_statement_check(pm_parser_t *parser, const pm_node_t *node) { * a "void" statement. */ static void -pm_void_statements_check(pm_parser_t *parser, const pm_statements_node_t *node) { +pm_void_statements_check(pm_parser_t *parser, const pm_statements_node_t *node, bool last_value) { assert(node->body.size > 0); - for (size_t index = 0; index < node->body.size - 1; index++) { + const size_t size = node->body.size - (last_value ? 1 : 0); + for (size_t index = 0; index < size; index++) { pm_void_statement_check(parser, node->body.nodes[index]); } } @@ -1388,13 +1360,25 @@ static bool pm_conditional_predicate_warn_write_literal_p(const pm_node_t *node) { switch (PM_NODE_TYPE(node)) { case PM_ARRAY_NODE: { + if (PM_NODE_FLAG_P(node, PM_NODE_FLAG_STATIC_LITERAL)) return true; + const pm_array_node_t *cast = (const pm_array_node_t *) node; - const pm_node_t *element; + for (size_t index = 0; index < cast->elements.size; index++) { + if (!pm_conditional_predicate_warn_write_literal_p(cast->elements.nodes[index])) return false; + } - PM_NODE_LIST_FOREACH(&cast->elements, index, element) { - if (!pm_conditional_predicate_warn_write_literal_p(element)) { - return false; - } + return true; + } + case PM_HASH_NODE: { + if (PM_NODE_FLAG_P(node, PM_NODE_FLAG_STATIC_LITERAL)) return true; + + const pm_hash_node_t *cast = (const pm_hash_node_t *) node; + for (size_t index = 0; index < cast->elements.size; index++) { + const pm_node_t *element = cast->elements.nodes[index]; + if (!PM_NODE_TYPE_P(element, PM_ASSOC_NODE)) return false; + + const pm_assoc_node_t *assoc = (const pm_assoc_node_t *) element; + if (!pm_conditional_predicate_warn_write_literal_p(assoc->key) || !pm_conditional_predicate_warn_write_literal_p(assoc->value)) return false; } return true; @@ -1575,7 +1559,7 @@ not_provided(pm_parser_t *parser) { return (pm_token_t) { .type = PM_TOKEN_NOT_PROVIDED, .start = parser->start, .end = parser->start }; } -#define PM_LOCATION_NULL_VALUE(parser) ((pm_location_t) { .start = parser->start, .end = parser->start }) +#define PM_LOCATION_NULL_VALUE(parser) ((pm_location_t) { .start = (parser)->start, .end = (parser)->start }) #define PM_LOCATION_TOKEN_VALUE(token) ((pm_location_t) { .start = (token)->start, .end = (token)->end }) #define PM_LOCATION_NODE_VALUE(node) ((pm_location_t) { .start = (node)->location.start, .end = (node)->location.end }) #define PM_LOCATION_NODE_BASE_VALUE(node) ((pm_location_t) { .start = (node)->base.location.start, .end = (node)->base.location.end }) @@ -1703,7 +1687,7 @@ char_is_identifier_utf8(const uint8_t *b, const uint8_t *end) { * it's important that it be as fast as possible. */ static inline size_t -char_is_identifier(pm_parser_t *parser, const uint8_t *b) { +char_is_identifier(const pm_parser_t *parser, const uint8_t *b) { if (parser->encoding_changed) { size_t width; if ((width = parser->encoding->alnum_char(b, parser->end - b)) != 0) { @@ -1915,7 +1899,7 @@ static pm_statements_node_t * pm_statements_node_create(pm_parser_t *parser); static void -pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node, pm_node_t *statement); +pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node, pm_node_t *statement, bool newline); static size_t pm_statements_node_body_length(pm_statements_node_t *node); @@ -1925,7 +1909,7 @@ pm_statements_node_body_length(pm_statements_node_t *node); * implement our own arena allocation. */ static inline void * -pm_alloc_node(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, size_t size) { +pm_node_alloc(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, size_t size) { void *memory = xcalloc(1, size); if (memory == NULL) { fprintf(stderr, "Failed to allocate %d bytes\n", (int) size); @@ -1934,15 +1918,22 @@ pm_alloc_node(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, size_t size) { return memory; } -#define PM_ALLOC_NODE(parser, type) (type *) pm_alloc_node(parser, sizeof(type)) +#define PM_NODE_ALLOC(parser, type) (type *) pm_node_alloc(parser, sizeof(type)) +#define PM_NODE_IDENTIFY(parser) (++parser->node_id) /** * Allocate a new MissingNode node. */ static pm_missing_node_t * pm_missing_node_create(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) { - pm_missing_node_t *node = PM_ALLOC_NODE(parser, pm_missing_node_t); - *node = (pm_missing_node_t) {{ .type = PM_MISSING_NODE, .location = { .start = start, .end = end } }}; + pm_missing_node_t *node = PM_NODE_ALLOC(parser, pm_missing_node_t); + + *node = (pm_missing_node_t) {{ + .type = PM_MISSING_NODE, + .node_id = PM_NODE_IDENTIFY(parser), + .location = { .start = start, .end = end } + }}; + return node; } @@ -1952,11 +1943,12 @@ pm_missing_node_create(pm_parser_t *parser, const uint8_t *start, const uint8_t static pm_alias_global_variable_node_t * pm_alias_global_variable_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *new_name, pm_node_t *old_name) { assert(keyword->type == PM_TOKEN_KEYWORD_ALIAS); - pm_alias_global_variable_node_t *node = PM_ALLOC_NODE(parser, pm_alias_global_variable_node_t); + pm_alias_global_variable_node_t *node = PM_NODE_ALLOC(parser, pm_alias_global_variable_node_t); *node = (pm_alias_global_variable_node_t) { { .type = PM_ALIAS_GLOBAL_VARIABLE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = keyword->start, .end = old_name->location.end @@ -1976,11 +1968,12 @@ pm_alias_global_variable_node_create(pm_parser_t *parser, const pm_token_t *keyw static pm_alias_method_node_t * pm_alias_method_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *new_name, pm_node_t *old_name) { assert(keyword->type == PM_TOKEN_KEYWORD_ALIAS); - pm_alias_method_node_t *node = PM_ALLOC_NODE(parser, pm_alias_method_node_t); + pm_alias_method_node_t *node = PM_NODE_ALLOC(parser, pm_alias_method_node_t); *node = (pm_alias_method_node_t) { { .type = PM_ALIAS_METHOD_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = keyword->start, .end = old_name->location.end @@ -1999,11 +1992,12 @@ pm_alias_method_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_n */ static pm_alternation_pattern_node_t * pm_alternation_pattern_node_create(pm_parser_t *parser, pm_node_t *left, pm_node_t *right, const pm_token_t *operator) { - pm_alternation_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_alternation_pattern_node_t); + pm_alternation_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_alternation_pattern_node_t); *node = (pm_alternation_pattern_node_t) { { .type = PM_ALTERNATION_PATTERN_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = left->location.start, .end = right->location.end @@ -2024,11 +2018,12 @@ static pm_and_node_t * pm_and_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operator, pm_node_t *right) { pm_assert_value_expression(parser, left); - pm_and_node_t *node = PM_ALLOC_NODE(parser, pm_and_node_t); + pm_and_node_t *node = PM_NODE_ALLOC(parser, pm_and_node_t); *node = (pm_and_node_t) { { .type = PM_AND_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = left->location.start, .end = right->location.end @@ -2047,11 +2042,12 @@ pm_and_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *opera */ static pm_arguments_node_t * pm_arguments_node_create(pm_parser_t *parser) { - pm_arguments_node_t *node = PM_ALLOC_NODE(parser, pm_arguments_node_t); + pm_arguments_node_t *node = PM_NODE_ALLOC(parser, pm_arguments_node_t); *node = (pm_arguments_node_t) { { .type = PM_ARGUMENTS_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_NULL_VALUE(parser) }, .arguments = { 0 } @@ -2079,6 +2075,14 @@ pm_arguments_node_arguments_append(pm_arguments_node_t *node, pm_node_t *argumen node->base.location.end = argument->location.end; pm_node_list_append(&node->arguments, argument); + + if (PM_NODE_TYPE_P(argument, PM_SPLAT_NODE)) { + if (PM_NODE_FLAG_P(node, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT)) { + pm_node_flag_set((pm_node_t *) node, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_MULTIPLE_SPLATS); + } else { + pm_node_flag_set((pm_node_t *) node, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT); + } + } } /** @@ -2086,12 +2090,13 @@ pm_arguments_node_arguments_append(pm_arguments_node_t *node, pm_node_t *argumen */ static pm_array_node_t * pm_array_node_create(pm_parser_t *parser, const pm_token_t *opening) { - pm_array_node_t *node = PM_ALLOC_NODE(parser, pm_array_node_t); + pm_array_node_t *node = PM_NODE_ALLOC(parser, pm_array_node_t); *node = (pm_array_node_t) { { .type = PM_ARRAY_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(opening) }, .opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening), @@ -2102,14 +2107,6 @@ pm_array_node_create(pm_parser_t *parser, const pm_token_t *opening) { return node; } -/** - * Return the size of the given array node. - */ -static inline size_t -pm_array_node_size(pm_array_node_t *node) { - return node->elements.size; -} - /** * Append an argument to an array node. */ @@ -2149,11 +2146,12 @@ pm_array_node_close_set(pm_array_node_t *node, const pm_token_t *closing) { */ static pm_array_pattern_node_t * pm_array_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *nodes) { - pm_array_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_array_pattern_node_t); + pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t); *node = (pm_array_pattern_node_t) { { .type = PM_ARRAY_PATTERN_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = nodes->nodes[0]->location.start, .end = nodes->nodes[nodes->size - 1]->location.end @@ -2191,11 +2189,12 @@ pm_array_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *node */ static pm_array_pattern_node_t * pm_array_pattern_node_rest_create(pm_parser_t *parser, pm_node_t *rest) { - pm_array_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_array_pattern_node_t); + pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t); *node = (pm_array_pattern_node_t) { { .type = PM_ARRAY_PATTERN_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = rest->location, }, .constant = NULL, @@ -2215,11 +2214,12 @@ pm_array_pattern_node_rest_create(pm_parser_t *parser, pm_node_t *rest) { */ static pm_array_pattern_node_t * pm_array_pattern_node_constant_create(pm_parser_t *parser, pm_node_t *constant, const pm_token_t *opening, const pm_token_t *closing) { - pm_array_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_array_pattern_node_t); + pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t); *node = (pm_array_pattern_node_t) { { .type = PM_ARRAY_PATTERN_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = constant->location.start, .end = closing->end @@ -2242,11 +2242,12 @@ pm_array_pattern_node_constant_create(pm_parser_t *parser, pm_node_t *constant, */ static pm_array_pattern_node_t * pm_array_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) { - pm_array_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_array_pattern_node_t); + pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t); *node = (pm_array_pattern_node_t) { { .type = PM_ARRAY_PATTERN_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = opening->start, .end = closing->end @@ -2273,7 +2274,7 @@ pm_array_pattern_node_requireds_append(pm_array_pattern_node_t *node, pm_node_t */ static pm_assoc_node_t * pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *operator, pm_node_t *value) { - pm_assoc_node_t *node = PM_ALLOC_NODE(parser, pm_assoc_node_t); + pm_assoc_node_t *node = PM_NODE_ALLOC(parser, pm_assoc_node_t); const uint8_t *end; if (value != NULL && value->location.end > key->location.end) { @@ -2294,7 +2295,10 @@ pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *oper // If the key and value of this assoc node are both static literals, then // we can mark this node as a static literal. pm_node_flags_t flags = 0; - if (value && !PM_NODE_TYPE_P(value, PM_ARRAY_NODE) && !PM_NODE_TYPE_P(value, PM_HASH_NODE) && !PM_NODE_TYPE_P(value, PM_RANGE_NODE)) { + if ( + !PM_NODE_TYPE_P(key, PM_ARRAY_NODE) && !PM_NODE_TYPE_P(key, PM_HASH_NODE) && !PM_NODE_TYPE_P(key, PM_RANGE_NODE) && + value && !PM_NODE_TYPE_P(value, PM_ARRAY_NODE) && !PM_NODE_TYPE_P(value, PM_HASH_NODE) && !PM_NODE_TYPE_P(value, PM_RANGE_NODE) + ) { flags = key->flags & value->flags & PM_NODE_FLAG_STATIC_LITERAL; } @@ -2302,6 +2306,7 @@ pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *oper { .type = PM_ASSOC_NODE, .flags = flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = key->location.start, .end = end @@ -2321,11 +2326,12 @@ pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *oper static pm_assoc_splat_node_t * pm_assoc_splat_node_create(pm_parser_t *parser, pm_node_t *value, const pm_token_t *operator) { assert(operator->type == PM_TOKEN_USTAR_STAR); - pm_assoc_splat_node_t *node = PM_ALLOC_NODE(parser, pm_assoc_splat_node_t); + pm_assoc_splat_node_t *node = PM_NODE_ALLOC(parser, pm_assoc_splat_node_t); *node = (pm_assoc_splat_node_t) { { .type = PM_ASSOC_SPLAT_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = operator->start, .end = value == NULL ? operator->end : value->location.end @@ -2344,11 +2350,12 @@ pm_assoc_splat_node_create(pm_parser_t *parser, pm_node_t *value, const pm_token static pm_back_reference_read_node_t * pm_back_reference_read_node_create(pm_parser_t *parser, const pm_token_t *name) { assert(name->type == PM_TOKEN_BACK_REFERENCE); - pm_back_reference_read_node_t *node = PM_ALLOC_NODE(parser, pm_back_reference_read_node_t); + pm_back_reference_read_node_t *node = PM_NODE_ALLOC(parser, pm_back_reference_read_node_t); *node = (pm_back_reference_read_node_t) { { .type = PM_BACK_REFERENCE_READ_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(name), }, .name = pm_parser_constant_id_token(parser, name) @@ -2362,11 +2369,12 @@ pm_back_reference_read_node_create(pm_parser_t *parser, const pm_token_t *name) */ static pm_begin_node_t * pm_begin_node_create(pm_parser_t *parser, const pm_token_t *begin_keyword, pm_statements_node_t *statements) { - pm_begin_node_t *node = PM_ALLOC_NODE(parser, pm_begin_node_t); + pm_begin_node_t *node = PM_NODE_ALLOC(parser, pm_begin_node_t); *node = (pm_begin_node_t) { { .type = PM_BEGIN_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = begin_keyword->start, .end = statements == NULL ? begin_keyword->end : statements->base.location.end @@ -2427,11 +2435,12 @@ pm_begin_node_end_keyword_set(pm_begin_node_t *node, const pm_token_t *end_keywo */ static pm_block_argument_node_t * pm_block_argument_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *expression) { - pm_block_argument_node_t *node = PM_ALLOC_NODE(parser, pm_block_argument_node_t); + pm_block_argument_node_t *node = PM_NODE_ALLOC(parser, pm_block_argument_node_t); *node = (pm_block_argument_node_t) { { .type = PM_BLOCK_ARGUMENT_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = operator->start, .end = expression == NULL ? operator->end : expression->location.end @@ -2449,11 +2458,12 @@ pm_block_argument_node_create(pm_parser_t *parser, const pm_token_t *operator, p */ static pm_block_node_t * pm_block_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *opening, pm_node_t *parameters, pm_node_t *body, const pm_token_t *closing) { - pm_block_node_t *node = PM_ALLOC_NODE(parser, pm_block_node_t); + pm_block_node_t *node = PM_NODE_ALLOC(parser, pm_block_node_t); *node = (pm_block_node_t) { { .type = PM_BLOCK_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = opening->start, .end = closing->end }, }, .locals = *locals, @@ -2472,11 +2482,12 @@ pm_block_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const p static pm_block_parameter_node_t * pm_block_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, const pm_token_t *operator) { assert(operator->type == PM_TOKEN_NOT_PROVIDED || operator->type == PM_TOKEN_UAMPERSAND || operator->type == PM_TOKEN_AMPERSAND); - pm_block_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_block_parameter_node_t); + pm_block_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_block_parameter_node_t); *node = (pm_block_parameter_node_t) { { .type = PM_BLOCK_PARAMETER_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = operator->start, .end = (name->type == PM_TOKEN_NOT_PROVIDED ? operator->end : name->end) @@ -2495,7 +2506,7 @@ pm_block_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, cons */ static pm_block_parameters_node_t * pm_block_parameters_node_create(pm_parser_t *parser, pm_parameters_node_t *parameters, const pm_token_t *opening) { - pm_block_parameters_node_t *node = PM_ALLOC_NODE(parser, pm_block_parameters_node_t); + pm_block_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_block_parameters_node_t); const uint8_t *start; if (opening->type != PM_TOKEN_NOT_PROVIDED) { @@ -2518,6 +2529,7 @@ pm_block_parameters_node_create(pm_parser_t *parser, pm_parameters_node_t *param *node = (pm_block_parameters_node_t) { { .type = PM_BLOCK_PARAMETERS_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = start, .end = end @@ -2548,11 +2560,12 @@ pm_block_parameters_node_closing_set(pm_block_parameters_node_t *node, const pm_ */ static pm_block_local_variable_node_t * pm_block_local_variable_node_create(pm_parser_t *parser, const pm_token_t *name) { - pm_block_local_variable_node_t *node = PM_ALLOC_NODE(parser, pm_block_local_variable_node_t); + pm_block_local_variable_node_t *node = PM_NODE_ALLOC(parser, pm_block_local_variable_node_t); *node = (pm_block_local_variable_node_t) { { .type = PM_BLOCK_LOCAL_VARIABLE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(name), }, .name = pm_parser_constant_id_token(parser, name) @@ -2578,11 +2591,12 @@ pm_block_parameters_node_append_local(pm_block_parameters_node_t *node, const pm static pm_break_node_t * pm_break_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_node_t *arguments) { assert(keyword->type == PM_TOKEN_KEYWORD_BREAK); - pm_break_node_t *node = PM_ALLOC_NODE(parser, pm_break_node_t); + pm_break_node_t *node = PM_NODE_ALLOC(parser, pm_break_node_t); *node = (pm_break_node_t) { { .type = PM_BREAK_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = keyword->start, .end = (arguments == NULL ? keyword->end : arguments->base.location.end) @@ -2598,8 +2612,10 @@ pm_break_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argument // There are certain flags that we want to use internally but don't want to // expose because they are not relevant beyond parsing. Therefore we'll define // them here and not define them in config.yml/a header file. -static const pm_node_flags_t PM_CALL_NODE_FLAGS_COMPARISON = 0x10; -static const pm_node_flags_t PM_CALL_NODE_FLAGS_INDEX = 0x20; +static const pm_node_flags_t PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY = 0x4; +static const pm_node_flags_t PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY = 0x40; +static const pm_node_flags_t PM_CALL_NODE_FLAGS_COMPARISON = 0x80; +static const pm_node_flags_t PM_CALL_NODE_FLAGS_INDEX = 0x100; /** * Allocate and initialize a new CallNode node. This sets everything to NULL or @@ -2608,12 +2624,13 @@ static const pm_node_flags_t PM_CALL_NODE_FLAGS_INDEX = 0x20; */ static pm_call_node_t * pm_call_node_create(pm_parser_t *parser, pm_node_flags_t flags) { - pm_call_node_t *node = PM_ALLOC_NODE(parser, pm_call_node_t); + pm_call_node_t *node = PM_NODE_ALLOC(parser, pm_call_node_t); *node = (pm_call_node_t) { { .type = PM_CALL_NODE, .flags = flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_NULL_VALUE(parser), }, .receiver = NULL, @@ -2772,8 +2789,7 @@ static pm_call_node_t * pm_call_node_fcall_synthesized_create(pm_parser_t *parser, pm_arguments_node_t *arguments, pm_constant_id_t name) { pm_call_node_t *node = pm_call_node_create(parser, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY); - node->base.location.start = parser->start; - node->base.location.end = parser->start; + node->base.location = PM_LOCATION_NULL_VALUE(parser); node->arguments = arguments; node->name = name; @@ -2913,12 +2929,13 @@ static pm_call_and_write_node_t * pm_call_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(target->block == NULL); assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_call_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_call_and_write_node_t); + pm_call_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_call_and_write_node_t); *node = (pm_call_and_write_node_t) { { .type = PM_CALL_AND_WRITE_NODE, .flags = target->base.flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -2972,14 +2989,16 @@ pm_index_arguments_check(pm_parser_t *parser, const pm_arguments_node_t *argumen static pm_index_and_write_node_t * pm_index_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_index_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_index_and_write_node_t); + pm_index_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_index_and_write_node_t); pm_index_arguments_check(parser, target->arguments, target->block); + assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE)); *node = (pm_index_and_write_node_t) { { .type = PM_INDEX_AND_WRITE_NODE, .flags = target->base.flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -2990,7 +3009,7 @@ pm_index_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, cons .opening_loc = target->opening_loc, .arguments = target->arguments, .closing_loc = target->closing_loc, - .block = target->block, + .block = (pm_block_argument_node_t *) target->block, .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value }; @@ -3009,12 +3028,13 @@ pm_index_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, cons static pm_call_operator_write_node_t * pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(target->block == NULL); - pm_call_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_call_operator_write_node_t); + pm_call_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_call_operator_write_node_t); *node = (pm_call_operator_write_node_t) { { .type = PM_CALL_OPERATOR_WRITE_NODE, .flags = target->base.flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -3025,8 +3045,8 @@ pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, .message_loc = target->message_loc, .read_name = 0, .write_name = target->name, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1), - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value }; @@ -3045,14 +3065,16 @@ pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, */ static pm_index_operator_write_node_t * pm_index_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_index_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_index_operator_write_node_t); + pm_index_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_index_operator_write_node_t); pm_index_arguments_check(parser, target->arguments, target->block); + assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE)); *node = (pm_index_operator_write_node_t) { { .type = PM_INDEX_OPERATOR_WRITE_NODE, .flags = target->base.flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -3063,9 +3085,9 @@ pm_index_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, .opening_loc = target->opening_loc, .arguments = target->arguments, .closing_loc = target->closing_loc, - .block = target->block, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1), - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .block = (pm_block_argument_node_t *) target->block, + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value }; @@ -3084,12 +3106,13 @@ static pm_call_or_write_node_t * pm_call_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(target->block == NULL); assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_call_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_call_or_write_node_t); + pm_call_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_call_or_write_node_t); *node = (pm_call_or_write_node_t) { { .type = PM_CALL_OR_WRITE_NODE, .flags = target->base.flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -3120,14 +3143,16 @@ pm_call_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const static pm_index_or_write_node_t * pm_index_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_index_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_index_or_write_node_t); + pm_index_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_index_or_write_node_t); pm_index_arguments_check(parser, target->arguments, target->block); + assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE)); *node = (pm_index_or_write_node_t) { { .type = PM_INDEX_OR_WRITE_NODE, .flags = target->base.flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -3138,7 +3163,7 @@ pm_index_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const .opening_loc = target->opening_loc, .arguments = target->arguments, .closing_loc = target->closing_loc, - .block = target->block, + .block = (pm_block_argument_node_t *) target->block, .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value }; @@ -3157,12 +3182,13 @@ pm_index_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const */ static pm_call_target_node_t * pm_call_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { - pm_call_target_node_t *node = PM_ALLOC_NODE(parser, pm_call_target_node_t); + pm_call_target_node_t *node = PM_NODE_ALLOC(parser, pm_call_target_node_t); *node = (pm_call_target_node_t) { { .type = PM_CALL_TARGET_NODE, .flags = target->base.flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = target->base.location }, .receiver = target->receiver, @@ -3185,22 +3211,24 @@ pm_call_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { */ static pm_index_target_node_t * pm_index_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { - pm_index_target_node_t *node = PM_ALLOC_NODE(parser, pm_index_target_node_t); + pm_index_target_node_t *node = PM_NODE_ALLOC(parser, pm_index_target_node_t); pm_node_flags_t flags = target->base.flags; pm_index_arguments_check(parser, target->arguments, target->block); + assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE)); *node = (pm_index_target_node_t) { { .type = PM_INDEX_TARGET_NODE, .flags = flags | PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE, + .node_id = PM_NODE_IDENTIFY(parser), .location = target->base.location }, .receiver = target->receiver, .opening_loc = target->opening_loc, .arguments = target->arguments, .closing_loc = target->closing_loc, - .block = target->block + .block = (pm_block_argument_node_t *) target->block, }; // Here we're going to free the target, since it is no longer necessary. @@ -3215,15 +3243,16 @@ pm_index_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { * Allocate and initialize a new CapturePatternNode node. */ static pm_capture_pattern_node_t * -pm_capture_pattern_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t *target, const pm_token_t *operator) { - pm_capture_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_capture_pattern_node_t); +pm_capture_pattern_node_create(pm_parser_t *parser, pm_node_t *value, pm_local_variable_target_node_t *target, const pm_token_t *operator) { + pm_capture_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_capture_pattern_node_t); *node = (pm_capture_pattern_node_t) { { .type = PM_CAPTURE_PATTERN_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = value->location.start, - .end = target->location.end + .end = target->base.location.end }, }, .value = value, @@ -3239,18 +3268,19 @@ pm_capture_pattern_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t */ static pm_case_node_t * pm_case_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, pm_node_t *predicate, const pm_token_t *end_keyword) { - pm_case_node_t *node = PM_ALLOC_NODE(parser, pm_case_node_t); + pm_case_node_t *node = PM_NODE_ALLOC(parser, pm_case_node_t); *node = (pm_case_node_t) { { .type = PM_CASE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = case_keyword->start, .end = end_keyword->end }, }, .predicate = predicate, - .consequent = NULL, + .else_clause = NULL, .case_keyword_loc = PM_LOCATION_TOKEN_VALUE(case_keyword), .end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword), .conditions = { 0 } @@ -3271,12 +3301,12 @@ pm_case_node_condition_append(pm_case_node_t *node, pm_node_t *condition) { } /** - * Set the consequent of a CaseNode node. + * Set the else clause of a CaseNode node. */ static void -pm_case_node_consequent_set(pm_case_node_t *node, pm_else_node_t *consequent) { - node->consequent = consequent; - node->base.location.end = consequent->base.location.end; +pm_case_node_else_clause_set(pm_case_node_t *node, pm_else_node_t *else_clause) { + node->else_clause = else_clause; + node->base.location.end = else_clause->base.location.end; } /** @@ -3293,18 +3323,19 @@ pm_case_node_end_keyword_loc_set(pm_case_node_t *node, const pm_token_t *end_key */ static pm_case_match_node_t * pm_case_match_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, pm_node_t *predicate, const pm_token_t *end_keyword) { - pm_case_match_node_t *node = PM_ALLOC_NODE(parser, pm_case_match_node_t); + pm_case_match_node_t *node = PM_NODE_ALLOC(parser, pm_case_match_node_t); *node = (pm_case_match_node_t) { { .type = PM_CASE_MATCH_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = case_keyword->start, .end = end_keyword->end }, }, .predicate = predicate, - .consequent = NULL, + .else_clause = NULL, .case_keyword_loc = PM_LOCATION_TOKEN_VALUE(case_keyword), .end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword), .conditions = { 0 } @@ -3325,12 +3356,12 @@ pm_case_match_node_condition_append(pm_case_match_node_t *node, pm_node_t *condi } /** - * Set the consequent of a CaseMatchNode node. + * Set the else clause of a CaseMatchNode node. */ static void -pm_case_match_node_consequent_set(pm_case_match_node_t *node, pm_else_node_t *consequent) { - node->consequent = consequent; - node->base.location.end = consequent->base.location.end; +pm_case_match_node_else_clause_set(pm_case_match_node_t *node, pm_else_node_t *else_clause) { + node->else_clause = else_clause; + node->base.location.end = else_clause->base.location.end; } /** @@ -3347,11 +3378,12 @@ pm_case_match_node_end_keyword_loc_set(pm_case_match_node_t *node, const pm_toke */ static pm_class_node_t * pm_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *class_keyword, pm_node_t *constant_path, const pm_token_t *name, const pm_token_t *inheritance_operator, pm_node_t *superclass, pm_node_t *body, const pm_token_t *end_keyword) { - pm_class_node_t *node = PM_ALLOC_NODE(parser, pm_class_node_t); + pm_class_node_t *node = PM_NODE_ALLOC(parser, pm_class_node_t); *node = (pm_class_node_t) { { .type = PM_CLASS_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = class_keyword->start, .end = end_keyword->end }, }, .locals = *locals, @@ -3373,11 +3405,12 @@ pm_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const p static pm_class_variable_and_write_node_t * pm_class_variable_and_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_class_variable_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_class_variable_and_write_node_t); + pm_class_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_and_write_node_t); *node = (pm_class_variable_and_write_node_t) { { .type = PM_CLASS_VARIABLE_AND_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -3397,11 +3430,12 @@ pm_class_variable_and_write_node_create(pm_parser_t *parser, pm_class_variable_r */ static pm_class_variable_operator_write_node_t * pm_class_variable_operator_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_class_variable_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_class_variable_operator_write_node_t); + pm_class_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_operator_write_node_t); *node = (pm_class_variable_operator_write_node_t) { { .type = PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -3409,9 +3443,9 @@ pm_class_variable_operator_write_node_create(pm_parser_t *parser, pm_class_varia }, .name = target->name, .name_loc = target->base.location, - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) }; return node; @@ -3423,11 +3457,12 @@ pm_class_variable_operator_write_node_create(pm_parser_t *parser, pm_class_varia static pm_class_variable_or_write_node_t * pm_class_variable_or_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_class_variable_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_class_variable_or_write_node_t); + pm_class_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_or_write_node_t); *node = (pm_class_variable_or_write_node_t) { { .type = PM_CLASS_VARIABLE_OR_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -3448,11 +3483,12 @@ pm_class_variable_or_write_node_create(pm_parser_t *parser, pm_class_variable_re static pm_class_variable_read_node_t * pm_class_variable_read_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_CLASS_VARIABLE); - pm_class_variable_read_node_t *node = PM_ALLOC_NODE(parser, pm_class_variable_read_node_t); + pm_class_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_read_node_t); *node = (pm_class_variable_read_node_t) { { .type = PM_CLASS_VARIABLE_READ_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }, .name = pm_parser_constant_id_token(parser, token) @@ -3461,16 +3497,32 @@ pm_class_variable_read_node_create(pm_parser_t *parser, const pm_token_t *token) return node; } +/** + * True if the given node is an implicit array node on a write, as in: + * + * a = *b + * a = 1, 2, 3 + */ +static inline pm_node_flags_t +pm_implicit_array_write_flags(const pm_node_t *node, pm_node_flags_t flags) { + if (PM_NODE_TYPE_P(node, PM_ARRAY_NODE) && ((const pm_array_node_t *) node)->opening_loc.start == NULL) { + return flags; + } + return 0; +} + /** * Initialize a new ClassVariableWriteNode node from a ClassVariableRead node. */ static pm_class_variable_write_node_t * pm_class_variable_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *read_node, pm_token_t *operator, pm_node_t *value) { - pm_class_variable_write_node_t *node = PM_ALLOC_NODE(parser, pm_class_variable_write_node_t); + pm_class_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_write_node_t); *node = (pm_class_variable_write_node_t) { { .type = PM_CLASS_VARIABLE_WRITE_NODE, + .flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = read_node->base.location.start, .end = value->location.end @@ -3491,11 +3543,12 @@ pm_class_variable_write_node_create(pm_parser_t *parser, pm_class_variable_read_ static pm_constant_path_and_write_node_t * pm_constant_path_and_write_node_create(pm_parser_t *parser, pm_constant_path_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_constant_path_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_path_and_write_node_t); + pm_constant_path_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_and_write_node_t); *node = (pm_constant_path_and_write_node_t) { { .type = PM_CONSTANT_PATH_AND_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -3514,20 +3567,21 @@ pm_constant_path_and_write_node_create(pm_parser_t *parser, pm_constant_path_nod */ static pm_constant_path_operator_write_node_t * pm_constant_path_operator_write_node_create(pm_parser_t *parser, pm_constant_path_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_constant_path_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_path_operator_write_node_t); + pm_constant_path_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_operator_write_node_t); *node = (pm_constant_path_operator_write_node_t) { { .type = PM_CONSTANT_PATH_OPERATOR_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end } }, .target = target, - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) }; return node; @@ -3539,11 +3593,12 @@ pm_constant_path_operator_write_node_create(pm_parser_t *parser, pm_constant_pat static pm_constant_path_or_write_node_t * pm_constant_path_or_write_node_create(pm_parser_t *parser, pm_constant_path_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_constant_path_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_path_or_write_node_t); + pm_constant_path_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_or_write_node_t); *node = (pm_constant_path_or_write_node_t) { { .type = PM_CONSTANT_PATH_OR_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -3563,7 +3618,7 @@ pm_constant_path_or_write_node_create(pm_parser_t *parser, pm_constant_path_node static pm_constant_path_node_t * pm_constant_path_node_create(pm_parser_t *parser, pm_node_t *parent, const pm_token_t *delimiter, const pm_token_t *name_token) { pm_assert_value_expression(parser, parent); - pm_constant_path_node_t *node = PM_ALLOC_NODE(parser, pm_constant_path_node_t); + pm_constant_path_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_node_t); pm_constant_id_t name = PM_CONSTANT_ID_UNSET; if (name_token->type == PM_TOKEN_CONSTANT) { @@ -3573,6 +3628,7 @@ pm_constant_path_node_create(pm_parser_t *parser, pm_node_t *parent, const pm_to *node = (pm_constant_path_node_t) { { .type = PM_CONSTANT_PATH_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = parent == NULL ? delimiter->start : parent->location.start, .end = name_token->end @@ -3592,11 +3648,13 @@ pm_constant_path_node_create(pm_parser_t *parser, pm_node_t *parent, const pm_to */ static pm_constant_path_write_node_t * pm_constant_path_write_node_create(pm_parser_t *parser, pm_constant_path_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_constant_path_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_path_write_node_t); + pm_constant_path_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_write_node_t); *node = (pm_constant_path_write_node_t) { { .type = PM_CONSTANT_PATH_WRITE_NODE, + .flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -3616,11 +3674,12 @@ pm_constant_path_write_node_create(pm_parser_t *parser, pm_constant_path_node_t static pm_constant_and_write_node_t * pm_constant_and_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_constant_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_and_write_node_t); + pm_constant_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_and_write_node_t); *node = (pm_constant_and_write_node_t) { { .type = PM_CONSTANT_AND_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -3640,11 +3699,12 @@ pm_constant_and_write_node_create(pm_parser_t *parser, pm_constant_read_node_t * */ static pm_constant_operator_write_node_t * pm_constant_operator_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_constant_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_operator_write_node_t); + pm_constant_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_operator_write_node_t); *node = (pm_constant_operator_write_node_t) { { .type = PM_CONSTANT_OPERATOR_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -3652,9 +3712,9 @@ pm_constant_operator_write_node_create(pm_parser_t *parser, pm_constant_read_nod }, .name = target->name, .name_loc = target->base.location, - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) }; return node; @@ -3666,11 +3726,12 @@ pm_constant_operator_write_node_create(pm_parser_t *parser, pm_constant_read_nod static pm_constant_or_write_node_t * pm_constant_or_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_constant_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_or_write_node_t); + pm_constant_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_or_write_node_t); *node = (pm_constant_or_write_node_t) { { .type = PM_CONSTANT_OR_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -3691,11 +3752,12 @@ pm_constant_or_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *t static pm_constant_read_node_t * pm_constant_read_node_create(pm_parser_t *parser, const pm_token_t *name) { assert(name->type == PM_TOKEN_CONSTANT || name->type == PM_TOKEN_MISSING); - pm_constant_read_node_t *node = PM_ALLOC_NODE(parser, pm_constant_read_node_t); + pm_constant_read_node_t *node = PM_NODE_ALLOC(parser, pm_constant_read_node_t); *node = (pm_constant_read_node_t) { { .type = PM_CONSTANT_READ_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(name) }, .name = pm_parser_constant_id_token(parser, name) @@ -3709,11 +3771,13 @@ pm_constant_read_node_create(pm_parser_t *parser, const pm_token_t *name) { */ static pm_constant_write_node_t * pm_constant_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_constant_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_write_node_t); + pm_constant_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_write_node_t); *node = (pm_constant_write_node_t) { { .type = PM_CONSTANT_WRITE_NODE, + .flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -3773,133 +3837,26 @@ pm_def_node_receiver_check(pm_parser_t *parser, const pm_node_t *node) { } /** - * When a method body is created, we want to check if the last statement is a - * return or a statement that houses a return. If it is, then we want to mark - * that return as being redundant so that we can compile it differently but also - * so that we can indicate that to the user. + * Allocate and initialize a new DefNode node. */ -static void -pm_def_node_body_redundant_return(pm_node_t *node) { - switch (PM_NODE_TYPE(node)) { - case PM_RETURN_NODE: - node->flags |= PM_RETURN_NODE_FLAGS_REDUNDANT; - break; - case PM_BEGIN_NODE: { - pm_begin_node_t *cast = (pm_begin_node_t *) node; - - if (cast->statements != NULL && cast->else_clause == NULL) { - pm_def_node_body_redundant_return((pm_node_t *) cast->statements); - } - break; - } - case PM_STATEMENTS_NODE: { - pm_statements_node_t *cast = (pm_statements_node_t *) node; - - if (cast->body.size > 0) { - pm_def_node_body_redundant_return(cast->body.nodes[cast->body.size - 1]); - } - break; - } - case PM_IF_NODE: { - pm_if_node_t *cast = (pm_if_node_t *) node; - - if (cast->statements != NULL) { - pm_def_node_body_redundant_return((pm_node_t *) cast->statements); - } - - if (cast->consequent != NULL) { - pm_def_node_body_redundant_return(cast->consequent); - } - break; - } - case PM_UNLESS_NODE: { - pm_unless_node_t *cast = (pm_unless_node_t *) node; - - if (cast->statements != NULL) { - pm_def_node_body_redundant_return((pm_node_t *) cast->statements); - } - - if (cast->consequent != NULL) { - pm_def_node_body_redundant_return((pm_node_t *) cast->consequent); - } - break; - } - case PM_ELSE_NODE: { - pm_else_node_t *cast = (pm_else_node_t *) node; - - if (cast->statements != NULL) { - pm_def_node_body_redundant_return((pm_node_t *) cast->statements); - } - break; - } - case PM_CASE_NODE: { - pm_case_node_t *cast = (pm_case_node_t *) node; - pm_node_t *condition; - - PM_NODE_LIST_FOREACH(&cast->conditions, index, condition) { - pm_def_node_body_redundant_return(condition); - } - - if (cast->consequent != NULL) { - pm_def_node_body_redundant_return((pm_node_t *) cast->consequent); - } - break; - } - case PM_WHEN_NODE: { - pm_when_node_t *cast = (pm_when_node_t *) node; - - if (cast->statements != NULL) { - pm_def_node_body_redundant_return((pm_node_t *) cast->statements); - } - break; - } - case PM_CASE_MATCH_NODE: { - pm_case_match_node_t *cast = (pm_case_match_node_t *) node; - pm_node_t *condition; - - PM_NODE_LIST_FOREACH(&cast->conditions, index, condition) { - pm_def_node_body_redundant_return(condition); - } - - if (cast->consequent != NULL) { - pm_def_node_body_redundant_return((pm_node_t *) cast->consequent); - } - break; - } - case PM_IN_NODE: { - pm_in_node_t *cast = (pm_in_node_t *) node; - - if (cast->statements != NULL) { - pm_def_node_body_redundant_return((pm_node_t *) cast->statements); - } - break; - } - default: - break; - } -} - -/** - * Allocate and initialize a new DefNode node. - */ -static pm_def_node_t * -pm_def_node_create( - pm_parser_t *parser, - pm_constant_id_t name, - const pm_token_t *name_loc, - pm_node_t *receiver, - pm_parameters_node_t *parameters, - pm_node_t *body, - pm_constant_id_list_t *locals, - const pm_token_t *def_keyword, - const pm_token_t *operator, - const pm_token_t *lparen, - const pm_token_t *rparen, - const pm_token_t *equal, - const pm_token_t *end_keyword -) { - pm_def_node_t *node = PM_ALLOC_NODE(parser, pm_def_node_t); - const uint8_t *end; +static pm_def_node_t * +pm_def_node_create( + pm_parser_t *parser, + pm_constant_id_t name, + const pm_token_t *name_loc, + pm_node_t *receiver, + pm_parameters_node_t *parameters, + pm_node_t *body, + pm_constant_id_list_t *locals, + const pm_token_t *def_keyword, + const pm_token_t *operator, + const pm_token_t *lparen, + const pm_token_t *rparen, + const pm_token_t *equal, + const pm_token_t *end_keyword +) { + pm_def_node_t *node = PM_NODE_ALLOC(parser, pm_def_node_t); + const uint8_t *end; if (end_keyword->type == PM_TOKEN_NOT_PROVIDED) { end = body->location.end; @@ -3911,13 +3868,10 @@ pm_def_node_create( pm_def_node_receiver_check(parser, receiver); } - if (body != NULL) { - pm_def_node_body_redundant_return(body); - } - *node = (pm_def_node_t) { { .type = PM_DEF_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = def_keyword->start, .end = end }, }, .name = name, @@ -3942,11 +3896,12 @@ pm_def_node_create( */ static pm_defined_node_t * pm_defined_node_create(pm_parser_t *parser, const pm_token_t *lparen, pm_node_t *value, const pm_token_t *rparen, const pm_location_t *keyword_loc) { - pm_defined_node_t *node = PM_ALLOC_NODE(parser, pm_defined_node_t); + pm_defined_node_t *node = PM_NODE_ALLOC(parser, pm_defined_node_t); *node = (pm_defined_node_t) { { .type = PM_DEFINED_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = keyword_loc->start, .end = (rparen->type == PM_TOKEN_NOT_PROVIDED ? value->location.end : rparen->end) @@ -3966,7 +3921,7 @@ pm_defined_node_create(pm_parser_t *parser, const pm_token_t *lparen, pm_node_t */ static pm_else_node_t * pm_else_node_create(pm_parser_t *parser, const pm_token_t *else_keyword, pm_statements_node_t *statements, const pm_token_t *end_keyword) { - pm_else_node_t *node = PM_ALLOC_NODE(parser, pm_else_node_t); + pm_else_node_t *node = PM_NODE_ALLOC(parser, pm_else_node_t); const uint8_t *end = NULL; if ((end_keyword->type == PM_TOKEN_NOT_PROVIDED) && (statements != NULL)) { end = statements->base.location.end; @@ -3977,6 +3932,7 @@ pm_else_node_create(pm_parser_t *parser, const pm_token_t *else_keyword, pm_stat *node = (pm_else_node_t) { { .type = PM_ELSE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = else_keyword->start, .end = end, @@ -3995,11 +3951,12 @@ pm_else_node_create(pm_parser_t *parser, const pm_token_t *else_keyword, pm_stat */ static pm_embedded_statements_node_t * pm_embedded_statements_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_statements_node_t *statements, const pm_token_t *closing) { - pm_embedded_statements_node_t *node = PM_ALLOC_NODE(parser, pm_embedded_statements_node_t); + pm_embedded_statements_node_t *node = PM_NODE_ALLOC(parser, pm_embedded_statements_node_t); *node = (pm_embedded_statements_node_t) { { .type = PM_EMBEDDED_STATEMENTS_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = opening->start, .end = closing->end @@ -4018,11 +3975,12 @@ pm_embedded_statements_node_create(pm_parser_t *parser, const pm_token_t *openin */ static pm_embedded_variable_node_t * pm_embedded_variable_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *variable) { - pm_embedded_variable_node_t *node = PM_ALLOC_NODE(parser, pm_embedded_variable_node_t); + pm_embedded_variable_node_t *node = PM_NODE_ALLOC(parser, pm_embedded_variable_node_t); *node = (pm_embedded_variable_node_t) { { .type = PM_EMBEDDED_VARIABLE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = operator->start, .end = variable->location.end @@ -4040,11 +3998,12 @@ pm_embedded_variable_node_create(pm_parser_t *parser, const pm_token_t *operator */ static pm_ensure_node_t * pm_ensure_node_create(pm_parser_t *parser, const pm_token_t *ensure_keyword, pm_statements_node_t *statements, const pm_token_t *end_keyword) { - pm_ensure_node_t *node = PM_ALLOC_NODE(parser, pm_ensure_node_t); + pm_ensure_node_t *node = PM_NODE_ALLOC(parser, pm_ensure_node_t); *node = (pm_ensure_node_t) { { .type = PM_ENSURE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = ensure_keyword->start, .end = end_keyword->end @@ -4064,11 +4023,12 @@ pm_ensure_node_create(pm_parser_t *parser, const pm_token_t *ensure_keyword, pm_ static pm_false_node_t * pm_false_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD_FALSE); - pm_false_node_t *node = PM_ALLOC_NODE(parser, pm_false_node_t); + pm_false_node_t *node = PM_NODE_ALLOC(parser, pm_false_node_t); *node = (pm_false_node_t) {{ .type = PM_FALSE_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }}; @@ -4081,28 +4041,40 @@ pm_false_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_find_pattern_node_t * pm_find_pattern_node_create(pm_parser_t *parser, pm_node_list_t *nodes) { - pm_find_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_find_pattern_node_t); + pm_find_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_find_pattern_node_t); pm_node_t *left = nodes->nodes[0]; + assert(PM_NODE_TYPE_P(left, PM_SPLAT_NODE)); + pm_splat_node_t *left_splat_node = (pm_splat_node_t *) left; + pm_node_t *right; if (nodes->size == 1) { right = (pm_node_t *) pm_missing_node_create(parser, left->location.end, left->location.end); } else { right = nodes->nodes[nodes->size - 1]; + assert(PM_NODE_TYPE_P(right, PM_SPLAT_NODE)); } +#if PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS + // FindPatternNode#right is typed as SplatNode in this case, so replace the potential MissingNode with a SplatNode. + // The resulting AST will anyway be ignored, but this file still needs to compile. + pm_splat_node_t *right_splat_node = PM_NODE_TYPE_P(right, PM_SPLAT_NODE) ? (pm_splat_node_t *) right : left_splat_node; +#else + pm_node_t *right_splat_node = right; +#endif *node = (pm_find_pattern_node_t) { { .type = PM_FIND_PATTERN_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = left->location.start, .end = right->location.end, }, }, .constant = NULL, - .left = left, - .right = right, + .left = left_splat_node, + .right = right_splat_node, .requireds = { 0 }, .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE @@ -4197,12 +4169,13 @@ pm_double_parse(pm_parser_t *parser, const pm_token_t *token) { static pm_float_node_t * pm_float_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_FLOAT); - pm_float_node_t *node = PM_ALLOC_NODE(parser, pm_float_node_t); + pm_float_node_t *node = PM_NODE_ALLOC(parser, pm_float_node_t); *node = (pm_float_node_t) { { .type = PM_FLOAT_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }, .value = pm_double_parse(parser, token) @@ -4218,11 +4191,12 @@ static pm_imaginary_node_t * pm_float_node_imaginary_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_FLOAT_IMAGINARY); - pm_imaginary_node_t *node = PM_ALLOC_NODE(parser, pm_imaginary_node_t); + pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t); *node = (pm_imaginary_node_t) { { .type = PM_IMAGINARY_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }, .numeric = (pm_node_t *) pm_float_node_create(parser, &((pm_token_t) { @@ -4236,26 +4210,55 @@ pm_float_node_imaginary_create(pm_parser_t *parser, const pm_token_t *token) { } /** - * Allocate and initialize a new FloatNode node from a FLOAT_RATIONAL token. + * Allocate and initialize a new RationalNode node from a FLOAT_RATIONAL token. */ static pm_rational_node_t * pm_float_node_rational_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_FLOAT_RATIONAL); - pm_rational_node_t *node = PM_ALLOC_NODE(parser, pm_rational_node_t); + pm_rational_node_t *node = PM_NODE_ALLOC(parser, pm_rational_node_t); *node = (pm_rational_node_t) { { .type = PM_RATIONAL_NODE, - .flags = PM_NODE_FLAG_STATIC_LITERAL, + .flags = PM_INTEGER_BASE_FLAGS_DECIMAL | PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }, - .numeric = (pm_node_t *) pm_float_node_create(parser, &((pm_token_t) { - .type = PM_TOKEN_FLOAT, - .start = token->start, - .end = token->end - 1 - })) + .numerator = { 0 }, + .denominator = { 0 } }; + const uint8_t *start = token->start; + const uint8_t *end = token->end - 1; // r + + while (start < end && *start == '0') start++; // 0.1 -> .1 + while (end > start && end[-1] == '0') end--; // 1.0 -> 1. + + size_t length = (size_t) (end - start); + if (length == 1) { + node->denominator.value = 1; + return node; + } + + const uint8_t *point = memchr(start, '.', length); + assert(point && "should have a decimal point"); + + uint8_t *digits = malloc(length); + if (digits == NULL) { + fputs("[pm_float_node_rational_create] Failed to allocate memory", stderr); + abort(); + } + + memcpy(digits, start, (unsigned long) (point - start)); + memcpy(digits + (point - start), point + 1, (unsigned long) (end - point - 1)); + pm_integer_parse(&node->numerator, PM_INTEGER_BASE_DEFAULT, digits, digits + length - 1); + + digits[0] = '1'; + if (end - point > 1) memset(digits + 1, '0', (size_t) (end - point - 1)); + pm_integer_parse(&node->denominator, PM_INTEGER_BASE_DEFAULT, digits, digits + (end - point)); + free(digits); + + pm_integers_reduce(&node->numerator, &node->denominator); return node; } @@ -4267,11 +4270,12 @@ static pm_imaginary_node_t * pm_float_node_rational_imaginary_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_FLOAT_RATIONAL_IMAGINARY); - pm_imaginary_node_t *node = PM_ALLOC_NODE(parser, pm_imaginary_node_t); + pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t); *node = (pm_imaginary_node_t) { { .type = PM_IMAGINARY_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }, .numeric = (pm_node_t *) pm_float_node_rational_create(parser, &((pm_token_t) { @@ -4298,11 +4302,12 @@ pm_for_node_create( const pm_token_t *do_keyword, const pm_token_t *end_keyword ) { - pm_for_node_t *node = PM_ALLOC_NODE(parser, pm_for_node_t); + pm_for_node_t *node = PM_NODE_ALLOC(parser, pm_for_node_t); *node = (pm_for_node_t) { { .type = PM_FOR_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = for_keyword->start, .end = end_keyword->end @@ -4326,8 +4331,14 @@ pm_for_node_create( static pm_forwarding_arguments_node_t * pm_forwarding_arguments_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_UDOT_DOT_DOT); - pm_forwarding_arguments_node_t *node = PM_ALLOC_NODE(parser, pm_forwarding_arguments_node_t); - *node = (pm_forwarding_arguments_node_t) {{ .type = PM_FORWARDING_ARGUMENTS_NODE, .location = PM_LOCATION_TOKEN_VALUE(token) }}; + pm_forwarding_arguments_node_t *node = PM_NODE_ALLOC(parser, pm_forwarding_arguments_node_t); + + *node = (pm_forwarding_arguments_node_t) {{ + .type = PM_FORWARDING_ARGUMENTS_NODE, + .node_id = PM_NODE_IDENTIFY(parser), + .location = PM_LOCATION_TOKEN_VALUE(token) + }}; + return node; } @@ -4337,8 +4348,14 @@ pm_forwarding_arguments_node_create(pm_parser_t *parser, const pm_token_t *token static pm_forwarding_parameter_node_t * pm_forwarding_parameter_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_UDOT_DOT_DOT); - pm_forwarding_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_forwarding_parameter_node_t); - *node = (pm_forwarding_parameter_node_t) {{ .type = PM_FORWARDING_PARAMETER_NODE, .location = PM_LOCATION_TOKEN_VALUE(token) }}; + pm_forwarding_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_forwarding_parameter_node_t); + + *node = (pm_forwarding_parameter_node_t) {{ + .type = PM_FORWARDING_PARAMETER_NODE, + .node_id = PM_NODE_IDENTIFY(parser), + .location = PM_LOCATION_TOKEN_VALUE(token) + }}; + return node; } @@ -4349,7 +4366,7 @@ static pm_forwarding_super_node_t * pm_forwarding_super_node_create(pm_parser_t *parser, const pm_token_t *token, pm_arguments_t *arguments) { assert(arguments->block == NULL || PM_NODE_TYPE_P(arguments->block, PM_BLOCK_NODE)); assert(token->type == PM_TOKEN_KEYWORD_SUPER); - pm_forwarding_super_node_t *node = PM_ALLOC_NODE(parser, pm_forwarding_super_node_t); + pm_forwarding_super_node_t *node = PM_NODE_ALLOC(parser, pm_forwarding_super_node_t); pm_block_node_t *block = NULL; if (arguments->block != NULL) { @@ -4359,6 +4376,7 @@ pm_forwarding_super_node_create(pm_parser_t *parser, const pm_token_t *token, pm *node = (pm_forwarding_super_node_t) { { .type = PM_FORWARDING_SUPER_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = token->start, .end = block != NULL ? block->base.location.end : token->end @@ -4376,11 +4394,12 @@ pm_forwarding_super_node_create(pm_parser_t *parser, const pm_token_t *token, pm */ static pm_hash_pattern_node_t * pm_hash_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) { - pm_hash_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_hash_pattern_node_t); + pm_hash_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_hash_pattern_node_t); *node = (pm_hash_pattern_node_t) { { .type = PM_HASH_PATTERN_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = opening->start, .end = closing->end @@ -4401,7 +4420,7 @@ pm_hash_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *opening */ static pm_hash_pattern_node_t * pm_hash_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *elements, pm_node_t *rest) { - pm_hash_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_hash_pattern_node_t); + pm_hash_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_hash_pattern_node_t); const uint8_t *start; const uint8_t *end; @@ -4423,6 +4442,7 @@ pm_hash_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *eleme *node = (pm_hash_pattern_node_t) { { .type = PM_HASH_PATTERN_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = start, .end = end @@ -4469,11 +4489,12 @@ pm_global_variable_write_name(pm_parser_t *parser, const pm_node_t *target) { static pm_global_variable_and_write_node_t * pm_global_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_global_variable_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_and_write_node_t); + pm_global_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_and_write_node_t); *node = (pm_global_variable_and_write_node_t) { { .type = PM_GLOBAL_VARIABLE_AND_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->location.start, .end = value->location.end @@ -4493,11 +4514,12 @@ pm_global_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target, */ static pm_global_variable_operator_write_node_t * pm_global_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_global_variable_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_operator_write_node_t); + pm_global_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_operator_write_node_t); *node = (pm_global_variable_operator_write_node_t) { { .type = PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->location.start, .end = value->location.end @@ -4505,9 +4527,9 @@ pm_global_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *ta }, .name = pm_global_variable_write_name(parser, target), .name_loc = target->location, - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) }; return node; @@ -4519,11 +4541,12 @@ pm_global_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *ta static pm_global_variable_or_write_node_t * pm_global_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_global_variable_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_or_write_node_t); + pm_global_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_or_write_node_t); *node = (pm_global_variable_or_write_node_t) { { .type = PM_GLOBAL_VARIABLE_OR_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->location.start, .end = value->location.end @@ -4543,11 +4566,12 @@ pm_global_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, */ static pm_global_variable_read_node_t * pm_global_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name) { - pm_global_variable_read_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_read_node_t); + pm_global_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_read_node_t); *node = (pm_global_variable_read_node_t) { { .type = PM_GLOBAL_VARIABLE_READ_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(name), }, .name = pm_parser_constant_id_token(parser, name) @@ -4561,12 +4585,13 @@ pm_global_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name) */ static pm_global_variable_read_node_t * pm_global_variable_read_node_synthesized_create(pm_parser_t *parser, pm_constant_id_t name) { - pm_global_variable_read_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_read_node_t); + pm_global_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_read_node_t); *node = (pm_global_variable_read_node_t) { { .type = PM_GLOBAL_VARIABLE_READ_NODE, - .location = { .start = parser->start, .end = parser->start } + .node_id = PM_NODE_IDENTIFY(parser), + .location = PM_LOCATION_NULL_VALUE(parser) }, .name = name }; @@ -4579,11 +4604,13 @@ pm_global_variable_read_node_synthesized_create(pm_parser_t *parser, pm_constant */ static pm_global_variable_write_node_t * pm_global_variable_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_global_variable_write_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_write_node_t); + pm_global_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_write_node_t); *node = (pm_global_variable_write_node_t) { { .type = PM_GLOBAL_VARIABLE_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), + .flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), .location = { .start = target->location.start, .end = value->location.end @@ -4603,16 +4630,17 @@ pm_global_variable_write_node_create(pm_parser_t *parser, pm_node_t *target, con */ static pm_global_variable_write_node_t * pm_global_variable_write_node_synthesized_create(pm_parser_t *parser, pm_constant_id_t name, pm_node_t *value) { - pm_global_variable_write_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_write_node_t); + pm_global_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_write_node_t); *node = (pm_global_variable_write_node_t) { { .type = PM_GLOBAL_VARIABLE_WRITE_NODE, - .location = { .start = parser->start, .end = parser->start } + .node_id = PM_NODE_IDENTIFY(parser), + .location = PM_LOCATION_NULL_VALUE(parser) }, .name = name, - .name_loc = { .start = parser->start, .end = parser->start }, - .operator_loc = { .start = parser->start, .end = parser->start }, + .name_loc = PM_LOCATION_NULL_VALUE(parser), + .operator_loc = PM_LOCATION_NULL_VALUE(parser), .value = value }; @@ -4625,12 +4653,13 @@ pm_global_variable_write_node_synthesized_create(pm_parser_t *parser, pm_constan static pm_hash_node_t * pm_hash_node_create(pm_parser_t *parser, const pm_token_t *opening) { assert(opening != NULL); - pm_hash_node_t *node = PM_ALLOC_NODE(parser, pm_hash_node_t); + pm_hash_node_t *node = PM_NODE_ALLOC(parser, pm_hash_node_t); *node = (pm_hash_node_t) { { .type = PM_HASH_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(opening) }, .opening_loc = PM_LOCATION_TOKEN_VALUE(opening), @@ -4676,17 +4705,17 @@ pm_if_node_create(pm_parser_t *parser, pm_node_t *predicate, const pm_token_t *then_keyword, pm_statements_node_t *statements, - pm_node_t *consequent, + pm_node_t *subsequent, const pm_token_t *end_keyword ) { pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - pm_if_node_t *node = PM_ALLOC_NODE(parser, pm_if_node_t); + pm_if_node_t *node = PM_NODE_ALLOC(parser, pm_if_node_t); const uint8_t *end; if (end_keyword->type != PM_TOKEN_NOT_PROVIDED) { end = end_keyword->end; - } else if (consequent != NULL) { - end = consequent->location.end; + } else if (subsequent != NULL) { + end = subsequent->location.end; } else if (pm_statements_node_body_length(statements) != 0) { end = statements->base.location.end; } else { @@ -4697,6 +4726,7 @@ pm_if_node_create(pm_parser_t *parser, { .type = PM_IF_NODE, .flags = PM_NODE_FLAG_NEWLINE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = if_keyword->start, .end = end @@ -4706,7 +4736,7 @@ pm_if_node_create(pm_parser_t *parser, .predicate = predicate, .then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(then_keyword), .statements = statements, - .consequent = consequent, + .subsequent = subsequent, .end_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(end_keyword) }; @@ -4719,15 +4749,16 @@ pm_if_node_create(pm_parser_t *parser, static pm_if_node_t * pm_if_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_token_t *if_keyword, pm_node_t *predicate) { pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - pm_if_node_t *node = PM_ALLOC_NODE(parser, pm_if_node_t); + pm_if_node_t *node = PM_NODE_ALLOC(parser, pm_if_node_t); pm_statements_node_t *statements = pm_statements_node_create(parser); - pm_statements_node_body_append(parser, statements, statement); + pm_statements_node_body_append(parser, statements, statement, true); *node = (pm_if_node_t) { { .type = PM_IF_NODE, .flags = PM_NODE_FLAG_NEWLINE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = statement->location.start, .end = predicate->location.end @@ -4737,7 +4768,7 @@ pm_if_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_t .predicate = predicate, .then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, .statements = statements, - .consequent = NULL, + .subsequent = NULL, .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE }; @@ -4753,20 +4784,21 @@ pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, const pm_to pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); pm_statements_node_t *if_statements = pm_statements_node_create(parser); - pm_statements_node_body_append(parser, if_statements, true_expression); + pm_statements_node_body_append(parser, if_statements, true_expression, true); pm_statements_node_t *else_statements = pm_statements_node_create(parser); - pm_statements_node_body_append(parser, else_statements, false_expression); + pm_statements_node_body_append(parser, else_statements, false_expression, true); pm_token_t end_keyword = not_provided(parser); pm_else_node_t *else_node = pm_else_node_create(parser, colon, else_statements, &end_keyword); - pm_if_node_t *node = PM_ALLOC_NODE(parser, pm_if_node_t); + pm_if_node_t *node = PM_NODE_ALLOC(parser, pm_if_node_t); *node = (pm_if_node_t) { { .type = PM_IF_NODE, .flags = PM_NODE_FLAG_NEWLINE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = predicate->location.start, .end = false_expression->location.end, @@ -4776,7 +4808,7 @@ pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, const pm_to .predicate = predicate, .then_keyword_loc = PM_LOCATION_TOKEN_VALUE(qmark), .statements = if_statements, - .consequent = (pm_node_t *)else_node, + .subsequent = (pm_node_t *) else_node, .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE }; @@ -4801,11 +4833,12 @@ pm_else_node_end_keyword_loc_set(pm_else_node_t *node, const pm_token_t *keyword */ static pm_implicit_node_t * pm_implicit_node_create(pm_parser_t *parser, pm_node_t *value) { - pm_implicit_node_t *node = PM_ALLOC_NODE(parser, pm_implicit_node_t); + pm_implicit_node_t *node = PM_NODE_ALLOC(parser, pm_implicit_node_t); *node = (pm_implicit_node_t) { { .type = PM_IMPLICIT_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = value->location }, .value = value @@ -4821,11 +4854,12 @@ static pm_implicit_rest_node_t * pm_implicit_rest_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_COMMA); - pm_implicit_rest_node_t *node = PM_ALLOC_NODE(parser, pm_implicit_rest_node_t); + pm_implicit_rest_node_t *node = PM_NODE_ALLOC(parser, pm_implicit_rest_node_t); *node = (pm_implicit_rest_node_t) { { .type = PM_IMPLICIT_REST_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) } }; @@ -4839,12 +4873,13 @@ pm_implicit_rest_node_create(pm_parser_t *parser, const pm_token_t *token) { static pm_integer_node_t * pm_integer_node_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) { assert(token->type == PM_TOKEN_INTEGER); - pm_integer_node_t *node = PM_ALLOC_NODE(parser, pm_integer_node_t); + pm_integer_node_t *node = PM_NODE_ALLOC(parser, pm_integer_node_t); *node = (pm_integer_node_t) { { .type = PM_INTEGER_NODE, .flags = base | PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }, .value = { 0 } @@ -4871,11 +4906,12 @@ static pm_imaginary_node_t * pm_integer_node_imaginary_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) { assert(token->type == PM_TOKEN_INTEGER_IMAGINARY); - pm_imaginary_node_t *node = PM_ALLOC_NODE(parser, pm_imaginary_node_t); + pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t); *node = (pm_imaginary_node_t) { { .type = PM_IMAGINARY_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }, .numeric = (pm_node_t *) pm_integer_node_create(parser, base, &((pm_token_t) { @@ -4889,27 +4925,36 @@ pm_integer_node_imaginary_create(pm_parser_t *parser, pm_node_flags_t base, cons } /** - * Allocate and initialize a new IntegerNode node from an INTEGER_RATIONAL + * Allocate and initialize a new RationalNode node from an INTEGER_RATIONAL * token. */ static pm_rational_node_t * pm_integer_node_rational_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) { assert(token->type == PM_TOKEN_INTEGER_RATIONAL); - pm_rational_node_t *node = PM_ALLOC_NODE(parser, pm_rational_node_t); + pm_rational_node_t *node = PM_NODE_ALLOC(parser, pm_rational_node_t); *node = (pm_rational_node_t) { { .type = PM_RATIONAL_NODE, - .flags = PM_NODE_FLAG_STATIC_LITERAL, + .flags = base | PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }, - .numeric = (pm_node_t *) pm_integer_node_create(parser, base, &((pm_token_t) { - .type = PM_TOKEN_INTEGER, - .start = token->start, - .end = token->end - 1 - })) + .numerator = { 0 }, + .denominator = { .value = 1, 0 } }; + pm_integer_base_t integer_base = PM_INTEGER_BASE_DECIMAL; + switch (base) { + case PM_INTEGER_BASE_FLAGS_BINARY: integer_base = PM_INTEGER_BASE_BINARY; break; + case PM_INTEGER_BASE_FLAGS_OCTAL: integer_base = PM_INTEGER_BASE_OCTAL; break; + case PM_INTEGER_BASE_FLAGS_DECIMAL: break; + case PM_INTEGER_BASE_FLAGS_HEXADECIMAL: integer_base = PM_INTEGER_BASE_HEXADECIMAL; break; + default: assert(false && "unreachable"); break; + } + + pm_integer_parse(&node->numerator, integer_base, token->start, token->end - 1); + return node; } @@ -4921,11 +4966,12 @@ static pm_imaginary_node_t * pm_integer_node_rational_imaginary_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) { assert(token->type == PM_TOKEN_INTEGER_RATIONAL_IMAGINARY); - pm_imaginary_node_t *node = PM_ALLOC_NODE(parser, pm_imaginary_node_t); + pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t); *node = (pm_imaginary_node_t) { { .type = PM_IMAGINARY_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }, .numeric = (pm_node_t *) pm_integer_node_rational_create(parser, base, &((pm_token_t) { @@ -4943,7 +4989,7 @@ pm_integer_node_rational_imaginary_create(pm_parser_t *parser, pm_node_flags_t b */ static pm_in_node_t * pm_in_node_create(pm_parser_t *parser, pm_node_t *pattern, pm_statements_node_t *statements, const pm_token_t *in_keyword, const pm_token_t *then_keyword) { - pm_in_node_t *node = PM_ALLOC_NODE(parser, pm_in_node_t); + pm_in_node_t *node = PM_NODE_ALLOC(parser, pm_in_node_t); const uint8_t *end; if (statements != NULL) { @@ -4957,6 +5003,7 @@ pm_in_node_create(pm_parser_t *parser, pm_node_t *pattern, pm_statements_node_t *node = (pm_in_node_t) { { .type = PM_IN_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = in_keyword->start, .end = end @@ -4977,11 +5024,12 @@ pm_in_node_create(pm_parser_t *parser, pm_node_t *pattern, pm_statements_node_t static pm_instance_variable_and_write_node_t * pm_instance_variable_and_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_instance_variable_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_instance_variable_and_write_node_t); + pm_instance_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_and_write_node_t); *node = (pm_instance_variable_and_write_node_t) { { .type = PM_INSTANCE_VARIABLE_AND_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -5001,11 +5049,12 @@ pm_instance_variable_and_write_node_create(pm_parser_t *parser, pm_instance_vari */ static pm_instance_variable_operator_write_node_t * pm_instance_variable_operator_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_instance_variable_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_instance_variable_operator_write_node_t); + pm_instance_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_operator_write_node_t); *node = (pm_instance_variable_operator_write_node_t) { { .type = PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -5013,9 +5062,9 @@ pm_instance_variable_operator_write_node_create(pm_parser_t *parser, pm_instance }, .name = target->name, .name_loc = target->base.location, - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) }; return node; @@ -5027,11 +5076,12 @@ pm_instance_variable_operator_write_node_create(pm_parser_t *parser, pm_instance static pm_instance_variable_or_write_node_t * pm_instance_variable_or_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_instance_variable_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_instance_variable_or_write_node_t); + pm_instance_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_or_write_node_t); *node = (pm_instance_variable_or_write_node_t) { { .type = PM_INSTANCE_VARIABLE_OR_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -5052,11 +5102,12 @@ pm_instance_variable_or_write_node_create(pm_parser_t *parser, pm_instance_varia static pm_instance_variable_read_node_t * pm_instance_variable_read_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_INSTANCE_VARIABLE); - pm_instance_variable_read_node_t *node = PM_ALLOC_NODE(parser, pm_instance_variable_read_node_t); + pm_instance_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_read_node_t); *node = (pm_instance_variable_read_node_t) { { .type = PM_INSTANCE_VARIABLE_READ_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }, .name = pm_parser_constant_id_token(parser, token) @@ -5071,10 +5122,12 @@ pm_instance_variable_read_node_create(pm_parser_t *parser, const pm_token_t *tok */ static pm_instance_variable_write_node_t * pm_instance_variable_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *read_node, pm_token_t *operator, pm_node_t *value) { - pm_instance_variable_write_node_t *node = PM_ALLOC_NODE(parser, pm_instance_variable_write_node_t); + pm_instance_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_write_node_t); *node = (pm_instance_variable_write_node_t) { { .type = PM_INSTANCE_VARIABLE_WRITE_NODE, + .flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = read_node->base.location.start, .end = value->location.end @@ -5138,12 +5191,13 @@ pm_interpolated_node_append(pm_node_t *node, pm_node_list_t *parts, pm_node_t *p */ static pm_interpolated_regular_expression_node_t * pm_interpolated_regular_expression_node_create(pm_parser_t *parser, const pm_token_t *opening) { - pm_interpolated_regular_expression_node_t *node = PM_ALLOC_NODE(parser, pm_interpolated_regular_expression_node_t); + pm_interpolated_regular_expression_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_regular_expression_node_t); *node = (pm_interpolated_regular_expression_node_t) { { .type = PM_INTERPOLATED_REGULAR_EXPRESSION_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = opening->start, .end = NULL, @@ -5215,7 +5269,7 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_ switch (PM_NODE_TYPE(part)) { case PM_STRING_NODE: - pm_node_flag_set(part, PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN); + part->flags = (pm_node_flags_t) ((part->flags | PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN) & ~PM_STRING_FLAGS_MUTABLE); break; case PM_INTERPOLATED_STRING_NODE: if (PM_NODE_FLAG_P(part, PM_NODE_FLAG_STATIC_LITERAL)) { @@ -5239,7 +5293,7 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_ // If the embedded statement is a string, then we can make that // string as frozen and static literal, and not touch the static // literal status of this string. - pm_node_flag_set(embedded, PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN); + embedded->flags = (pm_node_flags_t) ((embedded->flags | PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN) & ~PM_STRING_FLAGS_MUTABLE); if (PM_NODE_FLAG_P(node, PM_NODE_FLAG_STATIC_LITERAL)) { MUTABLE_FLAGS(node); @@ -5280,7 +5334,7 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_ */ static pm_interpolated_string_node_t * pm_interpolated_string_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_node_list_t *parts, const pm_token_t *closing) { - pm_interpolated_string_node_t *node = PM_ALLOC_NODE(parser, pm_interpolated_string_node_t); + pm_interpolated_string_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_string_node_t); pm_node_flags_t flags = PM_NODE_FLAG_STATIC_LITERAL; switch (parser->frozen_string_literal) { @@ -5296,6 +5350,7 @@ pm_interpolated_string_node_create(pm_parser_t *parser, const pm_token_t *openin { .type = PM_INTERPOLATED_STRING_NODE, .flags = flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = opening->start, .end = closing->end, @@ -5346,12 +5401,13 @@ pm_interpolated_symbol_node_closing_loc_set(pm_interpolated_symbol_node_t *node, */ static pm_interpolated_symbol_node_t * pm_interpolated_symbol_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_node_list_t *parts, const pm_token_t *closing) { - pm_interpolated_symbol_node_t *node = PM_ALLOC_NODE(parser, pm_interpolated_symbol_node_t); + pm_interpolated_symbol_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_symbol_node_t); *node = (pm_interpolated_symbol_node_t) { { .type = PM_INTERPOLATED_SYMBOL_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = opening->start, .end = closing->end, @@ -5377,11 +5433,12 @@ pm_interpolated_symbol_node_create(pm_parser_t *parser, const pm_token_t *openin */ static pm_interpolated_x_string_node_t * pm_interpolated_xstring_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) { - pm_interpolated_x_string_node_t *node = PM_ALLOC_NODE(parser, pm_interpolated_x_string_node_t); + pm_interpolated_x_string_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_x_string_node_t); *node = (pm_interpolated_x_string_node_t) { { .type = PM_INTERPOLATED_X_STRING_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = opening->start, .end = closing->end @@ -5407,16 +5464,35 @@ pm_interpolated_xstring_node_closing_set(pm_interpolated_x_string_node_t *node, node->base.location.end = closing->end; } +/** + * Create a local variable read that is reading the implicit 'it' variable. + */ +static pm_it_local_variable_read_node_t * +pm_it_local_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name) { + pm_it_local_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_it_local_variable_read_node_t); + + *node = (pm_it_local_variable_read_node_t) { + { + .type = PM_IT_LOCAL_VARIABLE_READ_NODE, + .node_id = PM_NODE_IDENTIFY(parser), + .location = PM_LOCATION_TOKEN_VALUE(name) + } + }; + + return node; +} + /** * Allocate and initialize a new ItParametersNode node. */ static pm_it_parameters_node_t * pm_it_parameters_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) { - pm_it_parameters_node_t *node = PM_ALLOC_NODE(parser, pm_it_parameters_node_t); + pm_it_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_it_parameters_node_t); *node = (pm_it_parameters_node_t) { { .type = PM_IT_PARAMETERS_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = opening->start, .end = closing->end @@ -5432,13 +5508,14 @@ pm_it_parameters_node_create(pm_parser_t *parser, const pm_token_t *opening, con */ static pm_keyword_hash_node_t * pm_keyword_hash_node_create(pm_parser_t *parser) { - pm_keyword_hash_node_t *node = PM_ALLOC_NODE(parser, pm_keyword_hash_node_t); + pm_keyword_hash_node_t *node = PM_NODE_ALLOC(parser, pm_keyword_hash_node_t); *node = (pm_keyword_hash_node_t) { .base = { .type = PM_KEYWORD_HASH_NODE, - .location = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, - .flags = PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS + .flags = PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS, + .node_id = PM_NODE_IDENTIFY(parser), + .location = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE }, .elements = { 0 } }; @@ -5469,11 +5546,12 @@ pm_keyword_hash_node_elements_append(pm_keyword_hash_node_t *hash, pm_node_t *el */ static pm_required_keyword_parameter_node_t * pm_required_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t *name) { - pm_required_keyword_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_required_keyword_parameter_node_t); + pm_required_keyword_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_required_keyword_parameter_node_t); *node = (pm_required_keyword_parameter_node_t) { { .type = PM_REQUIRED_KEYWORD_PARAMETER_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = name->start, .end = name->end @@ -5491,11 +5569,12 @@ pm_required_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t */ static pm_optional_keyword_parameter_node_t * pm_optional_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, pm_node_t *value) { - pm_optional_keyword_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_optional_keyword_parameter_node_t); + pm_optional_keyword_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_optional_keyword_parameter_node_t); *node = (pm_optional_keyword_parameter_node_t) { { .type = PM_OPTIONAL_KEYWORD_PARAMETER_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = name->start, .end = value->location.end @@ -5514,11 +5593,12 @@ pm_optional_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t */ static pm_keyword_rest_parameter_node_t * pm_keyword_rest_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *name) { - pm_keyword_rest_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_keyword_rest_parameter_node_t); + pm_keyword_rest_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_keyword_rest_parameter_node_t); *node = (pm_keyword_rest_parameter_node_t) { { .type = PM_KEYWORD_REST_PARAMETER_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = operator->start, .end = (name->type == PM_TOKEN_NOT_PROVIDED ? operator->end : name->end) @@ -5545,11 +5625,12 @@ pm_lambda_node_create( pm_node_t *parameters, pm_node_t *body ) { - pm_lambda_node_t *node = PM_ALLOC_NODE(parser, pm_lambda_node_t); + pm_lambda_node_t *node = PM_NODE_ALLOC(parser, pm_lambda_node_t); *node = (pm_lambda_node_t) { { .type = PM_LAMBDA_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = operator->start, .end = closing->end @@ -5573,11 +5654,12 @@ static pm_local_variable_and_write_node_t * pm_local_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value, pm_constant_id_t name, uint32_t depth) { assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_CALL_NODE)); assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_local_variable_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_and_write_node_t); + pm_local_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_and_write_node_t); *node = (pm_local_variable_and_write_node_t) { { .type = PM_LOCAL_VARIABLE_AND_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->location.start, .end = value->location.end @@ -5598,21 +5680,22 @@ pm_local_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target, */ static pm_local_variable_operator_write_node_t * pm_local_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value, pm_constant_id_t name, uint32_t depth) { - pm_local_variable_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_operator_write_node_t); + pm_local_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_operator_write_node_t); *node = (pm_local_variable_operator_write_node_t) { { .type = PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->location.start, .end = value->location.end } }, .name_loc = target->location, - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value, .name = name, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1), + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1), .depth = depth }; @@ -5626,11 +5709,12 @@ static pm_local_variable_or_write_node_t * pm_local_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value, pm_constant_id_t name, uint32_t depth) { assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_CALL_NODE)); assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_local_variable_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_or_write_node_t); + pm_local_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_or_write_node_t); *node = (pm_local_variable_or_write_node_t) { { .type = PM_LOCAL_VARIABLE_OR_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->location.start, .end = value->location.end @@ -5653,11 +5737,12 @@ static pm_local_variable_read_node_t * pm_local_variable_read_node_create_constant_id(pm_parser_t *parser, const pm_token_t *name, pm_constant_id_t name_id, uint32_t depth, bool missing) { if (!missing) pm_locals_read(&pm_parser_scope_find(parser, depth)->locals, name_id); - pm_local_variable_read_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_read_node_t); + pm_local_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_read_node_t); *node = (pm_local_variable_read_node_t) { { .type = PM_LOCAL_VARIABLE_READ_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(name) }, .name = name_id, @@ -5691,11 +5776,13 @@ pm_local_variable_read_node_missing_create(pm_parser_t *parser, const pm_token_t */ static pm_local_variable_write_node_t * pm_local_variable_write_node_create(pm_parser_t *parser, pm_constant_id_t name, uint32_t depth, pm_node_t *value, const pm_location_t *name_loc, const pm_token_t *operator) { - pm_local_variable_write_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_write_node_t); + pm_local_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_write_node_t); *node = (pm_local_variable_write_node_t) { { .type = PM_LOCAL_VARIABLE_WRITE_NODE, + .flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = name_loc->start, .end = value->location.end @@ -5719,28 +5806,6 @@ pm_token_is_it(const uint8_t *start, const uint8_t *end) { return (end - start == 2) && (start[0] == 'i') && (start[1] == 't'); } -/** - * Returns true if the given node is `it` default parameter. - */ -static inline bool -pm_node_is_it(pm_parser_t *parser, pm_node_t *node) { - // Check if it's a local variable reference - if (node->type != PM_CALL_NODE) { - return false; - } - - // Check if it's a variable call - pm_call_node_t *call_node = (pm_call_node_t *) node; - if (!PM_NODE_FLAG_P(call_node, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { - return false; - } - - // Check if it's called `it` - pm_constant_id_t id = ((pm_call_node_t *)node)->name; - pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, id); - return pm_token_is_it(constant->start, constant->start + constant->length); -} - /** * Returns true if the given bounds comprise a numbered parameter (i.e., they * are of the form /^_\d$/). @@ -5768,11 +5833,12 @@ pm_refute_numbered_parameter(pm_parser_t *parser, const uint8_t *start, const ui static pm_local_variable_target_node_t * pm_local_variable_target_node_create(pm_parser_t *parser, const pm_location_t *location, pm_constant_id_t name, uint32_t depth) { pm_refute_numbered_parameter(parser, location->start, location->end); - pm_local_variable_target_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_target_node_t); + pm_local_variable_target_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_target_node_t); *node = (pm_local_variable_target_node_t) { { .type = PM_LOCAL_VARIABLE_TARGET_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = *location }, .name = name, @@ -5789,11 +5855,12 @@ static pm_match_predicate_node_t * pm_match_predicate_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t *pattern, const pm_token_t *operator) { pm_assert_value_expression(parser, value); - pm_match_predicate_node_t *node = PM_ALLOC_NODE(parser, pm_match_predicate_node_t); + pm_match_predicate_node_t *node = PM_NODE_ALLOC(parser, pm_match_predicate_node_t); *node = (pm_match_predicate_node_t) { { .type = PM_MATCH_PREDICATE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = value->location.start, .end = pattern->location.end @@ -5814,11 +5881,12 @@ static pm_match_required_node_t * pm_match_required_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t *pattern, const pm_token_t *operator) { pm_assert_value_expression(parser, value); - pm_match_required_node_t *node = PM_ALLOC_NODE(parser, pm_match_required_node_t); + pm_match_required_node_t *node = PM_NODE_ALLOC(parser, pm_match_required_node_t); *node = (pm_match_required_node_t) { { .type = PM_MATCH_REQUIRED_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = value->location.start, .end = pattern->location.end @@ -5837,11 +5905,12 @@ pm_match_required_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t * */ static pm_match_write_node_t * pm_match_write_node_create(pm_parser_t *parser, pm_call_node_t *call) { - pm_match_write_node_t *node = PM_ALLOC_NODE(parser, pm_match_write_node_t); + pm_match_write_node_t *node = PM_NODE_ALLOC(parser, pm_match_write_node_t); *node = (pm_match_write_node_t) { { .type = PM_MATCH_WRITE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = call->base.location }, .call = call, @@ -5856,11 +5925,12 @@ pm_match_write_node_create(pm_parser_t *parser, pm_call_node_t *call) { */ static pm_module_node_t * pm_module_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *module_keyword, pm_node_t *constant_path, const pm_token_t *name, pm_node_t *body, const pm_token_t *end_keyword) { - pm_module_node_t *node = PM_ALLOC_NODE(parser, pm_module_node_t); + pm_module_node_t *node = PM_NODE_ALLOC(parser, pm_module_node_t); *node = (pm_module_node_t) { { .type = PM_MODULE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = module_keyword->start, .end = end_keyword->end @@ -5882,11 +5952,12 @@ pm_module_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const */ static pm_multi_target_node_t * pm_multi_target_node_create(pm_parser_t *parser) { - pm_multi_target_node_t *node = PM_ALLOC_NODE(parser, pm_multi_target_node_t); + pm_multi_target_node_t *node = PM_NODE_ALLOC(parser, pm_multi_target_node_t); *node = (pm_multi_target_node_t) { { .type = PM_MULTI_TARGET_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = NULL, .end = NULL } }, .lefts = { 0 }, @@ -5956,11 +6027,13 @@ pm_multi_target_node_closing_set(pm_multi_target_node_t *node, const pm_token_t */ static pm_multi_write_node_t * pm_multi_write_node_create(pm_parser_t *parser, pm_multi_target_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_multi_write_node_t *node = PM_ALLOC_NODE(parser, pm_multi_write_node_t); + pm_multi_write_node_t *node = PM_NODE_ALLOC(parser, pm_multi_write_node_t); *node = (pm_multi_write_node_t) { { .type = PM_MULTI_WRITE_NODE, + .flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = target->base.location.start, .end = value->location.end @@ -5988,11 +6061,12 @@ pm_multi_write_node_create(pm_parser_t *parser, pm_multi_target_node_t *target, static pm_next_node_t * pm_next_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_node_t *arguments) { assert(keyword->type == PM_TOKEN_KEYWORD_NEXT); - pm_next_node_t *node = PM_ALLOC_NODE(parser, pm_next_node_t); + pm_next_node_t *node = PM_NODE_ALLOC(parser, pm_next_node_t); *node = (pm_next_node_t) { { .type = PM_NEXT_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = keyword->start, .end = (arguments == NULL ? keyword->end : arguments->base.location.end) @@ -6011,11 +6085,12 @@ pm_next_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments static pm_nil_node_t * pm_nil_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD_NIL); - pm_nil_node_t *node = PM_ALLOC_NODE(parser, pm_nil_node_t); + pm_nil_node_t *node = PM_NODE_ALLOC(parser, pm_nil_node_t); *node = (pm_nil_node_t) {{ .type = PM_NIL_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }}; @@ -6029,11 +6104,12 @@ static pm_no_keywords_parameter_node_t * pm_no_keywords_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *keyword) { assert(operator->type == PM_TOKEN_USTAR_STAR || operator->type == PM_TOKEN_STAR_STAR); assert(keyword->type == PM_TOKEN_KEYWORD_NIL); - pm_no_keywords_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_no_keywords_parameter_node_t); + pm_no_keywords_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_no_keywords_parameter_node_t); *node = (pm_no_keywords_parameter_node_t) { { .type = PM_NO_KEYWORDS_PARAMETER_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = operator->start, .end = keyword->end @@ -6051,11 +6127,12 @@ pm_no_keywords_parameter_node_create(pm_parser_t *parser, const pm_token_t *oper */ static pm_numbered_parameters_node_t * pm_numbered_parameters_node_create(pm_parser_t *parser, const pm_location_t *location, uint8_t maximum) { - pm_numbered_parameters_node_t *node = PM_ALLOC_NODE(parser, pm_numbered_parameters_node_t); + pm_numbered_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_numbered_parameters_node_t); *node = (pm_numbered_parameters_node_t) { { .type = PM_NUMBERED_PARAMETERS_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = *location }, .maximum = maximum @@ -6093,14 +6170,14 @@ pm_numbered_reference_read_node_number(pm_parser_t *parser, const pm_token_t *to errno = 0; unsigned long value = strtoul(digits, &endptr, 10); - if ((digits == endptr) || (*endptr != '\0') || (errno == ERANGE)) { + if ((digits == endptr) || (*endptr != '\0')) { pm_parser_err(parser, start, end, PM_ERR_INVALID_NUMBER_DECIMAL); value = 0; } xfree(digits); - if (value > NTH_REF_MAX) { + if ((errno == ERANGE) || (value > NTH_REF_MAX)) { PM_PARSER_WARN_FORMAT(parser, start, end, PM_WARN_INVALID_NUMBERED_REFERENCE, (int) (length + 1), (const char *) token->start); value = 0; } @@ -6116,11 +6193,12 @@ pm_numbered_reference_read_node_number(pm_parser_t *parser, const pm_token_t *to static pm_numbered_reference_read_node_t * pm_numbered_reference_read_node_create(pm_parser_t *parser, const pm_token_t *name) { assert(name->type == PM_TOKEN_NUMBERED_REFERENCE); - pm_numbered_reference_read_node_t *node = PM_ALLOC_NODE(parser, pm_numbered_reference_read_node_t); + pm_numbered_reference_read_node_t *node = PM_NODE_ALLOC(parser, pm_numbered_reference_read_node_t); *node = (pm_numbered_reference_read_node_t) { { .type = PM_NUMBERED_REFERENCE_READ_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(name), }, .number = pm_numbered_reference_read_node_number(parser, name) @@ -6134,11 +6212,12 @@ pm_numbered_reference_read_node_create(pm_parser_t *parser, const pm_token_t *na */ static pm_optional_parameter_node_t * pm_optional_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, const pm_token_t *operator, pm_node_t *value) { - pm_optional_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_optional_parameter_node_t); + pm_optional_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_optional_parameter_node_t); *node = (pm_optional_parameter_node_t) { { .type = PM_OPTIONAL_PARAMETER_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = name->start, .end = value->location.end @@ -6160,11 +6239,12 @@ static pm_or_node_t * pm_or_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operator, pm_node_t *right) { pm_assert_value_expression(parser, left); - pm_or_node_t *node = PM_ALLOC_NODE(parser, pm_or_node_t); + pm_or_node_t *node = PM_NODE_ALLOC(parser, pm_or_node_t); *node = (pm_or_node_t) { { .type = PM_OR_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = left->location.start, .end = right->location.end @@ -6183,11 +6263,12 @@ pm_or_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operat */ static pm_parameters_node_t * pm_parameters_node_create(pm_parser_t *parser) { - pm_parameters_node_t *node = PM_ALLOC_NODE(parser, pm_parameters_node_t); + pm_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_parameters_node_t); *node = (pm_parameters_node_t) { { .type = PM_PARAMETERS_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(&parser->current) }, .rest = NULL, @@ -6290,11 +6371,12 @@ pm_parameters_node_block_set(pm_parameters_node_t *params, pm_block_parameter_no */ static pm_program_node_t * pm_program_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, pm_statements_node_t *statements) { - pm_program_node_t *node = PM_ALLOC_NODE(parser, pm_program_node_t); + pm_program_node_t *node = PM_NODE_ALLOC(parser, pm_program_node_t); *node = (pm_program_node_t) { { .type = PM_PROGRAM_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = statements == NULL ? parser->start : statements->base.location.start, .end = statements == NULL ? parser->end : statements->base.location.end @@ -6312,11 +6394,12 @@ pm_program_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, pm_st */ static pm_parentheses_node_t * pm_parentheses_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_node_t *body, const pm_token_t *closing) { - pm_parentheses_node_t *node = PM_ALLOC_NODE(parser, pm_parentheses_node_t); + pm_parentheses_node_t *node = PM_NODE_ALLOC(parser, pm_parentheses_node_t); *node = (pm_parentheses_node_t) { { .type = PM_PARENTHESES_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = opening->start, .end = closing->end @@ -6335,11 +6418,12 @@ pm_parentheses_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_no */ static pm_pinned_expression_node_t * pm_pinned_expression_node_create(pm_parser_t *parser, pm_node_t *expression, const pm_token_t *operator, const pm_token_t *lparen, const pm_token_t *rparen) { - pm_pinned_expression_node_t *node = PM_ALLOC_NODE(parser, pm_pinned_expression_node_t); + pm_pinned_expression_node_t *node = PM_NODE_ALLOC(parser, pm_pinned_expression_node_t); *node = (pm_pinned_expression_node_t) { { .type = PM_PINNED_EXPRESSION_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = operator->start, .end = rparen->end @@ -6359,11 +6443,12 @@ pm_pinned_expression_node_create(pm_parser_t *parser, pm_node_t *expression, con */ static pm_pinned_variable_node_t * pm_pinned_variable_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *variable) { - pm_pinned_variable_node_t *node = PM_ALLOC_NODE(parser, pm_pinned_variable_node_t); + pm_pinned_variable_node_t *node = PM_NODE_ALLOC(parser, pm_pinned_variable_node_t); *node = (pm_pinned_variable_node_t) { { .type = PM_PINNED_VARIABLE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = operator->start, .end = variable->location.end @@ -6381,11 +6466,12 @@ pm_pinned_variable_node_create(pm_parser_t *parser, const pm_token_t *operator, */ static pm_post_execution_node_t * pm_post_execution_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *opening, pm_statements_node_t *statements, const pm_token_t *closing) { - pm_post_execution_node_t *node = PM_ALLOC_NODE(parser, pm_post_execution_node_t); + pm_post_execution_node_t *node = PM_NODE_ALLOC(parser, pm_post_execution_node_t); *node = (pm_post_execution_node_t) { { .type = PM_POST_EXECUTION_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = keyword->start, .end = closing->end @@ -6405,11 +6491,12 @@ pm_post_execution_node_create(pm_parser_t *parser, const pm_token_t *keyword, co */ static pm_pre_execution_node_t * pm_pre_execution_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *opening, pm_statements_node_t *statements, const pm_token_t *closing) { - pm_pre_execution_node_t *node = PM_ALLOC_NODE(parser, pm_pre_execution_node_t); + pm_pre_execution_node_t *node = PM_NODE_ALLOC(parser, pm_pre_execution_node_t); *node = (pm_pre_execution_node_t) { { .type = PM_PRE_EXECUTION_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = keyword->start, .end = closing->end @@ -6432,7 +6519,7 @@ pm_range_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *ope pm_assert_value_expression(parser, left); pm_assert_value_expression(parser, right); - pm_range_node_t *node = PM_ALLOC_NODE(parser, pm_range_node_t); + pm_range_node_t *node = PM_NODE_ALLOC(parser, pm_range_node_t); pm_node_flags_t flags = 0; // Indicate that this node is an exclusive range if the operator is `...`. @@ -6454,6 +6541,7 @@ pm_range_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *ope { .type = PM_RANGE_NODE, .flags = flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = (left == NULL ? operator->start : left->location.start), .end = (right == NULL ? operator->end : right->location.end) @@ -6473,9 +6561,14 @@ pm_range_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *ope static pm_redo_node_t * pm_redo_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD_REDO); - pm_redo_node_t *node = PM_ALLOC_NODE(parser, pm_redo_node_t); + pm_redo_node_t *node = PM_NODE_ALLOC(parser, pm_redo_node_t); + + *node = (pm_redo_node_t) {{ + .type = PM_REDO_NODE, + .node_id = PM_NODE_IDENTIFY(parser), + .location = PM_LOCATION_TOKEN_VALUE(token) + }}; - *node = (pm_redo_node_t) {{ .type = PM_REDO_NODE, .location = PM_LOCATION_TOKEN_VALUE(token) }}; return node; } @@ -6485,12 +6578,13 @@ pm_redo_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_regular_expression_node_t * pm_regular_expression_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *content, const pm_token_t *closing, const pm_string_t *unescaped) { - pm_regular_expression_node_t *node = PM_ALLOC_NODE(parser, pm_regular_expression_node_t); + pm_regular_expression_node_t *node = PM_NODE_ALLOC(parser, pm_regular_expression_node_t); *node = (pm_regular_expression_node_t) { { .type = PM_REGULAR_EXPRESSION_NODE, .flags = pm_regular_expression_flags_create(parser, closing) | PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = MIN(opening->start, closing->start), .end = MAX(opening->end, closing->end) @@ -6518,11 +6612,12 @@ pm_regular_expression_node_create(pm_parser_t *parser, const pm_token_t *opening */ static pm_required_parameter_node_t * pm_required_parameter_node_create(pm_parser_t *parser, const pm_token_t *token) { - pm_required_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_required_parameter_node_t); + pm_required_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_required_parameter_node_t); *node = (pm_required_parameter_node_t) { { .type = PM_REQUIRED_PARAMETER_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }, .name = pm_parser_constant_id_token(parser, token) @@ -6536,11 +6631,12 @@ pm_required_parameter_node_create(pm_parser_t *parser, const pm_token_t *token) */ static pm_rescue_modifier_node_t * pm_rescue_modifier_node_create(pm_parser_t *parser, pm_node_t *expression, const pm_token_t *keyword, pm_node_t *rescue_expression) { - pm_rescue_modifier_node_t *node = PM_ALLOC_NODE(parser, pm_rescue_modifier_node_t); + pm_rescue_modifier_node_t *node = PM_NODE_ALLOC(parser, pm_rescue_modifier_node_t); *node = (pm_rescue_modifier_node_t) { { .type = PM_RESCUE_MODIFIER_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = expression->location.start, .end = rescue_expression->location.end @@ -6559,18 +6655,19 @@ pm_rescue_modifier_node_create(pm_parser_t *parser, pm_node_t *expression, const */ static pm_rescue_node_t * pm_rescue_node_create(pm_parser_t *parser, const pm_token_t *keyword) { - pm_rescue_node_t *node = PM_ALLOC_NODE(parser, pm_rescue_node_t); + pm_rescue_node_t *node = PM_NODE_ALLOC(parser, pm_rescue_node_t); *node = (pm_rescue_node_t) { { .type = PM_RESCUE_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(keyword) }, .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword), .operator_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, .reference = NULL, .statements = NULL, - .consequent = NULL, + .subsequent = NULL, .exceptions = { 0 } }; @@ -6603,12 +6700,12 @@ pm_rescue_node_statements_set(pm_rescue_node_t *node, pm_statements_node_t *stat } /** - * Set the consequent of a rescue node, and update the location. + * Set the subsequent of a rescue node, and update the location. */ static void -pm_rescue_node_consequent_set(pm_rescue_node_t *node, pm_rescue_node_t *consequent) { - node->consequent = consequent; - node->base.location.end = consequent->base.location.end; +pm_rescue_node_subsequent_set(pm_rescue_node_t *node, pm_rescue_node_t *subsequent) { + node->subsequent = subsequent; + node->base.location.end = subsequent->base.location.end; } /** @@ -6625,11 +6722,12 @@ pm_rescue_node_exceptions_append(pm_rescue_node_t *node, pm_node_t *exception) { */ static pm_rest_parameter_node_t * pm_rest_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *name) { - pm_rest_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_rest_parameter_node_t); + pm_rest_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_rest_parameter_node_t); *node = (pm_rest_parameter_node_t) { { .type = PM_REST_PARAMETER_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = operator->start, .end = (name->type == PM_TOKEN_NOT_PROVIDED ? operator->end : name->end) @@ -6649,9 +6747,14 @@ pm_rest_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, c static pm_retry_node_t * pm_retry_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD_RETRY); - pm_retry_node_t *node = PM_ALLOC_NODE(parser, pm_retry_node_t); + pm_retry_node_t *node = PM_NODE_ALLOC(parser, pm_retry_node_t); + + *node = (pm_retry_node_t) {{ + .type = PM_RETRY_NODE, + .node_id = PM_NODE_IDENTIFY(parser), + .location = PM_LOCATION_TOKEN_VALUE(token) + }}; - *node = (pm_retry_node_t) {{ .type = PM_RETRY_NODE, .location = PM_LOCATION_TOKEN_VALUE(token) }}; return node; } @@ -6660,12 +6763,12 @@ pm_retry_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_return_node_t * pm_return_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_node_t *arguments) { - pm_return_node_t *node = PM_ALLOC_NODE(parser, pm_return_node_t); + pm_return_node_t *node = PM_NODE_ALLOC(parser, pm_return_node_t); *node = (pm_return_node_t) { { .type = PM_RETURN_NODE, - .flags = 0, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = keyword->start, .end = (arguments == NULL ? keyword->end : arguments->base.location.end) @@ -6684,10 +6787,11 @@ pm_return_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argumen static pm_self_node_t * pm_self_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD_SELF); - pm_self_node_t *node = PM_ALLOC_NODE(parser, pm_self_node_t); + pm_self_node_t *node = PM_NODE_ALLOC(parser, pm_self_node_t); *node = (pm_self_node_t) {{ .type = PM_SELF_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }}; @@ -6699,12 +6803,13 @@ pm_self_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_shareable_constant_node_t * pm_shareable_constant_node_create(pm_parser_t *parser, pm_node_t *write, pm_shareable_constant_value_t value) { - pm_shareable_constant_node_t *node = PM_ALLOC_NODE(parser, pm_shareable_constant_node_t); + pm_shareable_constant_node_t *node = PM_NODE_ALLOC(parser, pm_shareable_constant_node_t); *node = (pm_shareable_constant_node_t) { { .type = PM_SHAREABLE_CONSTANT_NODE, .flags = (pm_node_flags_t) value, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_NODE_VALUE(write) }, .write = write @@ -6718,11 +6823,12 @@ pm_shareable_constant_node_create(pm_parser_t *parser, pm_node_t *write, pm_shar */ static pm_singleton_class_node_t * pm_singleton_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *class_keyword, const pm_token_t *operator, pm_node_t *expression, pm_node_t *body, const pm_token_t *end_keyword) { - pm_singleton_class_node_t *node = PM_ALLOC_NODE(parser, pm_singleton_class_node_t); + pm_singleton_class_node_t *node = PM_NODE_ALLOC(parser, pm_singleton_class_node_t); *node = (pm_singleton_class_node_t) { { .type = PM_SINGLETON_CLASS_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = class_keyword->start, .end = end_keyword->end @@ -6745,11 +6851,12 @@ pm_singleton_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *local static pm_source_encoding_node_t * pm_source_encoding_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD___ENCODING__); - pm_source_encoding_node_t *node = PM_ALLOC_NODE(parser, pm_source_encoding_node_t); + pm_source_encoding_node_t *node = PM_NODE_ALLOC(parser, pm_source_encoding_node_t); *node = (pm_source_encoding_node_t) {{ .type = PM_SOURCE_ENCODING_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }}; @@ -6761,7 +6868,7 @@ pm_source_encoding_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_source_file_node_t* pm_source_file_node_create(pm_parser_t *parser, const pm_token_t *file_keyword) { - pm_source_file_node_t *node = PM_ALLOC_NODE(parser, pm_source_file_node_t); + pm_source_file_node_t *node = PM_NODE_ALLOC(parser, pm_source_file_node_t); assert(file_keyword->type == PM_TOKEN_KEYWORD___FILE__); pm_node_flags_t flags = 0; @@ -6779,6 +6886,7 @@ pm_source_file_node_create(pm_parser_t *parser, const pm_token_t *file_keyword) { .type = PM_SOURCE_FILE_NODE, .flags = flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(file_keyword), }, .filepath = parser->filepath @@ -6793,11 +6901,12 @@ pm_source_file_node_create(pm_parser_t *parser, const pm_token_t *file_keyword) static pm_source_line_node_t * pm_source_line_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD___LINE__); - pm_source_line_node_t *node = PM_ALLOC_NODE(parser, pm_source_line_node_t); + pm_source_line_node_t *node = PM_NODE_ALLOC(parser, pm_source_line_node_t); *node = (pm_source_line_node_t) {{ .type = PM_SOURCE_LINE_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }}; @@ -6809,11 +6918,12 @@ pm_source_line_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_splat_node_t * pm_splat_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *expression) { - pm_splat_node_t *node = PM_ALLOC_NODE(parser, pm_splat_node_t); + pm_splat_node_t *node = PM_NODE_ALLOC(parser, pm_splat_node_t); *node = (pm_splat_node_t) { { .type = PM_SPLAT_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = operator->start, .end = (expression == NULL ? operator->end : expression->location.end) @@ -6831,11 +6941,12 @@ pm_splat_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t */ static pm_statements_node_t * pm_statements_node_create(pm_parser_t *parser) { - pm_statements_node_t *node = PM_ALLOC_NODE(parser, pm_statements_node_t); + pm_statements_node_t *node = PM_NODE_ALLOC(parser, pm_statements_node_t); *node = (pm_statements_node_t) { { .type = PM_STATEMENTS_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_NULL_VALUE(parser) }, .body = { 0 } @@ -6879,7 +6990,7 @@ pm_statements_node_body_update(pm_statements_node_t *node, pm_node_t *statement) * Append a new node to the given StatementsNode node's body. */ static void -pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node, pm_node_t *statement) { +pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node, pm_node_t *statement, bool newline) { pm_statements_node_body_update(node, statement); if (node->body.size > 0) { @@ -6891,7 +7002,7 @@ pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node, case PM_REDO_NODE: case PM_RETRY_NODE: case PM_RETURN_NODE: - pm_parser_warn_node(parser, previous, PM_WARN_UNREACHABLE_STATEMENT); + pm_parser_warn_node(parser, statement, PM_WARN_UNREACHABLE_STATEMENT); break; default: break; @@ -6899,7 +7010,7 @@ pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node, } pm_node_list_append(&node->body, statement); - pm_node_flag_set(statement, PM_NODE_FLAG_NEWLINE); + if (newline) pm_node_flag_set(statement, PM_NODE_FLAG_NEWLINE); } /** @@ -6917,7 +7028,7 @@ pm_statements_node_body_prepend(pm_statements_node_t *node, pm_node_t *statement */ static inline pm_string_node_t * pm_string_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *content, const pm_token_t *closing, const pm_string_t *string) { - pm_string_node_t *node = PM_ALLOC_NODE(parser, pm_string_node_t); + pm_string_node_t *node = PM_NODE_ALLOC(parser, pm_string_node_t); pm_node_flags_t flags = 0; switch (parser->frozen_string_literal) { @@ -6933,6 +7044,7 @@ pm_string_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, { .type = PM_STRING_NODE, .flags = flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = (opening->type == PM_TOKEN_NOT_PROVIDED ? content->start : opening->start), .end = (closing->type == PM_TOKEN_NOT_PROVIDED ? content->end : closing->end) @@ -6972,7 +7084,7 @@ pm_string_node_create_current_string(pm_parser_t *parser, const pm_token_t *open static pm_super_node_t * pm_super_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_t *arguments) { assert(keyword->type == PM_TOKEN_KEYWORD_SUPER); - pm_super_node_t *node = PM_ALLOC_NODE(parser, pm_super_node_t); + pm_super_node_t *node = PM_NODE_ALLOC(parser, pm_super_node_t); const uint8_t *end = pm_arguments_end(arguments); if (end == NULL) { @@ -6982,6 +7094,7 @@ pm_super_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argument *node = (pm_super_node_t) { { .type = PM_SUPER_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = keyword->start, .end = end, @@ -7213,12 +7326,13 @@ parse_and_validate_regular_expression_encoding(pm_parser_t *parser, const pm_str */ static pm_symbol_node_t * pm_symbol_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *value, const pm_token_t *closing, const pm_string_t *unescaped, pm_node_flags_t flags) { - pm_symbol_node_t *node = PM_ALLOC_NODE(parser, pm_symbol_node_t); + pm_symbol_node_t *node = PM_NODE_ALLOC(parser, pm_symbol_node_t); *node = (pm_symbol_node_t) { { .type = PM_SYMBOL_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL | flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = (opening->type == PM_TOKEN_NOT_PROVIDED ? value->start : opening->start), .end = (closing->type == PM_TOKEN_NOT_PROVIDED ? value->end : closing->end) @@ -7294,15 +7408,16 @@ pm_symbol_node_label_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_symbol_node_t * pm_symbol_node_synthesized_create(pm_parser_t *parser, const char *content) { - pm_symbol_node_t *node = PM_ALLOC_NODE(parser, pm_symbol_node_t); + pm_symbol_node_t *node = PM_NODE_ALLOC(parser, pm_symbol_node_t); *node = (pm_symbol_node_t) { { .type = PM_SYMBOL_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL | PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING, - .location = { .start = parser->start, .end = parser->start } + .node_id = PM_NODE_IDENTIFY(parser), + .location = PM_LOCATION_NULL_VALUE(parser) }, - .value_loc = { .start = parser->start, .end = parser->start }, + .value_loc = PM_LOCATION_NULL_VALUE(parser), .unescaped = { 0 } }; @@ -7336,12 +7451,13 @@ pm_symbol_node_label_p(pm_node_t *node) { */ static pm_symbol_node_t * pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const pm_token_t *opening, const pm_token_t *closing) { - pm_symbol_node_t *new_node = PM_ALLOC_NODE(parser, pm_symbol_node_t); + pm_symbol_node_t *new_node = PM_NODE_ALLOC(parser, pm_symbol_node_t); *new_node = (pm_symbol_node_t) { { .type = PM_SYMBOL_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = opening->start, .end = closing->end @@ -7369,7 +7485,7 @@ pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const */ static pm_string_node_t * pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) { - pm_string_node_t *new_node = PM_ALLOC_NODE(parser, pm_string_node_t); + pm_string_node_t *new_node = PM_NODE_ALLOC(parser, pm_string_node_t); pm_node_flags_t flags = 0; switch (parser->frozen_string_literal) { @@ -7385,6 +7501,7 @@ pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) { { .type = PM_STRING_NODE, .flags = flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = node->base.location }, .opening_loc = node->opening_loc, @@ -7407,11 +7524,12 @@ pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) { static pm_true_node_t * pm_true_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD_TRUE); - pm_true_node_t *node = PM_ALLOC_NODE(parser, pm_true_node_t); + pm_true_node_t *node = PM_NODE_ALLOC(parser, pm_true_node_t); *node = (pm_true_node_t) {{ .type = PM_TRUE_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token) }}; @@ -7423,11 +7541,12 @@ pm_true_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_true_node_t * pm_true_node_synthesized_create(pm_parser_t *parser) { - pm_true_node_t *node = PM_ALLOC_NODE(parser, pm_true_node_t); + pm_true_node_t *node = PM_NODE_ALLOC(parser, pm_true_node_t); *node = (pm_true_node_t) {{ .type = PM_TRUE_NODE, .flags = PM_NODE_FLAG_STATIC_LITERAL, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = parser->start, .end = parser->end } }}; @@ -7440,11 +7559,12 @@ pm_true_node_synthesized_create(pm_parser_t *parser) { static pm_undef_node_t * pm_undef_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD_UNDEF); - pm_undef_node_t *node = PM_ALLOC_NODE(parser, pm_undef_node_t); + pm_undef_node_t *node = PM_NODE_ALLOC(parser, pm_undef_node_t); *node = (pm_undef_node_t) { { .type = PM_UNDEF_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = PM_LOCATION_TOKEN_VALUE(token), }, .keyword_loc = PM_LOCATION_TOKEN_VALUE(token), @@ -7469,7 +7589,7 @@ pm_undef_node_append(pm_undef_node_t *node, pm_node_t *name) { static pm_unless_node_t * pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, const pm_token_t *then_keyword, pm_statements_node_t *statements) { pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - pm_unless_node_t *node = PM_ALLOC_NODE(parser, pm_unless_node_t); + pm_unless_node_t *node = PM_NODE_ALLOC(parser, pm_unless_node_t); const uint8_t *end; if (statements != NULL) { @@ -7482,6 +7602,7 @@ pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t { .type = PM_UNLESS_NODE, .flags = PM_NODE_FLAG_NEWLINE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = keyword->start, .end = end @@ -7491,7 +7612,7 @@ pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t .predicate = predicate, .then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(then_keyword), .statements = statements, - .consequent = NULL, + .else_clause = NULL, .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE }; @@ -7504,15 +7625,16 @@ pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t static pm_unless_node_t * pm_unless_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_token_t *unless_keyword, pm_node_t *predicate) { pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - pm_unless_node_t *node = PM_ALLOC_NODE(parser, pm_unless_node_t); + pm_unless_node_t *node = PM_NODE_ALLOC(parser, pm_unless_node_t); pm_statements_node_t *statements = pm_statements_node_create(parser); - pm_statements_node_body_append(parser, statements, statement); + pm_statements_node_body_append(parser, statements, statement, true); *node = (pm_unless_node_t) { { .type = PM_UNLESS_NODE, .flags = PM_NODE_FLAG_NEWLINE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = statement->location.start, .end = predicate->location.end @@ -7522,7 +7644,7 @@ pm_unless_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const .predicate = predicate, .then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, .statements = statements, - .consequent = NULL, + .else_clause = NULL, .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE }; @@ -7535,18 +7657,42 @@ pm_unless_node_end_keyword_loc_set(pm_unless_node_t *node, const pm_token_t *end node->base.location.end = end_keyword->end; } +/** + * Loop modifiers could potentially modify an expression that contains block + * exits. In this case we need to loop through them and remove them from the + * list of block exits so that they do not later get marked as invalid. + */ +static void +pm_loop_modifier_block_exits(pm_parser_t *parser, pm_statements_node_t *statements) { + assert(parser->current_block_exits != NULL); + + // All of the block exits that we want to remove should be within the + // statements, and since we are modifying the statements, we shouldn't have + // to check the end location. + const uint8_t *start = statements->base.location.start; + + for (size_t index = parser->current_block_exits->size; index > 0; index--) { + pm_node_t *block_exit = parser->current_block_exits->nodes[index - 1]; + if (block_exit->location.start < start) break; + + // Implicitly remove from the list by lowering the size. + parser->current_block_exits->size--; + } +} + /** * Allocate a new UntilNode node. */ static pm_until_node_t * pm_until_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *closing, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) { - pm_until_node_t *node = PM_ALLOC_NODE(parser, pm_until_node_t); + pm_until_node_t *node = PM_NODE_ALLOC(parser, pm_until_node_t); pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); *node = (pm_until_node_t) { { .type = PM_UNTIL_NODE, .flags = flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = keyword->start, .end = closing->end, @@ -7566,13 +7712,15 @@ pm_until_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_to */ static pm_until_node_t * pm_until_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) { - pm_until_node_t *node = PM_ALLOC_NODE(parser, pm_until_node_t); + pm_until_node_t *node = PM_NODE_ALLOC(parser, pm_until_node_t); pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); + pm_loop_modifier_block_exits(parser, statements); *node = (pm_until_node_t) { { .type = PM_UNTIL_NODE, .flags = flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = statements->base.location.start, .end = predicate->location.end, @@ -7592,11 +7740,12 @@ pm_until_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm */ static pm_when_node_t * pm_when_node_create(pm_parser_t *parser, const pm_token_t *keyword) { - pm_when_node_t *node = PM_ALLOC_NODE(parser, pm_when_node_t); + pm_when_node_t *node = PM_NODE_ALLOC(parser, pm_when_node_t); *node = (pm_when_node_t) { { .type = PM_WHEN_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = keyword->start, .end = NULL @@ -7646,13 +7795,14 @@ pm_when_node_statements_set(pm_when_node_t *node, pm_statements_node_t *statemen */ static pm_while_node_t * pm_while_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *closing, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) { - pm_while_node_t *node = PM_ALLOC_NODE(parser, pm_while_node_t); + pm_while_node_t *node = PM_NODE_ALLOC(parser, pm_while_node_t); pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); *node = (pm_while_node_t) { { .type = PM_WHILE_NODE, .flags = flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = keyword->start, .end = closing->end @@ -7672,13 +7822,15 @@ pm_while_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_to */ static pm_while_node_t * pm_while_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) { - pm_while_node_t *node = PM_ALLOC_NODE(parser, pm_while_node_t); + pm_while_node_t *node = PM_NODE_ALLOC(parser, pm_while_node_t); pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); + pm_loop_modifier_block_exits(parser, statements); *node = (pm_while_node_t) { { .type = PM_WHILE_NODE, .flags = flags, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = statements->base.location.start, .end = predicate->location.end @@ -7698,15 +7850,16 @@ pm_while_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm */ static pm_while_node_t * pm_while_node_synthesized_create(pm_parser_t *parser, pm_node_t *predicate, pm_statements_node_t *statements) { - pm_while_node_t *node = PM_ALLOC_NODE(parser, pm_while_node_t); + pm_while_node_t *node = PM_NODE_ALLOC(parser, pm_while_node_t); *node = (pm_while_node_t) { { .type = PM_WHILE_NODE, - .location = { .start = parser->start, .end = parser->start } + .node_id = PM_NODE_IDENTIFY(parser), + .location = PM_LOCATION_NULL_VALUE(parser) }, - .keyword_loc = { .start = parser->start, .end = parser->start }, - .closing_loc = { .start = parser->start, .end = parser->start }, + .keyword_loc = PM_LOCATION_NULL_VALUE(parser), + .closing_loc = PM_LOCATION_NULL_VALUE(parser), .predicate = predicate, .statements = statements }; @@ -7720,12 +7873,13 @@ pm_while_node_synthesized_create(pm_parser_t *parser, pm_node_t *predicate, pm_s */ static pm_x_string_node_t * pm_xstring_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *content, const pm_token_t *closing, const pm_string_t *unescaped) { - pm_x_string_node_t *node = PM_ALLOC_NODE(parser, pm_x_string_node_t); + pm_x_string_node_t *node = PM_NODE_ALLOC(parser, pm_x_string_node_t); *node = (pm_x_string_node_t) { { .type = PM_X_STRING_NODE, .flags = PM_STRING_FLAGS_FROZEN, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = opening->start, .end = closing->end @@ -7753,7 +7907,7 @@ pm_xstring_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_ */ static pm_yield_node_t * pm_yield_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_location_t *lparen_loc, pm_arguments_node_t *arguments, const pm_location_t *rparen_loc) { - pm_yield_node_t *node = PM_ALLOC_NODE(parser, pm_yield_node_t); + pm_yield_node_t *node = PM_NODE_ALLOC(parser, pm_yield_node_t); const uint8_t *end; if (rparen_loc->start != NULL) { @@ -7769,6 +7923,7 @@ pm_yield_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_lo *node = (pm_yield_node_t) { { .type = PM_YIELD_NODE, + .node_id = PM_NODE_IDENTIFY(parser), .location = { .start = keyword->start, .end = end @@ -7783,7 +7938,8 @@ pm_yield_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_lo return node; } -#undef PM_ALLOC_NODE +#undef PM_NODE_ALLOC +#undef PM_NODE_IDENTIFY /** * Check if any of the currently visible scopes contain a local variable @@ -7861,51 +8017,6 @@ pm_parser_local_add_constant(pm_parser_t *parser, const char *start, size_t leng return constant_id; } -/** - * Create a local variable read that is reading the implicit 'it' variable. - */ -static pm_local_variable_read_node_t * -pm_local_variable_read_node_create_it(pm_parser_t *parser, const pm_token_t *name) { - if (parser->current_scope->parameters & PM_SCOPE_PARAMETERS_ORDINARY) { - pm_parser_err_token(parser, name, PM_ERR_IT_NOT_ALLOWED_ORDINARY); - return NULL; - } - - if (parser->current_scope->parameters & PM_SCOPE_PARAMETERS_NUMBERED) { - pm_parser_err_token(parser, name, PM_ERR_IT_NOT_ALLOWED_NUMBERED); - return NULL; - } - - parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_IT; - - pm_constant_id_t name_id = pm_parser_constant_id_constant(parser, "0it", 3); - pm_parser_local_add(parser, name_id, name->start, name->end, 0); - - return pm_local_variable_read_node_create_constant_id(parser, name, name_id, 0, false); -} - -/** - * Convert a `it` variable call node to a node for `it` default parameter. - */ -static pm_node_t * -pm_node_check_it(pm_parser_t *parser, pm_node_t *node) { - if ( - (parser->version != PM_OPTIONS_VERSION_CRUBY_3_3) && - !parser->current_scope->closed && - (parser->current_scope->numbered_parameters != PM_SCOPE_NUMBERED_PARAMETERS_DISALLOWED) && - pm_node_is_it(parser, node) - ) { - pm_local_variable_read_node_t *read = pm_local_variable_read_node_create_it(parser, &parser->previous); - - if (read != NULL) { - pm_node_destroy(parser, node); - node = (pm_node_t *) read; - } - } - - return node; -} - /** * Add a parameter name to the current scope and check whether the name of the * parameter is unique or not. @@ -7941,6 +8052,7 @@ pm_parser_scope_pop(pm_parser_t *parser) { pm_scope_t *scope = parser->current_scope; parser->current_scope = scope->previous; pm_locals_free(&scope->locals); + pm_node_list_free(&scope->implicit_parameters); xfree(scope); } @@ -8012,7 +8124,7 @@ pm_do_loop_stack_p(pm_parser_t *parser) { * is beyond the end of the source then return '\0'. */ static inline uint8_t -peek_at(pm_parser_t *parser, const uint8_t *cursor) { +peek_at(const pm_parser_t *parser, const uint8_t *cursor) { if (cursor < parser->end) { return *cursor; } else { @@ -8035,7 +8147,7 @@ peek_offset(pm_parser_t *parser, ptrdiff_t offset) { * that position is beyond the end of the source then return '\0'. */ static inline uint8_t -peek(pm_parser_t *parser) { +peek(const pm_parser_t *parser) { return peek_at(parser, parser->current.end); } @@ -8100,6 +8212,14 @@ next_newline(const uint8_t *cursor, ptrdiff_t length) { return memchr(cursor, '\n', (size_t) length); } +/** + * This is equivalent to the predicate of warn_balanced in CRuby. + */ +static inline bool +ambiguous_operator_p(const pm_parser_t *parser, bool space_seen) { + return !lex_state_p(parser, PM_LEX_STATE_CLASS | PM_LEX_STATE_DOT | PM_LEX_STATE_FNAME | PM_LEX_STATE_ENDFN) && space_seen && !pm_char_is_whitespace(peek(parser)); +} + /** * Here we're going to check if this is a "magic" comment, and perform whatever * actions are necessary for it here. @@ -8177,16 +8297,24 @@ parser_lex_magic_comment_encoding(pm_parser_t *parser) { } } +typedef enum { + PM_MAGIC_COMMENT_BOOLEAN_VALUE_TRUE, + PM_MAGIC_COMMENT_BOOLEAN_VALUE_FALSE, + PM_MAGIC_COMMENT_BOOLEAN_VALUE_INVALID +} pm_magic_comment_boolean_value_t; + /** * Check if this is a magic comment that includes the frozen_string_literal * pragma. If it does, set that field on the parser. */ -static void -parser_lex_magic_comment_frozen_string_literal_value(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) { - if ((start + 4 <= end) && pm_strncasecmp(start, (const uint8_t *) "true", 4) == 0) { - parser->frozen_string_literal = PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED; - } else if ((start + 5 <= end) && pm_strncasecmp(start, (const uint8_t *) "false", 5) == 0) { - parser->frozen_string_literal = PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED; +static pm_magic_comment_boolean_value_t +parser_lex_magic_comment_boolean_value(const uint8_t *value_start, uint32_t value_length) { + if (value_length == 4 && pm_strncasecmp(value_start, (const uint8_t *) "true", 4) == 0) { + return PM_MAGIC_COMMENT_BOOLEAN_VALUE_TRUE; + } else if (value_length == 5 && pm_strncasecmp(value_start, (const uint8_t *) "false", 5) == 0) { + return PM_MAGIC_COMMENT_BOOLEAN_VALUE_FALSE; + } else { + return PM_MAGIC_COMMENT_BOOLEAN_VALUE_INVALID; } } @@ -8275,6 +8403,7 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) { if (*cursor == '\\' && (cursor + 1 < end)) cursor++; } value_end = cursor; + if (*cursor == '"') cursor++; } else { value_start = cursor; while (cursor < end && *cursor != '"' && *cursor != ';' && !pm_char_is_whitespace(*cursor)) cursor++; @@ -8292,32 +8421,32 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) { // underscores. We only need to do this if there _is_ a dash in the key. pm_string_t key; const size_t key_length = (size_t) (key_end - key_start); - const uint8_t *dash = pm_memchr(key_start, '-', (size_t) key_length, parser->encoding_changed, parser->encoding); + const uint8_t *dash = pm_memchr(key_start, '-', key_length, parser->encoding_changed, parser->encoding); if (dash == NULL) { pm_string_shared_init(&key, key_start, key_end); } else { - size_t width = (size_t) (key_end - key_start); - uint8_t *buffer = xmalloc(width); + uint8_t *buffer = xmalloc(key_length); if (buffer == NULL) break; - memcpy(buffer, key_start, width); + memcpy(buffer, key_start, key_length); buffer[dash - key_start] = '_'; while ((dash = pm_memchr(dash + 1, '-', (size_t) (key_end - dash - 1), parser->encoding_changed, parser->encoding)) != NULL) { buffer[dash - key_start] = '_'; } - pm_string_owned_init(&key, buffer, width); + pm_string_owned_init(&key, buffer, key_length); } // Finally, we can start checking the key against the list of known // magic comment keys, and potentially change state based on that. const uint8_t *key_source = pm_string_source(&key); + uint32_t value_length = (uint32_t) (value_end - value_start); // We only want to attempt to compare against encoding comments if it's // the first line in the file (or the second in the case of a shebang). - if (parser->current.start == parser->encoding_comment_start) { + if (parser->current.start == parser->encoding_comment_start && !parser->encoding_locked) { if ( (key_length == 8 && pm_strncasecmp(key_source, (const uint8_t *) "encoding", 8) == 0) || (key_length == 6 && pm_strncasecmp(key_source, (const uint8_t *) "coding", 6) == 0) @@ -8326,35 +8455,82 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) { } } - // We only want to handle frozen string literal comments if it's before - // any semantic tokens have been seen. - if (key_length == 21 && pm_strncasecmp(key_source, (const uint8_t *) "frozen_string_literal", 21) == 0) { - if (semantic_token_seen) { - pm_parser_warn_token(parser, &parser->current, PM_WARN_IGNORED_FROZEN_STRING_LITERAL); - } else { - parser_lex_magic_comment_frozen_string_literal_value(parser, value_start, value_end); + if (key_length == 11) { + if (pm_strncasecmp(key_source, (const uint8_t *) "warn_indent", 11) == 0) { + switch (parser_lex_magic_comment_boolean_value(value_start, value_length)) { + case PM_MAGIC_COMMENT_BOOLEAN_VALUE_INVALID: + PM_PARSER_WARN_TOKEN_FORMAT( + parser, + parser->current, + PM_WARN_INVALID_MAGIC_COMMENT_VALUE, + (int) key_length, + (const char *) key_source, + (int) value_length, + (const char *) value_start + ); + break; + case PM_MAGIC_COMMENT_BOOLEAN_VALUE_FALSE: + parser->warn_mismatched_indentation = false; + break; + case PM_MAGIC_COMMENT_BOOLEAN_VALUE_TRUE: + parser->warn_mismatched_indentation = true; + break; + } } - } - - // If we have hit a ractor pragma, attempt to lex that. - uint32_t value_length = (uint32_t) (value_end - value_start); - if (key_length == 24 && pm_strncasecmp(key_source, (const uint8_t *) "shareable_constant_value", 24) == 0) { - if (value_length == 4 && pm_strncasecmp(value_start, (const uint8_t *) "none", 4) == 0) { - pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_NONE); - } else if (value_length == 7 && pm_strncasecmp(value_start, (const uint8_t *) "literal", 7) == 0) { - pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_LITERAL); - } else if (value_length == 23 && pm_strncasecmp(value_start, (const uint8_t *) "experimental_everything", 23) == 0) { - pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING); - } else if (value_length == 17 && pm_strncasecmp(value_start, (const uint8_t *) "experimental_copy", 17) == 0) { - pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY); - } else { - PM_PARSER_WARN_TOKEN_FORMAT( - parser, - parser->current, - PM_WARN_INVALID_SHAREABLE_CONSTANT_VALUE, - (int) value_length, - (const char *) value_start - ); + } else if (key_length == 21) { + if (pm_strncasecmp(key_source, (const uint8_t *) "frozen_string_literal", 21) == 0) { + // We only want to handle frozen string literal comments if it's + // before any semantic tokens have been seen. + if (semantic_token_seen) { + pm_parser_warn_token(parser, &parser->current, PM_WARN_IGNORED_FROZEN_STRING_LITERAL); + } else { + switch (parser_lex_magic_comment_boolean_value(value_start, value_length)) { + case PM_MAGIC_COMMENT_BOOLEAN_VALUE_INVALID: + PM_PARSER_WARN_TOKEN_FORMAT( + parser, + parser->current, + PM_WARN_INVALID_MAGIC_COMMENT_VALUE, + (int) key_length, + (const char *) key_source, + (int) value_length, + (const char *) value_start + ); + break; + case PM_MAGIC_COMMENT_BOOLEAN_VALUE_FALSE: + parser->frozen_string_literal = PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED; + break; + case PM_MAGIC_COMMENT_BOOLEAN_VALUE_TRUE: + parser->frozen_string_literal = PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED; + break; + } + } + } + } else if (key_length == 24) { + if (pm_strncasecmp(key_source, (const uint8_t *) "shareable_constant_value", 24) == 0) { + const uint8_t *cursor = parser->current.start; + while ((cursor > parser->start) && ((cursor[-1] == ' ') || (cursor[-1] == '\t'))) cursor--; + + if (!((cursor == parser->start) || (cursor[-1] == '\n'))) { + pm_parser_warn_token(parser, &parser->current, PM_WARN_SHAREABLE_CONSTANT_VALUE_LINE); + } else if (value_length == 4 && pm_strncasecmp(value_start, (const uint8_t *) "none", 4) == 0) { + pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_NONE); + } else if (value_length == 7 && pm_strncasecmp(value_start, (const uint8_t *) "literal", 7) == 0) { + pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_LITERAL); + } else if (value_length == 23 && pm_strncasecmp(value_start, (const uint8_t *) "experimental_everything", 23) == 0) { + pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING); + } else if (value_length == 17 && pm_strncasecmp(value_start, (const uint8_t *) "experimental_copy", 17) == 0) { + pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY); + } else { + PM_PARSER_WARN_TOKEN_FORMAT( + parser, + parser->current, + PM_WARN_INVALID_MAGIC_COMMENT_VALUE, + (int) key_length, + (const char *) key_source, + (int) value_length, + (const char *) value_start + ); + } } } @@ -8368,7 +8544,7 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) { magic_comment->key_start = key_start; magic_comment->value_start = value_start; magic_comment->key_length = (uint32_t) key_length; - magic_comment->value_length = (uint32_t) (value_end - value_start); + magic_comment->value_length = value_length; pm_list_append(&parser->magic_comment_list, (pm_list_node_t *) magic_comment); } } @@ -8386,6 +8562,7 @@ context_terminator(pm_context_t context, pm_token_t *token) { case PM_CONTEXT_MAIN: case PM_CONTEXT_DEF_PARAMS: case PM_CONTEXT_DEFINED: + case PM_CONTEXT_MULTI_TARGET: case PM_CONTEXT_TERNARY: case PM_CONTEXT_RESCUE_MODIFIER: return token->type == PM_TOKEN_EOF; @@ -8413,6 +8590,8 @@ context_terminator(pm_context_t context, pm_token_t *token) { case PM_CONTEXT_MODULE_ENSURE: case PM_CONTEXT_SCLASS_ENSURE: return token->type == PM_TOKEN_KEYWORD_END; + case PM_CONTEXT_LOOP_PREDICATE: + return token->type == PM_TOKEN_KEYWORD_DO || token->type == PM_TOKEN_KEYWORD_THEN; case PM_CONTEXT_FOR_INDEX: return token->type == PM_TOKEN_KEYWORD_IN; case PM_CONTEXT_CASE_WHEN: @@ -8585,8 +8764,10 @@ context_human(pm_context_t context) { case PM_CONTEXT_IF: return "if statement"; case PM_CONTEXT_LAMBDA_BRACES: return "'{'..'}' lambda block"; case PM_CONTEXT_LAMBDA_DO_END: return "'do'..'end' lambda block"; + case PM_CONTEXT_LOOP_PREDICATE: return "loop predicate"; case PM_CONTEXT_MAIN: return "top level context"; case PM_CONTEXT_MODULE: return "module definition"; + case PM_CONTEXT_MULTI_TARGET: return "multiple targets"; case PM_CONTEXT_PARENS: return "parentheses"; case PM_CONTEXT_POSTEXE: return "'END' block"; case PM_CONTEXT_PREDICATE: return "predicate"; @@ -8796,6 +8977,16 @@ lex_numeric_prefix(pm_parser_t *parser, bool* seen_e) { type = lex_optional_float_suffix(parser, seen_e); } + // At this point we have a completed number, but we want to provide the user + // with a good experience if they put an additional .xxx fractional + // component on the end, so we'll check for that here. + if (peek_offset(parser, 0) == '.' && pm_char_is_decimal_digit(peek_offset(parser, 1))) { + const uint8_t *fraction_start = parser->current.end; + const uint8_t *fraction_end = parser->current.end + 2; + fraction_end += pm_strspn_decimal_digit(fraction_end, parser->end - fraction_end); + pm_parser_err(parser, fraction_start, fraction_end, PM_ERR_INVALID_NUMBER_FRACTION); + } + return type; } @@ -8851,6 +9042,10 @@ lex_global_variable(pm_parser_t *parser) { return PM_TOKEN_GLOBAL_VARIABLE; } + // True if multiple characters are allowed after the declaration of the + // global variable. Not true when it starts with "$-". + bool allow_multiple = true; + switch (*parser->current.end) { case '~': // $~: match-data case '*': // $*: argv @@ -8909,6 +9104,7 @@ lex_global_variable(pm_parser_t *parser) { case '-': parser->current.end++; + allow_multiple = false; /* fallthrough */ default: { size_t width; @@ -8916,7 +9112,7 @@ lex_global_variable(pm_parser_t *parser) { if ((width = char_is_identifier(parser, parser->current.end)) > 0) { do { parser->current.end += width; - } while (parser->current.end < parser->end && (width = char_is_identifier(parser, parser->current.end)) > 0); + } while (allow_multiple && parser->current.end < parser->end && (width = char_is_identifier(parser, parser->current.end)) > 0); } else if (pm_char_is_whitespace(peek(parser))) { // If we get here, then we have a $ followed by whitespace, // which is not allowed. @@ -8925,8 +9121,8 @@ lex_global_variable(pm_parser_t *parser) { // If we get here, then we have a $ followed by something that // isn't recognized as a global variable. pm_diagnostic_id_t diag_id = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_ERR_INVALID_VARIABLE_GLOBAL_3_3 : PM_ERR_INVALID_VARIABLE_GLOBAL; - size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end); - PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, diag_id, (int) ((parser->current.end + width) - parser->current.start), (const char *) parser->current.start); + const uint8_t *end = parser->current.end + parser->encoding->char_width(parser->current.end, parser->end - parser->current.end); + PM_PARSER_ERR_FORMAT(parser, parser->current.start, end, diag_id, (int) (end - parser->current.start), (const char *) parser->current.start); } return PM_TOKEN_GLOBAL_VARIABLE; @@ -9297,12 +9493,20 @@ escape_hexadecimal_digit(const uint8_t value) { * validated. */ static inline uint32_t -escape_unicode(const uint8_t *string, size_t length) { +escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length) { uint32_t value = 0; for (size_t index = 0; index < length; index++) { if (index != 0) value <<= 4; value |= escape_hexadecimal_digit(string[index]); } + + // Here we're going to verify that the value is actually a valid Unicode + // codepoint and not a surrogate pair. + if (value >= 0xD800 && value <= 0xDFFF) { + pm_parser_err(parser, string, string + length, PM_ERR_ESCAPE_INVALID_UNICODE); + return 0xFFFD; + } + return value; } @@ -9311,7 +9515,7 @@ escape_unicode(const uint8_t *string, size_t length) { */ static inline uint8_t escape_byte(uint8_t value, const uint8_t flags) { - if (flags & PM_ESCAPE_FLAG_CONTROL) value &= 0x1f; + if (flags & PM_ESCAPE_FLAG_CONTROL) value &= 0x9f; if (flags & PM_ESCAPE_FLAG_META) value |= 0x80; return value; } @@ -9411,22 +9615,7 @@ escape_write_escape_encoded(pm_parser_t *parser, pm_buffer_t *buffer) { static inline void escape_write_byte(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expression_buffer, uint8_t flags, uint8_t byte) { if (flags & PM_ESCAPE_FLAG_REGEXP) { - pm_buffer_append_bytes(regular_expression_buffer, (const uint8_t *) "\\x", 2); - - uint8_t byte1 = (uint8_t) ((byte >> 4) & 0xF); - uint8_t byte2 = (uint8_t) (byte & 0xF); - - if (byte1 >= 0xA) { - pm_buffer_append_byte(regular_expression_buffer, (uint8_t) ((byte1 - 0xA) + 'A')); - } else { - pm_buffer_append_byte(regular_expression_buffer, (uint8_t) (byte1 + '0')); - } - - if (byte2 >= 0xA) { - pm_buffer_append_byte(regular_expression_buffer, (uint8_t) (byte2 - 0xA + 'A')); - } else { - pm_buffer_append_byte(regular_expression_buffer, (uint8_t) (byte2 + '0')); - } + pm_buffer_append_format(regular_expression_buffer, "\\x%02X", byte); } escape_write_byte_encoded(parser, buffer, byte); @@ -9461,57 +9650,57 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre switch (peek(parser)) { case '\\': { parser->current.end++; - escape_write_byte_encoded(parser, buffer, escape_byte('\\', flags)); + escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte('\\', flags)); return; } case '\'': { parser->current.end++; - escape_write_byte_encoded(parser, buffer, escape_byte('\'', flags)); + escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte('\'', flags)); return; } case 'a': { parser->current.end++; - escape_write_byte_encoded(parser, buffer, escape_byte('\a', flags)); + escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte('\a', flags)); return; } case 'b': { parser->current.end++; - escape_write_byte_encoded(parser, buffer, escape_byte('\b', flags)); + escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte('\b', flags)); return; } case 'e': { parser->current.end++; - escape_write_byte_encoded(parser, buffer, escape_byte('\033', flags)); + escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte('\033', flags)); return; } case 'f': { parser->current.end++; - escape_write_byte_encoded(parser, buffer, escape_byte('\f', flags)); + escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte('\f', flags)); return; } case 'n': { parser->current.end++; - escape_write_byte_encoded(parser, buffer, escape_byte('\n', flags)); + escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte('\n', flags)); return; } case 'r': { parser->current.end++; - escape_write_byte_encoded(parser, buffer, escape_byte('\r', flags)); + escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte('\r', flags)); return; } case 's': { parser->current.end++; - escape_write_byte_encoded(parser, buffer, escape_byte(' ', flags)); + escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(' ', flags)); return; } case 't': { parser->current.end++; - escape_write_byte_encoded(parser, buffer, escape_byte('\t', flags)); + escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte('\t', flags)); return; } case 'v': { parser->current.end++; - escape_write_byte_encoded(parser, buffer, escape_byte('\v', flags)); + escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte('\v', flags)); return; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { @@ -9528,7 +9717,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre } } - escape_write_byte_encoded(parser, buffer, value); + escape_write_byte(parser, buffer, regular_expression_buffer, flags, value); return; } case 'x': { @@ -9547,8 +9736,13 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre parser->current.end++; } + value = escape_byte(value, flags); if (flags & PM_ESCAPE_FLAG_REGEXP) { - pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end - start)); + if (flags & (PM_ESCAPE_FLAG_CONTROL | PM_ESCAPE_FLAG_META)) { + pm_buffer_append_format(regular_expression_buffer, "\\x%02X", value); + } else { + pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end - start)); + } } escape_write_byte_encoded(parser, buffer, value); @@ -9562,11 +9756,27 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre const uint8_t *start = parser->current.end - 1; parser->current.end++; - if (peek(parser) == '{') { + if (parser->current.end == parser->end) { + const uint8_t *start = parser->current.end - 2; + PM_PARSER_ERR_FORMAT(parser, start, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE_SHORT, 2, start); + } else if (peek(parser) == '{') { const uint8_t *unicode_codepoints_start = parser->current.end - 2; - parser->current.end++; - parser->current.end += pm_strspn_whitespace(parser->current.end, parser->end - parser->current.end); + + size_t whitespace; + while (true) { + if ((whitespace = pm_strspn_whitespace(parser->current.end, parser->end - parser->current.end)) > 0) { + parser->current.end += whitespace; + } else if (peek(parser) == '\\' && peek_offset(parser, 1) == 'n') { + // This is super hacky, but it gets us nicer error + // messages because we can still pass it off to the + // regular expression engine even if we hit an + // unterminated regular expression. + parser->current.end += 2; + } else { + break; + } + } const uint8_t *extra_codepoints_start = NULL; int codepoints_count = 0; @@ -9580,17 +9790,27 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre pm_parser_err(parser, unicode_start, unicode_start + hexadecimal_length, PM_ERR_ESCAPE_INVALID_UNICODE_LONG); } else if (hexadecimal_length == 0) { // there are not hexadecimal characters - pm_parser_err(parser, unicode_start, unicode_start + hexadecimal_length, PM_ERR_ESCAPE_INVALID_UNICODE); - return; - } - parser->current.end += hexadecimal_length; + if (flags & PM_ESCAPE_FLAG_REGEXP) { + // If this is a regular expression, we are going to + // let the regular expression engine handle this + // error instead of us. + pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end - start)); + } else { + pm_parser_err(parser, parser->current.end, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE); + pm_parser_err(parser, parser->current.end, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE_TERM); + } + + return; + } + + parser->current.end += hexadecimal_length; codepoints_count++; if (flags & PM_ESCAPE_FLAG_SINGLE && codepoints_count == 2) { extra_codepoints_start = unicode_start; } - uint32_t value = escape_unicode(unicode_start, hexadecimal_length); + uint32_t value = escape_unicode(parser, unicode_start, hexadecimal_length); escape_write_unicode(parser, buffer, flags, unicode_start, parser->current.end, value); parser->current.end += pm_strspn_whitespace(parser->current.end, parser->end - parser->current.end); @@ -9602,10 +9822,19 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre pm_parser_err(parser, extra_codepoints_start, parser->current.end - 1, PM_ERR_ESCAPE_INVALID_UNICODE_LITERAL); } - if (peek(parser) == '}') { + if (parser->current.end == parser->end) { + PM_PARSER_ERR_FORMAT(parser, start, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE_LIST, (int) (parser->current.end - start), start); + } else if (peek(parser) == '}') { parser->current.end++; } else { - pm_parser_err(parser, unicode_codepoints_start, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE_TERM); + if (flags & PM_ESCAPE_FLAG_REGEXP) { + // If this is a regular expression, we are going to let + // the regular expression engine handle this error + // instead of us. + pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end - start)); + } else { + pm_parser_err(parser, unicode_codepoints_start, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE_TERM); + } } if (flags & PM_ESCAPE_FLAG_REGEXP) { @@ -9614,8 +9843,15 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre } else { size_t length = pm_strspn_hexadecimal_digit(parser->current.end, MIN(parser->end - parser->current.end, 4)); - if (length == 4) { - uint32_t value = escape_unicode(parser->current.end, 4); + if (length == 0) { + if (flags & PM_ESCAPE_FLAG_REGEXP) { + pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end - start)); + } else { + const uint8_t *start = parser->current.end - 2; + PM_PARSER_ERR_FORMAT(parser, start, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE_SHORT, 2, start); + } + } else if (length == 4) { + uint32_t value = escape_unicode(parser, parser->current.end, 4); if (flags & PM_ESCAPE_FLAG_REGEXP) { pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end + 4 - start)); @@ -9625,7 +9861,15 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre parser->current.end += 4; } else { parser->current.end += length; - pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_UNICODE); + + if (flags & PM_ESCAPE_FLAG_REGEXP) { + // If this is a regular expression, we are going to let + // the regular expression engine handle this error + // instead of us. + pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end - start)); + } else { + pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_UNICODE); + } } } @@ -9633,6 +9877,10 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre } case 'c': { parser->current.end++; + if (flags & PM_ESCAPE_FLAG_CONTROL) { + pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT); + } + if (parser->current.end == parser->end) { pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL); return; @@ -9646,11 +9894,13 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; } case '\\': - if (flags & PM_ESCAPE_FLAG_CONTROL) { - pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT); + parser->current.end++; + + if (match(parser, 'u') || match(parser, 'U')) { + pm_parser_err(parser, parser->current.start, parser->current.end, PM_ERR_INVALID_ESCAPE_CHARACTER); return; } - parser->current.end++; + escape_read(parser, buffer, regular_expression_buffer, flags | PM_ESCAPE_FLAG_CONTROL); return; case ' ': @@ -9677,8 +9927,13 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre } case 'C': { parser->current.end++; + if (flags & PM_ESCAPE_FLAG_CONTROL) { + pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT); + } + if (peek(parser) != '-') { - pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL); + size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end); + pm_parser_err(parser, parser->current.start, parser->current.end + width, PM_ERR_ESCAPE_INVALID_CONTROL); return; } @@ -9696,11 +9951,13 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; } case '\\': - if (flags & PM_ESCAPE_FLAG_CONTROL) { - pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT); + parser->current.end++; + + if (match(parser, 'u') || match(parser, 'U')) { + pm_parser_err(parser, parser->current.start, parser->current.end, PM_ERR_INVALID_ESCAPE_CHARACTER); return; } - parser->current.end++; + escape_read(parser, buffer, regular_expression_buffer, flags | PM_ESCAPE_FLAG_CONTROL); return; case ' ': @@ -9715,7 +9972,8 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; default: { if (!char_is_ascii_printable(peeked)) { - pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL); + size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end); + pm_parser_err(parser, parser->current.start, parser->current.end + width, PM_ERR_ESCAPE_INVALID_CONTROL); return; } @@ -9727,8 +9985,13 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre } case 'M': { parser->current.end++; + if (flags & PM_ESCAPE_FLAG_META) { + pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_META_REPEAT); + } + if (peek(parser) != '-') { - pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_META); + size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end); + pm_parser_err(parser, parser->current.start, parser->current.end + width, PM_ERR_ESCAPE_INVALID_META); return; } @@ -9741,11 +10004,13 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre uint8_t peeked = peek(parser); switch (peeked) { case '\\': - if (flags & PM_ESCAPE_FLAG_META) { - pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_META_REPEAT); + parser->current.end++; + + if (match(parser, 'u') || match(parser, 'U')) { + pm_parser_err(parser, parser->current.start, parser->current.end, PM_ERR_INVALID_ESCAPE_CHARACTER); return; } - parser->current.end++; + escape_read(parser, buffer, regular_expression_buffer, flags | PM_ESCAPE_FLAG_META); return; case ' ': @@ -9760,7 +10025,8 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; default: if (!char_is_ascii_printable(peeked)) { - pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_META); + size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end); + pm_parser_err(parser, parser->current.start, parser->current.end + width, PM_ERR_ESCAPE_INVALID_META); return; } @@ -9780,6 +10046,8 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre default: { if (parser->current.end < parser->end) { escape_write_escape_encoded(parser, buffer); + } else { + pm_parser_err_current(parser, PM_ERR_INVALID_ESCAPE_CHARACTER); } return; } @@ -10455,7 +10723,9 @@ parser_lex(pm_parser_t *parser) { // pass and we're at the start of the file, then we need // to do another pass to potentially find other patterns // for encoding comments. - if (length >= 10) parser_lex_magic_comment_encoding(parser); + if (length >= 10 && !parser->encoding_locked) { + parser_lex_magic_comment_encoding(parser); + } } lexed_comment = true; @@ -10721,6 +10991,8 @@ parser_lex(pm_parser_t *parser) { type = PM_TOKEN_USTAR_STAR; } else if (lex_state_beg_p(parser)) { type = PM_TOKEN_USTAR_STAR; + } else if (ambiguous_operator_p(parser, space_seen)) { + PM_PARSER_WARN_TOKEN_FORMAT(parser, parser->current, PM_WARN_AMBIGUOUS_BINARY_OPERATOR, "**", "argument prefix"); } if (lex_state_operator_p(parser)) { @@ -10744,6 +11016,8 @@ parser_lex(pm_parser_t *parser) { type = PM_TOKEN_USTAR; } else if (lex_state_beg_p(parser)) { type = PM_TOKEN_USTAR; + } else if (ambiguous_operator_p(parser, space_seen)) { + PM_PARSER_WARN_TOKEN_FORMAT(parser, parser->current, PM_WARN_AMBIGUOUS_BINARY_OPERATOR, "*", "argument prefix"); } if (lex_state_operator_p(parser)) { @@ -10860,6 +11134,7 @@ parser_lex(pm_parser_t *parser) { // If we have quotes, then we're going to go until we find the // end quote. while ((parser->current.end < parser->end) && quote != (pm_heredoc_quote_t) (*parser->current.end)) { + if (*parser->current.end == '\r' || *parser->current.end == '\n') break; parser->current.end++; } } @@ -10876,12 +11151,14 @@ parser_lex(pm_parser_t *parser) { lex_mode_push(parser, (pm_lex_mode_t) { .mode = PM_LEX_HEREDOC, .as.heredoc = { - .ident_start = ident_start, - .ident_length = ident_length, + .base = { + .ident_start = ident_start, + .ident_length = ident_length, + .quote = quote, + .indent = indent + }, .next_start = parser->current.end, - .quote = quote, - .indent = indent, - .common_whitespace = (size_t) -1, + .common_whitespace = NULL, .line_continuation = false } }); @@ -10894,7 +11171,7 @@ parser_lex(pm_parser_t *parser) { // this is not a valid heredoc declaration. In this case we // will add an error, but we will still return a heredoc // start. - if (!ident_error) pm_parser_err_heredoc_term(parser, parser->lex_modes.current); + if (!ident_error) pm_parser_err_heredoc_term(parser, ident_start, ident_length); body_start = parser->end; } else { // Otherwise, we want to indicate that the body of the @@ -10917,6 +11194,10 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_LESS_LESS_EQUAL); } + if (ambiguous_operator_p(parser, space_seen)) { + PM_PARSER_WARN_TOKEN_FORMAT(parser, parser->current, PM_WARN_AMBIGUOUS_BINARY_OPERATOR, "<<", "here document"); + } + if (lex_state_operator_p(parser)) { lex_state_set(parser, PM_LEX_STATE_ARG); } else { @@ -11026,10 +11307,21 @@ parser_lex(pm_parser_t *parser) { pm_token_type_t type = PM_TOKEN_AMPERSAND; if (lex_state_spcarg_p(parser, space_seen)) { - pm_parser_warn_token(parser, &parser->current, PM_WARN_AMBIGUOUS_PREFIX_AMPERSAND); + if ((peek(parser) != ':') || (peek_offset(parser, 1) == '\0')) { + pm_parser_warn_token(parser, &parser->current, PM_WARN_AMBIGUOUS_PREFIX_AMPERSAND); + } else { + const uint8_t delim = peek_offset(parser, 1); + + if ((delim != '\'') && (delim != '"') && !char_is_identifier(parser, parser->current.end + 1)) { + pm_parser_warn_token(parser, &parser->current, PM_WARN_AMBIGUOUS_PREFIX_AMPERSAND); + } + } + type = PM_TOKEN_UAMPERSAND; } else if (lex_state_beg_p(parser)) { type = PM_TOKEN_UAMPERSAND; + } else if (ambiguous_operator_p(parser, space_seen)) { + PM_PARSER_WARN_TOKEN_FORMAT(parser, parser->current, PM_WARN_AMBIGUOUS_BINARY_OPERATOR, "&", "argument prefix"); } if (lex_state_operator_p(parser)) { @@ -11104,6 +11396,10 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_UPLUS); } + if (ambiguous_operator_p(parser, space_seen)) { + PM_PARSER_WARN_TOKEN_FORMAT(parser, parser->current, PM_WARN_AMBIGUOUS_BINARY_OPERATOR, "+", "unary operator"); + } + lex_state_set(parser, PM_LEX_STATE_BEG); LEX(PM_TOKEN_PLUS); } @@ -11141,6 +11437,10 @@ parser_lex(pm_parser_t *parser) { LEX(pm_char_is_decimal_digit(peek(parser)) ? PM_TOKEN_UMINUS_NUM : PM_TOKEN_UMINUS); } + if (ambiguous_operator_p(parser, space_seen)) { + PM_PARSER_WARN_TOKEN_FORMAT(parser, parser->current, PM_WARN_AMBIGUOUS_BINARY_OPERATOR, "-", "unary operator"); + } + lex_state_set(parser, PM_LEX_STATE_BEG); LEX(PM_TOKEN_MINUS); } @@ -11152,10 +11452,7 @@ parser_lex(pm_parser_t *parser) { if (match(parser, '.')) { if (match(parser, '.')) { // If we're _not_ inside a range within default parameters - if ( - !context_p(parser, PM_CONTEXT_DEFAULT_PARAMS) && - context_p(parser, PM_CONTEXT_DEF_PARAMS) - ) { + if (!context_p(parser, PM_CONTEXT_DEFAULT_PARAMS) && context_p(parser, PM_CONTEXT_DEF_PARAMS)) { if (lex_state_p(parser, PM_LEX_STATE_END)) { lex_state_set(parser, PM_LEX_STATE_BEG); } else { @@ -11239,6 +11536,10 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_REGEXP_BEGIN); } + if (ambiguous_operator_p(parser, space_seen)) { + PM_PARSER_WARN_TOKEN_FORMAT(parser, parser->current, PM_WARN_AMBIGUOUS_BINARY_OPERATOR, "/", "regexp literal"); + } + if (lex_state_operator_p(parser)) { lex_state_set(parser, PM_LEX_STATE_ARG); } else { @@ -11274,7 +11575,7 @@ parser_lex(pm_parser_t *parser) { // operator because we don't want to move into the string // lex mode unnecessarily. if ((lex_state_beg_p(parser) || lex_state_arg_p(parser)) && (parser->current.end >= parser->end)) { - pm_parser_err_current(parser, PM_ERR_INVALID_PERCENT); + pm_parser_err_current(parser, PM_ERR_INVALID_PERCENT_EOF); LEX(PM_TOKEN_PERCENT); } @@ -11293,10 +11594,7 @@ parser_lex(pm_parser_t *parser) { const uint8_t delimiter = pm_lex_percent_delimiter(parser); lex_mode_push_string(parser, true, false, lex_mode_incrementor(delimiter), lex_mode_terminator(delimiter)); - - if (parser->current.end < parser->end) { - LEX(PM_TOKEN_STRING_BEGIN); - } + LEX(PM_TOKEN_STRING_BEGIN); } // Delimiters for %-literals cannot be alphanumeric. We @@ -11423,6 +11721,10 @@ parser_lex(pm_parser_t *parser) { } } + if (ambiguous_operator_p(parser, space_seen)) { + PM_PARSER_WARN_TOKEN_FORMAT(parser, parser->current, PM_WARN_AMBIGUOUS_BINARY_OPERATOR, "%", "string literal"); + } + lex_state_set(parser, lex_state_operator_p(parser) ? PM_LEX_STATE_ARG : PM_LEX_STATE_BEG); LEX(PM_TOKEN_PERCENT); } @@ -12212,6 +12514,7 @@ parser_lex(pm_parser_t *parser) { // Now let's grab the information about the identifier off of the // current lex mode. pm_lex_mode_t *lex_mode = parser->lex_modes.current; + pm_heredoc_lex_mode_t *heredoc_lex_mode = &lex_mode->as.heredoc.base; bool line_continuation = lex_mode->as.heredoc.line_continuation; lex_mode->as.heredoc.line_continuation = false; @@ -12221,21 +12524,23 @@ parser_lex(pm_parser_t *parser) { // terminator) but still continue parsing so that content after the // declaration of the heredoc can be parsed. if (parser->current.end >= parser->end) { - pm_parser_err_heredoc_term(parser, lex_mode); + pm_parser_err_heredoc_term(parser, heredoc_lex_mode->ident_start, heredoc_lex_mode->ident_length); parser->next_start = lex_mode->as.heredoc.next_start; parser->heredoc_end = parser->current.end; lex_state_set(parser, PM_LEX_STATE_END); + lex_mode_pop(parser); LEX(PM_TOKEN_HEREDOC_END); } - const uint8_t *ident_start = lex_mode->as.heredoc.ident_start; - size_t ident_length = lex_mode->as.heredoc.ident_length; + const uint8_t *ident_start = heredoc_lex_mode->ident_start; + size_t ident_length = heredoc_lex_mode->ident_length; // If we are immediately following a newline and we have hit the // terminator, then we need to return the ending of the heredoc. - if (!line_continuation && current_token_starts_line(parser)) { + if (current_token_starts_line(parser)) { const uint8_t *start = parser->current.start; - if (start + ident_length <= parser->end) { + + if (!line_continuation && (start + ident_length <= parser->end)) { const uint8_t *newline = next_newline(start, parser->end - start); const uint8_t *ident_end = newline; const uint8_t *terminator_end = newline; @@ -12253,10 +12558,7 @@ parser_lex(pm_parser_t *parser) { const uint8_t *terminator_start = ident_end - ident_length; const uint8_t *cursor = start; - if ( - lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_DASH || - lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE - ) { + if (heredoc_lex_mode->indent == PM_HEREDOC_INDENT_DASH || heredoc_lex_mode->indent == PM_HEREDOC_INDENT_TILDE) { while (cursor < terminator_start && pm_char_is_inline_whitespace(*cursor)) { cursor++; } @@ -12279,17 +12581,19 @@ parser_lex(pm_parser_t *parser) { } lex_state_set(parser, PM_LEX_STATE_END); + lex_mode_pop(parser); LEX(PM_TOKEN_HEREDOC_END); } } - size_t whitespace = pm_heredoc_strspn_inline_whitespace(parser, &start, lex_mode->as.heredoc.indent); + size_t whitespace = pm_heredoc_strspn_inline_whitespace(parser, &start, heredoc_lex_mode->indent); if ( - lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE && - (lex_mode->as.heredoc.common_whitespace > whitespace) && + heredoc_lex_mode->indent == PM_HEREDOC_INDENT_TILDE && + lex_mode->as.heredoc.common_whitespace != NULL && + (*lex_mode->as.heredoc.common_whitespace > whitespace) && peek_at(parser, start) != '\n' ) { - lex_mode->as.heredoc.common_whitespace = whitespace; + *lex_mode->as.heredoc.common_whitespace = whitespace; } } @@ -12298,7 +12602,7 @@ parser_lex(pm_parser_t *parser) { // strpbrk to find the first of these characters. uint8_t breakpoints[] = "\r\n\\#"; - pm_heredoc_quote_t quote = lex_mode->as.heredoc.quote; + pm_heredoc_quote_t quote = heredoc_lex_mode->quote; if (quote == PM_HEREDOC_QUOTE_SINGLE) { breakpoints[3] = '\0'; } @@ -12361,8 +12665,7 @@ parser_lex(pm_parser_t *parser) { // leading whitespace if we have a - or ~ heredoc. const uint8_t *cursor = start; - if (lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_DASH || - lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE) { + if (heredoc_lex_mode->indent == PM_HEREDOC_INDENT_DASH || heredoc_lex_mode->indent == PM_HEREDOC_INDENT_TILDE) { while (cursor < terminator_start && pm_char_is_inline_whitespace(*cursor)) { cursor++; } @@ -12378,24 +12681,21 @@ parser_lex(pm_parser_t *parser) { } } - size_t whitespace = pm_heredoc_strspn_inline_whitespace(parser, &start, lex_mode->as.heredoc.indent); + size_t whitespace = pm_heredoc_strspn_inline_whitespace(parser, &start, lex_mode->as.heredoc.base.indent); // If we have hit a newline that is followed by a valid // terminator, then we need to return the content of the // heredoc here as string content. Then, the next time a // token is lexed, it will match again and return the // end of the heredoc. - if (lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE) { - if ((lex_mode->as.heredoc.common_whitespace > whitespace) && peek_at(parser, start) != '\n') { - lex_mode->as.heredoc.common_whitespace = whitespace; + if (lex_mode->as.heredoc.base.indent == PM_HEREDOC_INDENT_TILDE) { + if ((lex_mode->as.heredoc.common_whitespace != NULL) && (*lex_mode->as.heredoc.common_whitespace > whitespace) && peek_at(parser, start) != '\n') { + *lex_mode->as.heredoc.common_whitespace = whitespace; } parser->current.end = breakpoint + 1; - - if (!was_line_continuation) { - pm_token_buffer_flush(parser, &token_buffer); - LEX(PM_TOKEN_STRING_CONTENT); - } + pm_token_buffer_flush(parser, &token_buffer); + LEX(PM_TOKEN_STRING_CONTENT); } // Otherwise we hit a newline and it wasn't followed by @@ -12457,7 +12757,7 @@ parser_lex(pm_parser_t *parser) { // If we are in a tilde here, we should // break out of the loop and return the // string content. - if (lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE) { + if (heredoc_lex_mode->indent == PM_HEREDOC_INDENT_TILDE) { const uint8_t *end = parser->current.end; pm_newline_list_append(&parser->newline_list, end); @@ -12683,7 +12983,7 @@ pm_binding_powers_t pm_binding_powers[PM_TOKEN_MAXIMUM] = { [PM_TOKEN_PERCENT] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_FACTOR), [PM_TOKEN_SLASH] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_FACTOR), [PM_TOKEN_STAR] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_FACTOR), - [PM_TOKEN_USTAR] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_FACTOR), + [PM_TOKEN_USTAR] = RIGHT_ASSOCIATIVE_UNARY(PM_BINDING_POWER_FACTOR), // -@ [PM_TOKEN_UMINUS] = RIGHT_ASSOCIATIVE_UNARY(PM_BINDING_POWER_UMINUS), @@ -12865,28 +13165,26 @@ expect3(pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, pm_to * lex mode accordingly. */ static void -expect1_heredoc_term(pm_parser_t *parser, pm_lex_mode_t *lex_mode) { +expect1_heredoc_term(pm_parser_t *parser, const uint8_t *ident_start, size_t ident_length) { if (match1(parser, PM_TOKEN_HEREDOC_END)) { - lex_mode_pop(parser); parser_lex(parser); } else { - pm_parser_err_heredoc_term(parser, lex_mode); - lex_mode_pop(parser); + pm_parser_err_heredoc_term(parser, ident_start, ident_length); parser->previous.start = parser->previous.end; parser->previous.type = PM_TOKEN_MISSING; } } static pm_node_t * -parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id); +parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth); /** * This is a wrapper of parse_expression, which also checks whether the * resulting node is a value expression. */ static pm_node_t * -parse_value_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) { - pm_node_t *node = parse_expression(parser, binding_power, accepts_command_call, diag_id); +parse_value_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth) { + pm_node_t *node = parse_expression(parser, binding_power, accepts_command_call, accepts_label, diag_id, depth); pm_assert_value_expression(parser, node); return node; } @@ -12970,14 +13268,14 @@ token_begins_expression_p(pm_token_type_t type) { * prefixed by the * operator. */ static pm_node_t * -parse_starred_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) { +parse_starred_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id, uint16_t depth) { if (accept1(parser, PM_TOKEN_USTAR)) { pm_token_t operator = parser->previous; - pm_node_t *expression = parse_value_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR); + pm_node_t *expression = parse_value_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); return (pm_node_t *) pm_splat_node_create(parser, &operator, expression); } - return parse_value_expression(parser, binding_power, accepts_command_call, diag_id); + return parse_value_expression(parser, binding_power, accepts_command_call, false, diag_id, depth); } /** @@ -13030,11 +13328,40 @@ parse_unwriteable_target(pm_parser_t *parser, pm_node_t *target) { return (pm_node_t *) result; } +/** + * When an implicit local variable is written to or targeted, it becomes a + * regular, named local variable. This function removes it from the list of + * implicit parameters when that happens. + */ +static void +parse_target_implicit_parameter(pm_parser_t *parser, pm_node_t *node) { + pm_node_list_t *implicit_parameters = &parser->current_scope->implicit_parameters; + + for (size_t index = 0; index < implicit_parameters->size; index++) { + if (implicit_parameters->nodes[index] == node) { + // If the node is not the last one in the list, we need to shift the + // remaining nodes down to fill the gap. This is extremely unlikely + // to happen. + if (index != implicit_parameters->size - 1) { + memcpy(&implicit_parameters->nodes[index], &implicit_parameters->nodes[index + 1], (implicit_parameters->size - index - 1) * sizeof(pm_node_t *)); + } + + implicit_parameters->size--; + break; + } + } +} + /** * Convert the given node into a valid target node. + * + * @param multiple Whether or not this target is part of a larger set of + * targets. If it is, then the &. operator is not allowed. + * @param splat Whether or not this target is a child of a splat target. If it + * is, then fewer patterns are allowed. */ static pm_node_t * -parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple) { +parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple, bool splat_parent) { switch (PM_NODE_TYPE(target)) { case PM_MISSING_NODE: return target; @@ -13080,7 +13407,10 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple) { target->type = PM_GLOBAL_VARIABLE_TARGET_NODE; return target; case PM_LOCAL_VARIABLE_READ_NODE: { - pm_refute_numbered_parameter(parser, target->location.start, target->location.end); + if (pm_token_is_numbered_parameter(target->location.start, target->location.end)) { + PM_PARSER_ERR_FORMAT(parser, target->location.start, target->location.end, PM_ERR_PARAMETER_NUMBERED_RESERVED, target->location.start); + parse_target_implicit_parameter(parser, target); + } const pm_local_variable_read_node_t *cast = (const pm_local_variable_read_node_t *) target; uint32_t name = cast->name; @@ -13092,17 +13422,32 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple) { return target; } + case PM_IT_LOCAL_VARIABLE_READ_NODE: { + pm_constant_id_t name = pm_parser_local_add_constant(parser, "it", 2); + pm_node_t *node = (pm_node_t *) pm_local_variable_target_node_create(parser, &target->location, name, 0); + + parse_target_implicit_parameter(parser, target); + pm_node_destroy(parser, target); + + return node; + } case PM_INSTANCE_VARIABLE_READ_NODE: assert(sizeof(pm_instance_variable_target_node_t) == sizeof(pm_instance_variable_read_node_t)); target->type = PM_INSTANCE_VARIABLE_TARGET_NODE; return target; case PM_MULTI_TARGET_NODE: + if (splat_parent) { + // Multi target is not accepted in all positions. If this is one + // of them, then we need to add an error. + pm_parser_err_node(parser, target, PM_ERR_WRITE_TARGET_UNEXPECTED); + } + return target; case PM_SPLAT_NODE: { pm_splat_node_t *splat = (pm_splat_node_t *) target; if (splat->expression != NULL) { - splat->expression = parse_target(parser, splat->expression, multiple); + splat->expression = parse_target(parser, splat->expression, multiple, true); } return (pm_node_t *) splat; @@ -13172,9 +13517,10 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple) { */ static pm_node_t * parse_target_validate(pm_parser_t *parser, pm_node_t *target, bool multiple) { - pm_node_t *result = parse_target(parser, target, multiple); + pm_node_t *result = parse_target(parser, target, multiple, false); - // Ensure that we have one of an =, an 'in' in for indexes, and a ')' in parens after the targets. + // Ensure that we have one of an =, an 'in' in for indexes, and a ')' in + // parens after the targets. if ( !match1(parser, PM_TOKEN_EQUAL) && !(context_p(parser, PM_CONTEXT_FOR_INDEX) && match1(parser, PM_TOKEN_KEYWORD_IN)) && @@ -13244,18 +13590,34 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod return (pm_node_t *) node; } case PM_LOCAL_VARIABLE_READ_NODE: { - pm_refute_numbered_parameter(parser, target->location.start, target->location.end); pm_local_variable_read_node_t *local_read = (pm_local_variable_read_node_t *) target; pm_constant_id_t name = local_read->name; + pm_location_t name_loc = target->location; + uint32_t depth = local_read->depth; - pm_locals_unread(&pm_parser_scope_find(parser, depth)->locals, name); + pm_scope_t *scope = pm_parser_scope_find(parser, depth); - pm_location_t name_loc = target->location; + if (pm_token_is_numbered_parameter(target->location.start, target->location.end)) { + pm_diagnostic_id_t diag_id = (scope->parameters & PM_SCOPE_PARAMETERS_NUMBERED_FOUND) ? PM_ERR_EXPRESSION_NOT_WRITABLE_NUMBERED : PM_ERR_PARAMETER_NUMBERED_RESERVED; + PM_PARSER_ERR_FORMAT(parser, target->location.start, target->location.end, diag_id, target->location.start); + parse_target_implicit_parameter(parser, target); + } + + pm_locals_unread(&scope->locals, name); pm_node_destroy(parser, target); return (pm_node_t *) pm_local_variable_write_node_create(parser, name, depth, value, &name_loc, operator); } + case PM_IT_LOCAL_VARIABLE_READ_NODE: { + pm_constant_id_t name = pm_parser_local_add_constant(parser, "it", 2); + pm_node_t *node = (pm_node_t *) pm_local_variable_write_node_create(parser, name, 0, value, &target->location, operator); + + parse_target_implicit_parameter(parser, target); + pm_node_destroy(parser, target); + + return node; + } case PM_INSTANCE_VARIABLE_READ_NODE: { pm_node_t *write_node = (pm_node_t *) pm_instance_variable_write_node_create(parser, (pm_instance_variable_read_node_t *) target, operator, value); pm_node_destroy(parser, target); @@ -13329,7 +13691,8 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod call->base.location.end = arguments->base.location.end; parse_write_name(parser, &call->name); - pm_node_flag_set((pm_node_t *) call, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE); + pm_node_flag_set((pm_node_t *) call, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE | pm_implicit_array_write_flags(value, PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY)); + return (pm_node_t *) call; } } @@ -13347,7 +13710,8 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod // Replace the name with "[]=". call->name = pm_parser_constant_id_constant(parser, "[]=", 3); - pm_node_flag_set((pm_node_t *) call, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE); + pm_node_flag_set((pm_node_t *) call, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE | pm_implicit_array_write_flags(value, PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY)); + return target; } @@ -13387,7 +13751,7 @@ parse_unwriteable_write(pm_parser_t *parser, pm_node_t *target, const pm_token_t default: break; } - pm_constant_id_t name = pm_parser_constant_id_location(parser, target->location.start, target->location.end); + pm_constant_id_t name = pm_parser_local_add_location(parser, target->location.start, target->location.end, 1); pm_local_variable_write_node_t *result = pm_local_variable_write_node_create(parser, name, 0, value, &target->location, equals); pm_node_destroy(parser, target); @@ -13405,11 +13769,11 @@ parse_unwriteable_write(pm_parser_t *parser, pm_node_t *target, const pm_token_t * target node or a multi-target node. */ static pm_node_t * -parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t binding_power) { +parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t binding_power, uint16_t depth) { bool has_rest = PM_NODE_TYPE_P(first_target, PM_SPLAT_NODE); pm_multi_target_node_t *result = pm_multi_target_node_create(parser); - pm_multi_target_node_targets_append(parser, result, parse_target(parser, first_target, true)); + pm_multi_target_node_targets_append(parser, result, parse_target(parser, first_target, true, false)); while (accept1(parser, PM_TOKEN_COMMA)) { if (accept1(parser, PM_TOKEN_USTAR)) { @@ -13424,16 +13788,23 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b pm_node_t *name = NULL; if (token_begins_expression_p(parser->current.type)) { - name = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR); - name = parse_target(parser, name, true); + name = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); + name = parse_target(parser, name, true, true); } pm_node_t *splat = (pm_node_t *) pm_splat_node_create(parser, &star_operator, name); pm_multi_target_node_targets_append(parser, result, splat); has_rest = true; + } else if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) { + context_push(parser, PM_CONTEXT_MULTI_TARGET); + pm_node_t *target = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1)); + target = parse_target(parser, target, true, false); + + pm_multi_target_node_targets_append(parser, result, target); + context_pop(parser); } else if (token_begins_expression_p(parser->current.type)) { - pm_node_t *target = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA); - target = parse_target(parser, target, true); + pm_node_t *target = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1)); + target = parse_target(parser, target, true, false); pm_multi_target_node_targets_append(parser, result, target); } else if (!match1(parser, PM_TOKEN_EOF)) { @@ -13453,8 +13824,8 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b * assignment. */ static pm_node_t * -parse_targets_validate(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t binding_power) { - pm_node_t *result = parse_targets(parser, first_target, binding_power); +parse_targets_validate(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t binding_power, uint16_t depth) { + pm_node_t *result = parse_targets(parser, first_target, binding_power, depth); accept1(parser, PM_TOKEN_NEWLINE); // Ensure that we have either an = or a ) after the targets. @@ -13469,9 +13840,9 @@ parse_targets_validate(pm_parser_t *parser, pm_node_t *first_target, pm_binding_ * Parse a list of statements separated by newlines or semicolons. */ static pm_statements_node_t * -parse_statements(pm_parser_t *parser, pm_context_t context) { - // First, skip past any optional terminators that might be at the beginning of - // the statements. +parse_statements(pm_parser_t *parser, pm_context_t context, uint16_t depth) { + // First, skip past any optional terminators that might be at the beginning + // of the statements. while (accept2(parser, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE)); // If we have a terminator, then we can just return NULL. @@ -13484,23 +13855,23 @@ parse_statements(pm_parser_t *parser, pm_context_t context) { context_push(parser, context); while (true) { - pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_CANNOT_PARSE_EXPRESSION); - pm_statements_node_body_append(parser, statements, node); + pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, false, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1)); + pm_statements_node_body_append(parser, statements, node, true); - // If we're recovering from a syntax error, then we need to stop parsing the - // statements now. + // If we're recovering from a syntax error, then we need to stop parsing + // the statements now. if (parser->recovering) { - // If this is the level of context where the recovery has happened, then - // we can mark the parser as done recovering. + // If this is the level of context where the recovery has happened, + // then we can mark the parser as done recovering. if (context_terminator(context, &parser->current)) parser->recovering = false; break; } - // If we have a terminator, then we will parse all consecutive terminators - // and then continue parsing the statements list. + // If we have a terminator, then we will parse all consecutive + // terminators and then continue parsing the statements list. if (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { - // If we have a terminator, then we will continue parsing the statements - // list. + // If we have a terminator, then we will continue parsing the + // statements list. while (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)); if (context_terminator(context, &parser->current)) break; @@ -13508,27 +13879,28 @@ parse_statements(pm_parser_t *parser, pm_context_t context) { continue; } - // At this point we have a list of statements that are not terminated by a - // newline or semicolon. At this point we need to check if we're at the end - // of the statements list. If we are, then we should break out of the loop. + // At this point we have a list of statements that are not terminated by + // a newline or semicolon. At this point we need to check if we're at + // the end of the statements list. If we are, then we should break out + // of the loop. if (context_terminator(context, &parser->current)) break; // At this point, we have a syntax error, because the statement was not // terminated by a newline or semicolon, and we're not at the end of the - // statements list. Ideally we should scan forward to determine if we should - // insert a missing terminator or break out of parsing the statements list - // at this point. + // statements list. Ideally we should scan forward to determine if we + // should insert a missing terminator or break out of parsing the + // statements list at this point. // - // We don't have that yet, so instead we'll do a more naive approach. If we - // were unable to parse an expression, then we will skip past this token and - // continue parsing the statements list. Otherwise we'll add an error and - // continue parsing the statements list. + // We don't have that yet, so instead we'll do a more naive approach. If + // we were unable to parse an expression, then we will skip past this + // token and continue parsing the statements list. Otherwise we'll add + // an error and continue parsing the statements list. if (PM_NODE_TYPE_P(node, PM_MISSING_NODE)) { parser_lex(parser); while (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)); if (context_terminator(context, &parser->current)) break; - } else if (!accept1(parser, PM_TOKEN_NEWLINE)) { + } else if (!accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_EOF)) { // This is an inlined version of accept1 because the error that we // want to add has varargs. If this happens again, we should // probably extract a helper function. @@ -13539,7 +13911,16 @@ parse_statements(pm_parser_t *parser, pm_context_t context) { } context_pop(parser); - pm_void_statements_check(parser, statements); + bool last_value = true; + switch (context) { + case PM_CONTEXT_BEGIN_ENSURE: + case PM_CONTEXT_DEF_ENSURE: + last_value = false; + break; + default: + break; + } + pm_void_statements_check(parser, statements, last_value); return statements; } @@ -13550,7 +13931,7 @@ parse_statements(pm_parser_t *parser, pm_context_t context) { */ static void pm_hash_key_static_literals_add(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) { - const pm_node_t *duplicated = pm_static_literals_add(&parser->newline_list, parser->start_line, literals, node); + const pm_node_t *duplicated = pm_static_literals_add(&parser->newline_list, parser->start_line, literals, node, true); if (duplicated != NULL) { pm_buffer_t buffer = { 0 }; @@ -13576,13 +13957,16 @@ pm_hash_key_static_literals_add(pm_parser_t *parser, pm_static_literals_t *liter */ static void pm_when_clause_static_literals_add(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) { - if (pm_static_literals_add(&parser->newline_list, parser->start_line, literals, node) != NULL) { + pm_node_t *previous; + + if ((previous = pm_static_literals_add(&parser->newline_list, parser->start_line, literals, node, false)) != NULL) { pm_diagnostic_list_append_format( &parser->warning_list, node->location.start, node->location.end, PM_WARN_DUPLICATED_WHEN_CLAUSE, - pm_newline_list_line_column(&parser->newline_list, node->location.start, parser->start_line).line + pm_newline_list_line_column(&parser->newline_list, node->location.start, parser->start_line).line, + pm_newline_list_line_column(&parser->newline_list, previous->location.start, parser->start_line).line ); } } @@ -13591,7 +13975,7 @@ pm_when_clause_static_literals_add(pm_parser_t *parser, pm_static_literals_t *li * Parse all of the elements of a hash. Return true if a double splat was found. */ static bool -parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) { +parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node, uint16_t depth) { assert(PM_NODE_TYPE_P(node, PM_HASH_NODE) || PM_NODE_TYPE_P(node, PM_KEYWORD_HASH_NODE)); bool contains_keyword_splat = false; @@ -13610,9 +13994,9 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod // inner hash to share the static literals with the outer // hash. parser->current_hash_keys = literals; - value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH); + value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH, (uint16_t) (depth + 1)); } else if (token_begins_expression_p(parser->current.type)) { - value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH); + value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH, (uint16_t) (depth + 1)); } else { pm_parser_scope_forwarding_keywords_check(parser, &operator); } @@ -13632,7 +14016,7 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod pm_node_t *value = NULL; if (token_begins_expression_p(parser->current.type)) { - value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_EXPRESSION_AFTER_LABEL); + value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_EXPRESSION_AFTER_LABEL, (uint16_t) (depth + 1)); } else { if (parser->encoding->isupper_char(label.start, (label.end - 1) - label.start)) { pm_token_t constant = { .type = PM_TOKEN_CONSTANT, .start = label.start, .end = label.end - 1 }; @@ -13662,7 +14046,7 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod break; } default: { - pm_node_t *key = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_KEY); + pm_node_t *key = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, true, PM_ERR_HASH_KEY, (uint16_t) (depth + 1)); // Hash keys that are strings are automatically frozen. We will // mark that here. @@ -13680,7 +14064,7 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod operator = parser->previous; } - pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_VALUE); + pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); element = (pm_node_t *) pm_assoc_node_create(parser, key, &operator, value); break; } @@ -13726,11 +14110,11 @@ parse_arguments_append(pm_parser_t *parser, pm_arguments_t *arguments, pm_node_t * Parse a list of arguments. */ static void -parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_forwarding, pm_token_type_t terminator) { +parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_forwarding, pm_token_type_t terminator, uint16_t depth) { pm_binding_power_t binding_power = pm_binding_powers[parser->current.type].left; - // First we need to check if the next token is one that could be the start of - // an argument. If it's not, then we can just return. + // First we need to check if the next token is one that could be the start + // of an argument. If it's not, then we can just return. if ( match2(parser, terminator, PM_TOKEN_EOF) || (binding_power != PM_BINDING_POWER_UNSET && binding_power < PM_BINDING_POWER_RANGE) || @@ -13745,9 +14129,6 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for bool parsed_forwarding_arguments = false; while (!match1(parser, PM_TOKEN_EOF)) { - if (parsed_block_argument) { - pm_parser_err_current(parser, PM_ERR_ARGUMENT_AFTER_BLOCK); - } if (parsed_forwarding_arguments) { pm_parser_err_current(parser, PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES); } @@ -13765,7 +14146,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for argument = (pm_node_t *) hash; pm_static_literals_t hash_keys = { 0 }; - bool contains_keyword_splat = parse_assocs(parser, &hash_keys, (pm_node_t *) hash); + bool contains_keyword_splat = parse_assocs(parser, &hash_keys, (pm_node_t *) hash, (uint16_t) (depth + 1)); parse_arguments_append(parser, arguments, argument); @@ -13784,7 +14165,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for pm_node_t *expression = NULL; if (token_begins_expression_p(parser->current.type)) { - expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_ARGUMENT); + expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1)); } else { pm_parser_scope_forwarding_block_check(parser, &operator); } @@ -13796,6 +14177,10 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for arguments->block = argument; } + if (match1(parser, PM_TOKEN_COMMA)) { + pm_parser_err_current(parser, PM_ERR_ARGUMENT_AFTER_BLOCK); + } + parsed_block_argument = true; break; } @@ -13807,7 +14192,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for pm_parser_scope_forwarding_positionals_check(parser, &operator); argument = (pm_node_t *) pm_splat_node_create(parser, &operator, NULL); } else { - pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT); + pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT, (uint16_t) (depth + 1)); if (parsed_bare_hash) { pm_parser_err(parser, operator.start, expression->location.end, PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT); @@ -13824,10 +14209,20 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for parser_lex(parser); if (token_begins_expression_p(parser->current.type)) { - // If the token begins an expression then this ... was not actually - // argument forwarding but was instead a range. + // If the token begins an expression then this ... was + // not actually argument forwarding but was instead a + // range. pm_token_t operator = parser->previous; - pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_RANGE, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_RANGE, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + + // If we parse a range, we need to validate that we + // didn't accidentally violate the nonassoc rules of the + // ... operator. + if (PM_NODE_TYPE_P(right, PM_RANGE_NODE)) { + pm_range_node_t *range = (pm_range_node_t *) right; + pm_parser_err(parser, range->operator_loc.start, range->operator_loc.end, PM_ERR_UNEXPECTED_RANGE_OPERATOR); + } + argument = (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right); } else { pm_parser_scope_forwarding_all_check(parser, &parser->previous); @@ -13837,6 +14232,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for argument = (pm_node_t *) pm_forwarding_arguments_node_create(parser, &parser->previous); parse_arguments_append(parser, arguments, argument); + pm_node_flag_set((pm_node_t *) arguments->arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_FORWARDING); arguments->has_forwarding = true; parsed_forwarding_arguments = true; break; @@ -13846,7 +14242,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for /* fallthrough */ default: { if (argument == NULL) { - argument = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, !parsed_first_argument, PM_ERR_EXPECT_ARGUMENT); + argument = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, !parsed_first_argument, true, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1)); } bool contains_keywords = false; @@ -13872,7 +14268,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for pm_hash_key_static_literals_add(parser, &hash_keys, argument); // Finish parsing the one we are part way through. - pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_VALUE); + pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); argument = (pm_node_t *) pm_assoc_node_create(parser, argument, &operator, value); pm_keyword_hash_node_elements_append(bare_hash, argument); @@ -13883,14 +14279,11 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for token_begins_expression_p(parser->current.type) || match2(parser, PM_TOKEN_USTAR_STAR, PM_TOKEN_LABEL) )) { - contains_keyword_splat = parse_assocs(parser, &hash_keys, (pm_node_t *) bare_hash); + contains_keyword_splat = parse_assocs(parser, &hash_keys, (pm_node_t *) bare_hash, (uint16_t) (depth + 1)); } pm_static_literals_free(&hash_keys); parsed_bare_hash = true; - } else if (accept1(parser, PM_TOKEN_KEYWORD_IN)) { - // TODO: Could we solve this with binding powers instead? - pm_parser_err_current(parser, PM_ERR_ARGUMENT_IN); } parse_arguments_append(parser, arguments, argument); @@ -13909,23 +14302,32 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for // If parsing the argument failed, we need to stop parsing arguments. if (PM_NODE_TYPE_P(argument, PM_MISSING_NODE) || parser->recovering) break; - // If the terminator of these arguments is not EOF, then we have a specific - // token we're looking for. In that case we can accept a newline here - // because it is not functioning as a statement terminator. - if (terminator != PM_TOKEN_EOF) accept1(parser, PM_TOKEN_NEWLINE); + // If the terminator of these arguments is not EOF, then we have a + // specific token we're looking for. In that case we can accept a + // newline here because it is not functioning as a statement terminator. + bool accepted_newline = false; + if (terminator != PM_TOKEN_EOF) { + accepted_newline = accept1(parser, PM_TOKEN_NEWLINE); + } if (parser->previous.type == PM_TOKEN_COMMA && parsed_bare_hash) { - // If we previously were on a comma and we just parsed a bare hash, then - // we want to continue parsing arguments. This is because the comma was - // grabbed up by the hash parser. + // If we previously were on a comma and we just parsed a bare hash, + // then we want to continue parsing arguments. This is because the + // comma was grabbed up by the hash parser. + } else if (accept1(parser, PM_TOKEN_COMMA)) { + // If there was a comma, then we need to check if we also accepted a + // newline. If we did, then this is a syntax error. + if (accepted_newline) { + pm_parser_err_previous(parser, PM_ERR_INVALID_COMMA); + } } else { - // If there is no comma at the end of the argument list then we're done - // parsing arguments and can break out of this loop. - if (!accept1(parser, PM_TOKEN_COMMA)) break; + // If there is no comma at the end of the argument list then we're + // done parsing arguments and can break out of this loop. + break; } - // If we hit the terminator, then that means we have a trailing comma so we - // can accept that output as well. + // If we hit the terminator, then that means we have a trailing comma so + // we can accept that output as well. if (match1(parser, terminator)) break; } } @@ -14036,31 +14438,37 @@ static pm_parameters_order_t parameters_ordering[PM_TOKEN_MAXIMUM] = { * Check if current parameter follows valid parameters ordering. If not it adds * an error to the list without stopping the parsing, otherwise sets the * parameters state to the one corresponding to the current parameter. + * + * It returns true if it was successful, and false otherwise. */ -static void +static bool update_parameter_state(pm_parser_t *parser, pm_token_t *token, pm_parameters_order_t *current) { pm_parameters_order_t state = parameters_ordering[token->type]; - if (state == PM_PARAMETERS_NO_CHANGE) return; + if (state == PM_PARAMETERS_NO_CHANGE) return true; // If we see another ordered argument after a optional argument // we only continue parsing ordered arguments until we stop seeing ordered arguments. if (*current == PM_PARAMETERS_ORDER_OPTIONAL && state == PM_PARAMETERS_ORDER_NAMED) { *current = PM_PARAMETERS_ORDER_AFTER_OPTIONAL; - return; + return true; } else if (*current == PM_PARAMETERS_ORDER_AFTER_OPTIONAL && state == PM_PARAMETERS_ORDER_NAMED) { - return; + return true; } if (token->type == PM_TOKEN_USTAR && *current == PM_PARAMETERS_ORDER_AFTER_OPTIONAL) { pm_parser_err_token(parser, token, PM_ERR_PARAMETER_STAR); - } - - if (*current == PM_PARAMETERS_ORDER_NOTHING_AFTER || state > *current) { + return false; + } else if (token->type == PM_TOKEN_UDOT_DOT_DOT && (*current >= PM_PARAMETERS_ORDER_KEYWORDS_REST && *current <= PM_PARAMETERS_ORDER_AFTER_OPTIONAL)) { + pm_parser_err_token(parser, token, *current == PM_PARAMETERS_ORDER_AFTER_OPTIONAL ? PM_ERR_PARAMETER_FORWARDING_AFTER_REST : PM_ERR_PARAMETER_ORDER); + return false; + } else if (*current == PM_PARAMETERS_ORDER_NOTHING_AFTER || state > *current) { // We know what transition we failed on, so we can provide a better error here. pm_parser_err_token(parser, token, PM_ERR_PARAMETER_ORDER); - } else if (state < *current) { - *current = state; + return false; } + + if (state < *current) *current = state; + return true; } /** @@ -14072,15 +14480,18 @@ parse_parameters( pm_binding_power_t binding_power, bool uses_parentheses, bool allows_trailing_comma, - bool allows_forwarding_parameters + bool allows_forwarding_parameters, + bool accepts_blocks_in_defaults, + uint16_t depth ) { - pm_parameters_node_t *params = pm_parameters_node_create(parser); - bool looping = true; - pm_do_loop_stack_push(parser, false); + + pm_parameters_node_t *params = pm_parameters_node_create(parser); pm_parameters_order_t order = PM_PARAMETERS_ORDER_NONE; - do { + while (true) { + bool parsing = true; + switch (parser->current.type) { case PM_TOKEN_PARENTHESIS_LEFT: { update_parameter_state(parser, &parser->current, &order); @@ -14129,27 +14540,22 @@ parse_parameters( pm_parser_err_current(parser, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES); } - if (order > PM_PARAMETERS_ORDER_NOTHING_AFTER) { - update_parameter_state(parser, &parser->current, &order); - parser_lex(parser); + bool succeeded = update_parameter_state(parser, &parser->current, &order); + parser_lex(parser); - parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_ALL; + parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_ALL; + pm_forwarding_parameter_node_t *param = pm_forwarding_parameter_node_create(parser, &parser->previous); - pm_forwarding_parameter_node_t *param = pm_forwarding_parameter_node_create(parser, &parser->previous); - if (params->keyword_rest != NULL) { - // If we already have a keyword rest parameter, then we replace it with the - // forwarding parameter and move the keyword rest parameter to the posts list. - pm_node_t *keyword_rest = params->keyword_rest; - pm_parameters_node_posts_append(params, keyword_rest); - pm_parser_err_previous(parser, PM_ERR_PARAMETER_UNEXPECTED_FWD); - params->keyword_rest = NULL; - } - pm_parameters_node_keyword_rest_set(params, (pm_node_t *)param); - } else { - update_parameter_state(parser, &parser->current, &order); - parser_lex(parser); + if (params->keyword_rest != NULL) { + // If we already have a keyword rest parameter, then we replace it with the + // forwarding parameter and move the keyword rest parameter to the posts list. + pm_node_t *keyword_rest = params->keyword_rest; + pm_parameters_node_posts_append(params, keyword_rest); + if (succeeded) pm_parser_err_previous(parser, PM_ERR_PARAMETER_UNEXPECTED_FWD); + params->keyword_rest = NULL; } + pm_parameters_node_keyword_rest_set(params, (pm_node_t *) param); break; } case PM_TOKEN_CLASS_VARIABLE: @@ -14188,25 +14594,29 @@ parse_parameters( bool repeated = pm_parser_parameter_name_check(parser, &name); pm_parser_local_add_token(parser, &name, 1); - if (accept1(parser, PM_TOKEN_EQUAL)) { - pm_token_t operator = parser->previous; + if (match1(parser, PM_TOKEN_EQUAL)) { + pm_token_t operator = parser->current; context_push(parser, PM_CONTEXT_DEFAULT_PARAMS); + parser_lex(parser); pm_constant_id_t name_id = pm_parser_constant_id_token(parser, &name); - uint32_t reads = pm_locals_reads(&parser->current_scope->locals, name_id); + uint32_t reads = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0; + + if (accepts_blocks_in_defaults) pm_accepts_block_stack_push(parser, true); + pm_node_t *value = parse_value_expression(parser, binding_power, false, false, PM_ERR_PARAMETER_NO_DEFAULT, (uint16_t) (depth + 1)); + if (accepts_blocks_in_defaults) pm_accepts_block_stack_pop(parser); - pm_node_t *value = parse_value_expression(parser, binding_power, false, PM_ERR_PARAMETER_NO_DEFAULT); pm_optional_parameter_node_t *param = pm_optional_parameter_node_create(parser, &name, &operator, value); if (repeated) { - pm_node_flag_set_repeated_parameter((pm_node_t *)param); + pm_node_flag_set_repeated_parameter((pm_node_t *) param); } pm_parameters_node_optionals_append(params, param); // If the value of the parameter increased the number of // reads of that parameter, then we need to warn that we // have a circular definition. - if (pm_locals_reads(&parser->current_scope->locals, name_id) != reads) { + if ((parser->version == PM_OPTIONS_VERSION_CRUBY_3_3) && (pm_locals_reads(&parser->current_scope->locals, name_id) != reads)) { PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, name, PM_ERR_PARAMETER_CIRCULAR); } @@ -14216,7 +14626,7 @@ parse_parameters( // then we can put a missing node in its place and stop parsing the // parameters entirely now. if (parser->recovering) { - looping = false; + parsing = false; break; } } else if (order > PM_PARAMETERS_ORDER_AFTER_OPTIONAL) { @@ -14238,12 +14648,20 @@ parse_parameters( case PM_TOKEN_LABEL: { if (!uses_parentheses) parser->in_keyword_arg = true; update_parameter_state(parser, &parser->current, &order); + + context_push(parser, PM_CONTEXT_DEFAULT_PARAMS); parser_lex(parser); pm_token_t name = parser->previous; pm_token_t local = name; local.end -= 1; + if (parser->encoding_changed ? parser->encoding->isupper_char(local.start, local.end - local.start) : pm_encoding_utf_8_isupper_char(local.start, local.end - local.start)) { + pm_parser_err(parser, local.start, local.end, PM_ERR_ARGUMENT_FORMAL_CONSTANT); + } else if (local.end[-1] == '!' || local.end[-1] == '?') { + PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, local, PM_ERR_INVALID_LOCAL_VARIABLE_WRITE); + } + bool repeated = pm_parser_parameter_name_check(parser, &local); pm_parser_local_add_token(parser, &local, 1); @@ -14251,17 +14669,22 @@ parse_parameters( case PM_TOKEN_COMMA: case PM_TOKEN_PARENTHESIS_RIGHT: case PM_TOKEN_PIPE: { + context_pop(parser); + pm_node_t *param = (pm_node_t *) pm_required_keyword_parameter_node_create(parser, &name); if (repeated) { pm_node_flag_set_repeated_parameter(param); } + pm_parameters_node_keywords_append(params, param); break; } case PM_TOKEN_SEMICOLON: case PM_TOKEN_NEWLINE: { + context_pop(parser); + if (uses_parentheses) { - looping = false; + parsing = false; break; } @@ -14269,6 +14692,7 @@ parse_parameters( if (repeated) { pm_node_flag_set_repeated_parameter(param); } + pm_parameters_node_keywords_append(params, param); break; } @@ -14276,17 +14700,17 @@ parse_parameters( pm_node_t *param; if (token_begins_expression_p(parser->current.type)) { - context_push(parser, PM_CONTEXT_DEFAULT_PARAMS); - pm_constant_id_t name_id = pm_parser_constant_id_token(parser, &local); - uint32_t reads = pm_locals_reads(&parser->current_scope->locals, name_id); - pm_node_t *value = parse_value_expression(parser, binding_power, false, PM_ERR_PARAMETER_NO_DEFAULT_KW); + uint32_t reads = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0; - if (pm_locals_reads(&parser->current_scope->locals, name_id) != reads) { + if (accepts_blocks_in_defaults) pm_accepts_block_stack_push(parser, true); + pm_node_t *value = parse_value_expression(parser, binding_power, false, false, PM_ERR_PARAMETER_NO_DEFAULT_KW, (uint16_t) (depth + 1)); + if (accepts_blocks_in_defaults) pm_accepts_block_stack_pop(parser); + + if (parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 && (pm_locals_reads(&parser->current_scope->locals, name_id) != reads)) { PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, local, PM_ERR_PARAMETER_CIRCULAR); } - context_pop(parser); param = (pm_node_t *) pm_optional_keyword_parameter_node_create(parser, &name, value); } else { @@ -14296,13 +14720,15 @@ parse_parameters( if (repeated) { pm_node_flag_set_repeated_parameter(param); } + + context_pop(parser); pm_parameters_node_keywords_append(params, param); // If parsing the value of the parameter resulted in error recovery, // then we can put a missing node in its place and stop parsing the // parameters entirely now. if (parser->recovering) { - looping = false; + parsing = false; break; } } @@ -14388,7 +14814,7 @@ parse_parameters( } default: if (parser->previous.type == PM_TOKEN_COMMA) { - if (allows_trailing_comma) { + if (allows_trailing_comma && order >= PM_PARAMETERS_ORDER_NAMED) { // If we get here, then we have a trailing comma in a // block parameter list. pm_node_t *param = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous); @@ -14404,14 +14830,31 @@ parse_parameters( } } - looping = false; + parsing = false; break; } - if (looping && uses_parentheses) { - accept1(parser, PM_TOKEN_NEWLINE); + // If we hit some kind of issue while parsing the parameter, this would + // have been set to false. In that case, we need to break out of the + // loop. + if (!parsing) break; + + bool accepted_newline = false; + if (uses_parentheses) { + accepted_newline = accept1(parser, PM_TOKEN_NEWLINE); + } + + if (accept1(parser, PM_TOKEN_COMMA)) { + // If there was a comma, but we also accepted a newline, then this + // is a syntax error. + if (accepted_newline) { + pm_parser_err_previous(parser, PM_ERR_INVALID_COMMA); + } + } else { + // If there was no comma, then we're done parsing parameters. + break; } - } while (looping && accept1(parser, PM_TOKEN_COMMA)); + } pm_do_loop_stack_pop(parser); @@ -14424,6 +14867,107 @@ parse_parameters( return params; } +/** + * Accepts a parser returns the index of the last newline in the file that was + * ecorded before the current token within the newline list. + */ +static size_t +token_newline_index(const pm_parser_t *parser) { + if (parser->heredoc_end == NULL) { + // This is the common case. In this case we can look at the previously + // recorded newline in the newline list and subtract from the current + // offset. + return parser->newline_list.size - 1; + } else { + // This is unlikely. This is the case that we have already parsed the + // start of a heredoc, so we cannot rely on looking at the previous + // offset of the newline list, and instead must go through the whole + // process of a binary search for the line number. + return (size_t) pm_newline_list_line(&parser->newline_list, parser->current.start, 0); + } +} + +/** + * Accepts a parser, a newline index, and a token and returns the column. The + * important piece of this is that it expands tabs out to the next tab stop. + */ +static int64_t +token_column(const pm_parser_t *parser, size_t newline_index, const pm_token_t *token, bool break_on_non_space) { + const uint8_t *cursor = parser->start + parser->newline_list.offsets[newline_index]; + const uint8_t *end = token->start; + + // Skip over the BOM if it is present. + if ( + newline_index == 0 && + parser->start[0] == 0xef && + parser->start[1] == 0xbb && + parser->start[2] == 0xbf + ) cursor += 3; + + int64_t column = 0; + for (; cursor < end; cursor++) { + switch (*cursor) { + case '\t': + column = ((column / PM_TAB_WHITESPACE_SIZE) + 1) * PM_TAB_WHITESPACE_SIZE; + break; + case ' ': + column++; + break; + default: + column++; + if (break_on_non_space) return -1; + break; + } + } + + return column; +} + +/** + * Accepts a parser, two newline indices, and pointers to two tokens. This + * function warns if the indentation of the two tokens does not match. + */ +static void +parser_warn_indentation_mismatch(pm_parser_t *parser, size_t opening_newline_index, const pm_token_t *opening_token, bool if_after_else, bool allow_indent) { + // If these warnings are disabled (unlikely), then we can just return. + if (!parser->warn_mismatched_indentation) return; + + // If the tokens are on the same line, we do not warn. + size_t closing_newline_index = token_newline_index(parser); + if (opening_newline_index == closing_newline_index) return; + + // If the opening token has anything other than spaces or tabs before it, + // then we do not warn. This is unless we are matching up an `if`/`end` pair + // and the `if` immediately follows an `else` keyword. + int64_t opening_column = token_column(parser, opening_newline_index, opening_token, !if_after_else); + if (!if_after_else && (opening_column == -1)) return; + + // Get a reference to the closing token off the current parser. This assumes + // that the caller has placed this in the correct position. + pm_token_t *closing_token = &parser->current; + + // If the tokens are at the same indentation, we do not warn. + int64_t closing_column = token_column(parser, closing_newline_index, closing_token, true); + if ((closing_column == -1) || (opening_column == closing_column)) return; + + // If the closing column is greater than the opening column and we are + // allowing indentation, then we do not warn. + if (allow_indent && (closing_column > opening_column)) return; + + // Otherwise, add a warning. + PM_PARSER_WARN_FORMAT( + parser, + closing_token->start, + closing_token->end, + PM_WARN_INDENTATION_MISMATCH, + (int) (closing_token->end - closing_token->start), + (const char *) closing_token->start, + (int) (opening_token->end - opening_token->start), + (const char *) opening_token->start, + ((int32_t) opening_newline_index) + parser->start_line + ); +} + typedef enum { PM_RESCUES_BEGIN = 1, PM_RESCUES_BLOCK, @@ -14439,10 +14983,13 @@ typedef enum { * nodes pointing to each other from the top. */ static inline void -parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type_t type) { +parse_rescues(pm_parser_t *parser, size_t opening_newline_index, const pm_token_t *opening, pm_begin_node_t *parent_node, pm_rescues_type_t type, uint16_t depth) { pm_rescue_node_t *current = NULL; - while (accept1(parser, PM_TOKEN_KEYWORD_RESCUE)) { + while (match1(parser, PM_TOKEN_KEYWORD_RESCUE)) { + if (opening != NULL) parser_warn_indentation_mismatch(parser, opening_newline_index, opening, false, false); + parser_lex(parser); + pm_rescue_node_t *rescue = pm_rescue_node_create(parser, &parser->previous); switch (parser->current.type) { @@ -14453,8 +15000,8 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type parser_lex(parser); pm_rescue_node_operator_set(rescue, &parser->previous); - pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_RESCUE_VARIABLE); - reference = parse_target(parser, reference, false); + pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_RESCUE_VARIABLE, (uint16_t) (depth + 1)); + reference = parse_target(parser, reference, false, false); pm_rescue_node_reference_set(rescue, reference); break; @@ -14471,7 +15018,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type // we'll attempt to parse it here and any others delimited by commas. do { - pm_node_t *expression = parse_starred_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_RESCUE_EXPRESSION); + pm_node_t *expression = parse_starred_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_RESCUE_EXPRESSION, (uint16_t) (depth + 1)); pm_rescue_node_exceptions_append(rescue, expression); // If we hit a newline, then this is the end of the rescue expression. We @@ -14483,8 +15030,8 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type if (accept1(parser, PM_TOKEN_EQUAL_GREATER)) { pm_rescue_node_operator_set(rescue, &parser->previous); - pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_RESCUE_VARIABLE); - reference = parse_target(parser, reference, false); + pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_RESCUE_VARIABLE, (uint16_t) (depth + 1)); + reference = parse_target(parser, reference, false, false); pm_rescue_node_reference_set(rescue, reference); break; @@ -14515,7 +15062,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type default: assert(false && "unreachable"); context = PM_CONTEXT_BEGIN_RESCUE; break; } - pm_statements_node_t *statements = parse_statements(parser, context); + pm_statements_node_t *statements = parse_statements(parser, context, (uint16_t) (depth + 1)); if (statements != NULL) pm_rescue_node_statements_set(rescue, statements); pm_accepts_block_stack_pop(parser); @@ -14525,26 +15072,34 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type if (current == NULL) { pm_begin_node_rescue_clause_set(parent_node, rescue); } else { - pm_rescue_node_consequent_set(current, rescue); + pm_rescue_node_subsequent_set(current, rescue); } current = rescue; } // The end node locations on rescue nodes will not be set correctly - // since we won't know the end until we've found all consequent + // since we won't know the end until we've found all subsequent // clauses. This sets the end location on all rescues once we know it. - if (current) { + if (current != NULL) { const uint8_t *end_to_set = current->base.location.end; - current = parent_node->rescue_clause; - while (current) { - current->base.location.end = end_to_set; - current = current->consequent; + pm_rescue_node_t *clause = parent_node->rescue_clause; + + while (clause != NULL) { + clause->base.location.end = end_to_set; + clause = clause->subsequent; } } - if (accept1(parser, PM_TOKEN_KEYWORD_ELSE)) { - pm_token_t else_keyword = parser->previous; + pm_token_t else_keyword; + if (match1(parser, PM_TOKEN_KEYWORD_ELSE)) { + if (opening != NULL) parser_warn_indentation_mismatch(parser, opening_newline_index, opening, false, false); + opening_newline_index = token_newline_index(parser); + + else_keyword = parser->current; + opening = &else_keyword; + + parser_lex(parser); accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); pm_statements_node_t *else_statements = NULL; @@ -14563,7 +15118,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type default: assert(false && "unreachable"); context = PM_CONTEXT_BEGIN_RESCUE; break; } - else_statements = parse_statements(parser, context); + else_statements = parse_statements(parser, context, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); @@ -14571,10 +15126,17 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type pm_else_node_t *else_clause = pm_else_node_create(parser, &else_keyword, else_statements, &parser->current); pm_begin_node_else_clause_set(parent_node, else_clause); + + // If we don't have a `current` rescue node, then this is a dangling + // else, and it's an error. + if (current == NULL) pm_parser_err_node(parser, (pm_node_t *) else_clause, PM_ERR_BEGIN_LONELY_ELSE); } - if (accept1(parser, PM_TOKEN_KEYWORD_ENSURE)) { - pm_token_t ensure_keyword = parser->previous; + if (match1(parser, PM_TOKEN_KEYWORD_ENSURE)) { + if (opening != NULL) parser_warn_indentation_mismatch(parser, opening_newline_index, opening, false, false); + pm_token_t ensure_keyword = parser->current; + + parser_lex(parser); accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); pm_statements_node_t *ensure_statements = NULL; @@ -14593,7 +15155,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type default: assert(false && "unreachable"); context = PM_CONTEXT_BEGIN_RESCUE; break; } - ensure_statements = parse_statements(parser, context); + ensure_statements = parse_statements(parser, context, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); @@ -14603,7 +15165,8 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type pm_begin_node_ensure_clause_set(parent_node, ensure_clause); } - if (parser->current.type == PM_TOKEN_KEYWORD_END) { + if (match1(parser, PM_TOKEN_KEYWORD_END)) { + if (opening != NULL) parser_warn_indentation_mismatch(parser, opening_newline_index, opening, false, false); pm_begin_node_end_keyword_set(parent_node, &parser->current); } else { pm_token_t end_keyword = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end }; @@ -14616,11 +15179,11 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type * class, module, def, etc.). */ static pm_begin_node_t * -parse_rescues_implicit_begin(pm_parser_t *parser, const uint8_t *start, pm_statements_node_t *statements, pm_rescues_type_t type) { +parse_rescues_implicit_begin(pm_parser_t *parser, size_t opening_newline_index, const pm_token_t *opening, const uint8_t *start, pm_statements_node_t *statements, pm_rescues_type_t type, uint16_t depth) { pm_token_t begin_keyword = not_provided(parser); pm_begin_node_t *node = pm_begin_node_create(parser, &begin_keyword, statements); - parse_rescues(parser, node, type); + parse_rescues(parser, opening_newline_index, opening, node, type, (uint16_t) (depth + 1)); node->base.location.start = start; return node; @@ -14634,7 +15197,9 @@ parse_block_parameters( pm_parser_t *parser, bool allows_trailing_comma, const pm_token_t *opening, - bool is_lambda_literal + bool is_lambda_literal, + bool accepts_blocks_in_defaults, + uint16_t depth ) { pm_parameters_node_t *parameters = NULL; if (!match1(parser, PM_TOKEN_SEMICOLON)) { @@ -14643,7 +15208,9 @@ parse_block_parameters( is_lambda_literal ? PM_BINDING_POWER_DEFINED : PM_BINDING_POWER_INDEX, false, allows_trailing_comma, - false + false, + accepts_blocks_in_defaults, + (uint16_t) (depth + 1) ); } @@ -14689,6 +15256,28 @@ parse_block_parameters( return block_parameters; } +/** + * Return true if any of the visible scopes to the current context are using + * numbered parameters. + */ +static bool +outer_scope_using_numbered_parameters_p(pm_parser_t *parser) { + for (pm_scope_t *scope = parser->current_scope->previous; scope != NULL && !scope->closed; scope = scope->previous) { + if (scope->parameters & PM_SCOPE_PARAMETERS_NUMBERED_FOUND) return true; + } + + return false; +} + +/** + * These are the names of the various numbered parameters. We have them here so + * that when we insert them into the constant pool we can use a constant string + * and not have to allocate. + */ +static const char * const pm_numbered_parameter_names[] = { + "_1", "_2", "_3", "_4", "_5", "_6", "_7", "_8", "_9" +}; + /** * Return the node that should be used in the parameters field of a block-like * (block or lambda) node, depending on the kind of parameters that were @@ -14696,38 +15285,86 @@ parse_block_parameters( */ static pm_node_t * parse_blocklike_parameters(pm_parser_t *parser, pm_node_t *parameters, const pm_token_t *opening, const pm_token_t *closing) { - uint8_t masked = parser->current_scope->parameters & PM_SCOPE_PARAMETERS_TYPE_MASK; - - if (masked == PM_SCOPE_PARAMETERS_NONE) { - assert(parameters == NULL); - return NULL; - } else if (masked == PM_SCOPE_PARAMETERS_ORDINARY) { - assert(parameters != NULL); - return parameters; - } else if (masked == PM_SCOPE_PARAMETERS_NUMBERED) { - assert(parameters == NULL); + pm_node_list_t *implicit_parameters = &parser->current_scope->implicit_parameters; - int8_t maximum = parser->current_scope->numbered_parameters; - if (maximum > 0) { - const pm_location_t location = { .start = opening->start, .end = closing->end }; - return (pm_node_t *) pm_numbered_parameters_node_create(parser, &location, (uint8_t) maximum); + // If we have ordinary parameters, then we will return them as the set of + // parameters. + if (parameters != NULL) { + // If we also have implicit parameters, then this is an error. + if (implicit_parameters->size > 0) { + pm_node_t *node = implicit_parameters->nodes[0]; + + if (PM_NODE_TYPE_P(node, PM_LOCAL_VARIABLE_READ_NODE)) { + pm_parser_err_node(parser, node, PM_ERR_NUMBERED_PARAMETER_ORDINARY); + } else if (PM_NODE_TYPE_P(node, PM_IT_LOCAL_VARIABLE_READ_NODE)) { + pm_parser_err_node(parser, node, PM_ERR_IT_NOT_ALLOWED_ORDINARY); + } else { + assert(false && "unreachable"); + } } - return NULL; - } else if (masked == PM_SCOPE_PARAMETERS_IT) { - assert(parameters == NULL); - return (pm_node_t *) pm_it_parameters_node_create(parser, opening, closing); - } else { - assert(false && "unreachable"); + return parameters; + } + + // If we don't have any implicit parameters, then the set of parameters is + // NULL. + if (implicit_parameters->size == 0) { return NULL; } -} -/** - * Parse a block. - */ + // If we don't have ordinary parameters, then we now must validate our set + // of implicit parameters. We can only have numbered parameters or it, but + // they cannot be mixed. + uint8_t numbered_parameter = 0; + bool it_parameter = false; + + for (size_t index = 0; index < implicit_parameters->size; index++) { + pm_node_t *node = implicit_parameters->nodes[index]; + + if (PM_NODE_TYPE_P(node, PM_LOCAL_VARIABLE_READ_NODE)) { + if (it_parameter) { + pm_parser_err_node(parser, node, PM_ERR_NUMBERED_PARAMETER_IT); + } else if (outer_scope_using_numbered_parameters_p(parser)) { + pm_parser_err_node(parser, node, PM_ERR_NUMBERED_PARAMETER_OUTER_BLOCK); + } else if (parser->current_scope->parameters & PM_SCOPE_PARAMETERS_NUMBERED_INNER) { + pm_parser_err_node(parser, node, PM_ERR_NUMBERED_PARAMETER_INNER_BLOCK); + } else if (pm_token_is_numbered_parameter(node->location.start, node->location.end)) { + numbered_parameter = MAX(numbered_parameter, (uint8_t) (node->location.start[1] - '0')); + } else { + assert(false && "unreachable"); + } + } else if (PM_NODE_TYPE_P(node, PM_IT_LOCAL_VARIABLE_READ_NODE)) { + if (numbered_parameter > 0) { + pm_parser_err_node(parser, node, PM_ERR_IT_NOT_ALLOWED_NUMBERED); + } else { + it_parameter = true; + } + } + } + + if (numbered_parameter > 0) { + // Go through the parent scopes and mark them as being disallowed from + // using numbered parameters because this inner scope is using them. + for (pm_scope_t *scope = parser->current_scope->previous; scope != NULL && !scope->closed; scope = scope->previous) { + scope->parameters |= PM_SCOPE_PARAMETERS_NUMBERED_INNER; + } + + const pm_location_t location = { .start = opening->start, .end = closing->end }; + return (pm_node_t *) pm_numbered_parameters_node_create(parser, &location, numbered_parameter); + } + + if (it_parameter) { + return (pm_node_t *) pm_it_parameters_node_create(parser, opening, closing); + } + + return NULL; +} + +/** + * Parse a block. + */ static pm_block_node_t * -parse_block(pm_parser_t *parser) { +parse_block(pm_parser_t *parser, uint16_t depth) { pm_token_t opening = parser->previous; accept1(parser, PM_TOKEN_NEWLINE); @@ -14737,16 +15374,13 @@ parse_block(pm_parser_t *parser) { pm_block_parameters_node_t *block_parameters = NULL; if (accept1(parser, PM_TOKEN_PIPE)) { - assert(parser->current_scope->parameters == PM_SCOPE_PARAMETERS_NONE); - parser->current_scope->parameters = PM_SCOPE_PARAMETERS_ORDINARY; - pm_token_t block_parameters_opening = parser->previous; if (match1(parser, PM_TOKEN_PIPE)) { block_parameters = pm_block_parameters_node_create(parser, NULL, &block_parameters_opening); parser->command_start = true; parser_lex(parser); } else { - block_parameters = parse_block_parameters(parser, true, &block_parameters_opening, false); + block_parameters = parse_block_parameters(parser, true, &block_parameters_opening, false, true, (uint16_t) (depth + 1)); accept1(parser, PM_TOKEN_NEWLINE); parser->command_start = true; expect1(parser, PM_TOKEN_PIPE, PM_ERR_BLOCK_PARAM_PIPE_TERM); @@ -14760,7 +15394,7 @@ parse_block(pm_parser_t *parser) { if (opening.type == PM_TOKEN_BRACE_LEFT) { if (!match1(parser, PM_TOKEN_BRACE_RIGHT)) { - statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_BLOCK_BRACES); + statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_BLOCK_BRACES, (uint16_t) (depth + 1)); } expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_BLOCK_TERM_BRACE); @@ -14768,13 +15402,13 @@ parse_block(pm_parser_t *parser) { if (!match1(parser, PM_TOKEN_KEYWORD_END)) { if (!match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_ENSURE)) { pm_accepts_block_stack_push(parser, true); - statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_BLOCK_KEYWORDS); + statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_BLOCK_KEYWORDS, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); } if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) { assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE)); - statements = (pm_node_t *) parse_rescues_implicit_begin(parser, opening.start, (pm_statements_node_t *) statements, PM_RESCUES_BLOCK); + statements = (pm_node_t *) parse_rescues_implicit_begin(parser, 0, NULL, opening.start, (pm_statements_node_t *) statements, PM_RESCUES_BLOCK, (uint16_t) (depth + 1)); } } @@ -14797,7 +15431,7 @@ parse_block(pm_parser_t *parser) { * arguments, or blocks). */ static bool -parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_block, bool accepts_command_call) { +parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_block, bool accepts_command_call, uint16_t depth) { bool found = false; if (accept1(parser, PM_TOKEN_PARENTHESIS_LEFT)) { @@ -14808,7 +15442,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept arguments->closing_loc = PM_LOCATION_TOKEN_VALUE(&parser->previous); } else { pm_accepts_block_stack_push(parser, true); - parse_arguments(parser, arguments, true, PM_TOKEN_PARENTHESIS_RIGHT); + parse_arguments(parser, arguments, accepts_block, PM_TOKEN_PARENTHESIS_RIGHT, (uint16_t) (depth + 1)); if (!accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_ARGUMENT_TERM_PAREN, pm_token_type_human(parser->current.type)); @@ -14826,13 +15460,13 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept // If we get here, then the subsequent token cannot be used as an infix // operator. In this case we assume the subsequent token is part of an // argument to this method call. - parse_arguments(parser, arguments, true, PM_TOKEN_EOF); + parse_arguments(parser, arguments, accepts_block, PM_TOKEN_EOF, (uint16_t) (depth + 1)); // If we have done with the arguments and still not consumed the comma, // then we have a trailing comma where we need to check whether it is // allowed or not. if (parser->previous.type == PM_TOKEN_COMMA && !match1(parser, PM_TOKEN_SEMICOLON)) { - pm_parser_err_previous(parser, PM_ERR_EXPECT_ARGUMENT); + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, PM_ERR_EXPECT_ARGUMENT, pm_token_type_human(parser->current.type)); } pm_accepts_block_stack_pop(parser); @@ -14846,22 +15480,19 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept if (accept1(parser, PM_TOKEN_BRACE_LEFT)) { found |= true; - block = parse_block(parser); + block = parse_block(parser, (uint16_t) (depth + 1)); pm_arguments_validate_block(parser, arguments, block); } else if (pm_accepts_block_stack_p(parser) && accept1(parser, PM_TOKEN_KEYWORD_DO)) { found |= true; - block = parse_block(parser); + block = parse_block(parser, (uint16_t) (depth + 1)); } if (block != NULL) { if (arguments->block == NULL && !arguments->has_forwarding) { arguments->block = (pm_node_t *) block; } else { - if (arguments->has_forwarding) { - pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_BLOCK_FORWARDING); - } else { - pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_BLOCK_MULTI); - } + pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_BLOCK_MULTI); + if (arguments->block != NULL) { if (arguments->arguments == NULL) { arguments->arguments = pm_arguments_node_create(parser); @@ -14876,16 +15507,97 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept return found; } +/** + * Check that the return is allowed in the current context. If it isn't, add an + * error to the parser. + */ +static void +parse_return(pm_parser_t *parser, pm_node_t *node) { + bool in_sclass = false; + for (pm_context_node_t *context_node = parser->current_context; context_node != NULL; context_node = context_node->prev) { + switch (context_node->context) { + case PM_CONTEXT_BEGIN_ELSE: + case PM_CONTEXT_BEGIN_ENSURE: + case PM_CONTEXT_BEGIN_RESCUE: + case PM_CONTEXT_BEGIN: + case PM_CONTEXT_CASE_IN: + case PM_CONTEXT_CASE_WHEN: + case PM_CONTEXT_DEFAULT_PARAMS: + case PM_CONTEXT_DEFINED: + case PM_CONTEXT_ELSE: + case PM_CONTEXT_ELSIF: + case PM_CONTEXT_EMBEXPR: + case PM_CONTEXT_FOR_INDEX: + case PM_CONTEXT_FOR: + case PM_CONTEXT_IF: + case PM_CONTEXT_LOOP_PREDICATE: + case PM_CONTEXT_MAIN: + case PM_CONTEXT_MULTI_TARGET: + case PM_CONTEXT_PARENS: + case PM_CONTEXT_POSTEXE: + case PM_CONTEXT_PREDICATE: + case PM_CONTEXT_PREEXE: + case PM_CONTEXT_RESCUE_MODIFIER: + case PM_CONTEXT_TERNARY: + case PM_CONTEXT_UNLESS: + case PM_CONTEXT_UNTIL: + case PM_CONTEXT_WHILE: + // Keep iterating up the lists of contexts, because returns can + // see through these. + continue; + case PM_CONTEXT_SCLASS_ELSE: + case PM_CONTEXT_SCLASS_ENSURE: + case PM_CONTEXT_SCLASS_RESCUE: + case PM_CONTEXT_SCLASS: + in_sclass = true; + continue; + case PM_CONTEXT_CLASS_ELSE: + case PM_CONTEXT_CLASS_ENSURE: + case PM_CONTEXT_CLASS_RESCUE: + case PM_CONTEXT_CLASS: + case PM_CONTEXT_MODULE_ELSE: + case PM_CONTEXT_MODULE_ENSURE: + case PM_CONTEXT_MODULE_RESCUE: + case PM_CONTEXT_MODULE: + // These contexts are invalid for a return. + pm_parser_err_node(parser, node, PM_ERR_RETURN_INVALID); + return; + case PM_CONTEXT_BLOCK_BRACES: + case PM_CONTEXT_BLOCK_ELSE: + case PM_CONTEXT_BLOCK_ENSURE: + case PM_CONTEXT_BLOCK_KEYWORDS: + case PM_CONTEXT_BLOCK_RESCUE: + case PM_CONTEXT_DEF_ELSE: + case PM_CONTEXT_DEF_ENSURE: + case PM_CONTEXT_DEF_PARAMS: + case PM_CONTEXT_DEF_RESCUE: + case PM_CONTEXT_DEF: + case PM_CONTEXT_LAMBDA_BRACES: + case PM_CONTEXT_LAMBDA_DO_END: + case PM_CONTEXT_LAMBDA_ELSE: + case PM_CONTEXT_LAMBDA_ENSURE: + case PM_CONTEXT_LAMBDA_RESCUE: + // These contexts are valid for a return, and we should not + // continue to loop. + return; + case PM_CONTEXT_NONE: + // This case should never happen. + assert(false && "unreachable"); + break; + } + } + if (in_sclass) { + pm_parser_err_node(parser, node, PM_ERR_RETURN_INVALID); + } +} + /** * Check that the block exit (next, break, redo) is allowed in the current * context. If it isn't, add an error to the parser. */ static void -parse_block_exit(pm_parser_t *parser, pm_node_t *node, const char *type) { - pm_context_node_t *context_node = parser->current_context; - bool through_expression = false; - - while (context_node != NULL) { +parse_block_exit(pm_parser_t *parser, pm_node_t *node) { + for (pm_context_node_t *context_node = parser->current_context; context_node != NULL; context_node = context_node->prev) { switch (context_node->context) { case PM_CONTEXT_BLOCK_BRACES: case PM_CONTEXT_BLOCK_KEYWORDS: @@ -14899,6 +15611,7 @@ parse_block_exit(pm_parser_t *parser, pm_node_t *node, const char *type) { case PM_CONTEXT_LAMBDA_ELSE: case PM_CONTEXT_LAMBDA_ENSURE: case PM_CONTEXT_LAMBDA_RESCUE: + case PM_CONTEXT_LOOP_PREDICATE: case PM_CONTEXT_POSTEXE: case PM_CONTEXT_UNTIL: case PM_CONTEXT_WHILE: @@ -14918,65 +15631,50 @@ parse_block_exit(pm_parser_t *parser, pm_node_t *node, const char *type) { case PM_CONTEXT_SCLASS_RESCUE: // These are the bad cases. We're not allowed to have a block // exit in these contexts. - - if (through_expression) { - // If we get here, then we're about to mark this block exit - // as invalid. However, it could later _become_ valid if we - // find a trailing while/until on the expression. In this - // case instead of adding the error here, we'll add the - // block exit to the list of exits for the expression, and - // the node parsing will handle validating it instead. - assert(parser->current_block_exits != NULL); - pm_node_list_append(parser->current_block_exits, node); - } else { - // Otherwise, if we haven't gone through an expression - // context, then this is just invalid and we'll add the - // error here. - PM_PARSER_ERR_NODE_FORMAT(parser, node, PM_ERR_INVALID_BLOCK_EXIT, type); - } - + // + // If we get here, then we're about to mark this block exit + // as invalid. However, it could later _become_ valid if we + // find a trailing while/until on the expression. In this + // case instead of adding the error here, we'll add the + // block exit to the list of exits for the expression, and + // the node parsing will handle validating it instead. + assert(parser->current_block_exits != NULL); + pm_node_list_append(parser->current_block_exits, node); return; - case PM_CONTEXT_NONE: - // This case should never happen. - assert(false && "unreachable"); - break; - case PM_CONTEXT_BEGIN: case PM_CONTEXT_BEGIN_ELSE: case PM_CONTEXT_BEGIN_ENSURE: case PM_CONTEXT_BEGIN_RESCUE: + case PM_CONTEXT_BEGIN: case PM_CONTEXT_CASE_IN: case PM_CONTEXT_CASE_WHEN: - case PM_CONTEXT_CLASS: case PM_CONTEXT_CLASS_ELSE: case PM_CONTEXT_CLASS_ENSURE: case PM_CONTEXT_CLASS_RESCUE: + case PM_CONTEXT_CLASS: + case PM_CONTEXT_DEFAULT_PARAMS: case PM_CONTEXT_ELSE: case PM_CONTEXT_ELSIF: + case PM_CONTEXT_EMBEXPR: + case PM_CONTEXT_FOR_INDEX: case PM_CONTEXT_IF: - case PM_CONTEXT_MODULE: case PM_CONTEXT_MODULE_ELSE: case PM_CONTEXT_MODULE_ENSURE: case PM_CONTEXT_MODULE_RESCUE: + case PM_CONTEXT_MODULE: + case PM_CONTEXT_MULTI_TARGET: case PM_CONTEXT_PARENS: + case PM_CONTEXT_PREDICATE: case PM_CONTEXT_RESCUE_MODIFIER: case PM_CONTEXT_TERNARY: case PM_CONTEXT_UNLESS: - // If we got to an expression that could be modified by a - // trailing while/until, then we'll track that we have gotten - // here because we need to know it if this block exit is later - // marked as invalid. - through_expression = true; - break; - case PM_CONTEXT_EMBEXPR: - case PM_CONTEXT_DEFAULT_PARAMS: - case PM_CONTEXT_FOR_INDEX: - case PM_CONTEXT_PREDICATE: // In these contexts we should continue walking up the list of // contexts. break; + case PM_CONTEXT_NONE: + // This case should never happen. + assert(false && "unreachable"); + break; } - - context_node = context_node->prev; } } @@ -14991,6 +15689,30 @@ push_block_exits(pm_parser_t *parser, pm_node_list_t *current_block_exits) { return previous_block_exits; } +/** + * If we did not match a trailing while/until and this was the last chance to do + * so, then all of the block exits in the list are invalid and we need to add an + * error for each of them. + */ +static void +flush_block_exits(pm_parser_t *parser, pm_node_list_t *previous_block_exits) { + pm_node_t *block_exit; + PM_NODE_LIST_FOREACH(parser->current_block_exits, index, block_exit) { + const char *type; + + switch (PM_NODE_TYPE(block_exit)) { + case PM_BREAK_NODE: type = "break"; break; + case PM_NEXT_NODE: type = "next"; break; + case PM_REDO_NODE: type = "redo"; break; + default: assert(false && "unreachable"); type = ""; break; + } + + PM_PARSER_ERR_NODE_FORMAT(parser, block_exit, PM_ERR_INVALID_BLOCK_EXIT, type); + } + + parser->current_block_exits = previous_block_exits; +} + /** * Pop the current level of block exits from the parser, and add errors to the * parser if any of them are deemed to be invalid. @@ -15001,6 +15723,7 @@ pop_block_exits(pm_parser_t *parser, pm_node_list_t *previous_block_exits) { // If we matched a trailing while/until, then all of the block exits in // the contained list are valid. In this case we do not need to do // anything. + parser->current_block_exits = previous_block_exits; } else if (previous_block_exits != NULL) { // If we did not matching a trailing while/until, then all of the block // exits contained in the list are invalid for this specific context. @@ -15008,33 +15731,20 @@ pop_block_exits(pm_parser_t *parser, pm_node_list_t *previous_block_exits) { // there is another list above this one. In this case we'll push all of // the block exits up to the previous list. pm_node_list_concat(previous_block_exits, parser->current_block_exits); + parser->current_block_exits = previous_block_exits; } else { // If we did not match a trailing while/until and this was the last // chance to do so, then all of the block exits in the list are invalid // and we need to add an error for each of them. - pm_node_t *block_exit; - PM_NODE_LIST_FOREACH(parser->current_block_exits, index, block_exit) { - const char *type; - - switch (PM_NODE_TYPE(block_exit)) { - case PM_BREAK_NODE: type = "break"; break; - case PM_NEXT_NODE: type = "next"; break; - case PM_REDO_NODE: type = "redo"; break; - default: assert(false && "unreachable"); type = ""; break; - } - - PM_PARSER_ERR_NODE_FORMAT(parser, block_exit, PM_ERR_INVALID_BLOCK_EXIT, type); - } + flush_block_exits(parser, previous_block_exits); } - - parser->current_block_exits = previous_block_exits; } static inline pm_node_t * -parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_context_t context, pm_token_t *then_keyword) { +parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_context_t context, pm_token_t *then_keyword, uint16_t depth) { context_push(parser, PM_CONTEXT_PREDICATE); pm_diagnostic_id_t error_id = context == PM_CONTEXT_IF ? PM_ERR_CONDITIONAL_IF_PREDICATE : PM_ERR_CONDITIONAL_UNLESS_PREDICATE; - pm_node_t *predicate = parse_value_expression(parser, binding_power, true, error_id); + pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, error_id, (uint16_t) (depth + 1)); // Predicates are closed by a term, a "then", or a term and then a "then". bool predicate_closed = accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); @@ -15053,19 +15763,19 @@ parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_contex } static inline pm_node_t * -parse_conditional(pm_parser_t *parser, pm_context_t context) { +parse_conditional(pm_parser_t *parser, pm_context_t context, size_t opening_newline_index, bool if_after_else, uint16_t depth) { pm_node_list_t current_block_exits = { 0 }; pm_node_list_t *previous_block_exits = push_block_exits(parser, ¤t_block_exits); pm_token_t keyword = parser->previous; pm_token_t then_keyword = not_provided(parser); - pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, context, &then_keyword); + pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, context, &then_keyword, (uint16_t) (depth + 1)); pm_statements_node_t *statements = NULL; if (!match3(parser, PM_TOKEN_KEYWORD_ELSIF, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) { pm_accepts_block_stack_push(parser, true); - statements = parse_statements(parser, context); + statements = parse_statements(parser, context, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); } @@ -15095,49 +15805,53 @@ parse_conditional(pm_parser_t *parser, pm_context_t context) { PM_PARSER_WARN_TOKEN_FORMAT_CONTENT(parser, parser->current, PM_WARN_KEYWORD_EOL); } + parser_warn_indentation_mismatch(parser, opening_newline_index, &keyword, false, false); pm_token_t elsif_keyword = parser->current; parser_lex(parser); - pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, PM_CONTEXT_ELSIF, &then_keyword); + pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, PM_CONTEXT_ELSIF, &then_keyword, (uint16_t) (depth + 1)); pm_accepts_block_stack_push(parser, true); - pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_ELSIF); + pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_ELSIF, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); pm_node_t *elsif = (pm_node_t *) pm_if_node_create(parser, &elsif_keyword, predicate, &then_keyword, statements, NULL, &end_keyword); - ((pm_if_node_t *) current)->consequent = elsif; + ((pm_if_node_t *) current)->subsequent = elsif; current = elsif; } } if (match1(parser, PM_TOKEN_KEYWORD_ELSE)) { + parser_warn_indentation_mismatch(parser, opening_newline_index, &keyword, false, false); + opening_newline_index = token_newline_index(parser); + parser_lex(parser); pm_token_t else_keyword = parser->previous; pm_accepts_block_stack_push(parser, true); - pm_statements_node_t *else_statements = parse_statements(parser, PM_CONTEXT_ELSE); + pm_statements_node_t *else_statements = parse_statements(parser, PM_CONTEXT_ELSE, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); + parser_warn_indentation_mismatch(parser, opening_newline_index, &else_keyword, false, false); expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CONDITIONAL_TERM_ELSE); pm_else_node_t *else_node = pm_else_node_create(parser, &else_keyword, else_statements, &parser->previous); switch (context) { case PM_CONTEXT_IF: - ((pm_if_node_t *) current)->consequent = (pm_node_t *) else_node; + ((pm_if_node_t *) current)->subsequent = (pm_node_t *) else_node; break; case PM_CONTEXT_UNLESS: - ((pm_unless_node_t *) parent)->consequent = else_node; + ((pm_unless_node_t *) parent)->else_clause = else_node; break; default: assert(false && "unreachable"); break; } } else { - // We should specialize this error message to refer to 'if' or 'unless' - // explicitly. + parser_warn_indentation_mismatch(parser, opening_newline_index, &keyword, if_after_else, false); expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CONDITIONAL_TERM); } @@ -15151,7 +15865,7 @@ parse_conditional(pm_parser_t *parser, pm_context_t context) { switch (PM_NODE_TYPE(current)) { case PM_IF_NODE: pm_if_node_end_keyword_loc_set((pm_if_node_t *) current, &parser->previous); - current = ((pm_if_node_t *) current)->consequent; + current = ((pm_if_node_t *) current)->subsequent; recursing = current != NULL; break; case PM_ELSE_NODE: @@ -15240,7 +15954,7 @@ parse_conditional(pm_parser_t *parser, pm_context_t context) { #define PM_CASE_WRITABLE PM_CLASS_VARIABLE_READ_NODE: case PM_CONSTANT_PATH_NODE: \ case PM_CONSTANT_READ_NODE: case PM_GLOBAL_VARIABLE_READ_NODE: case PM_LOCAL_VARIABLE_READ_NODE: \ case PM_INSTANCE_VARIABLE_READ_NODE: case PM_MULTI_TARGET_NODE: case PM_BACK_REFERENCE_READ_NODE: \ - case PM_NUMBERED_REFERENCE_READ_NODE + case PM_NUMBERED_REFERENCE_READ_NODE: case PM_IT_LOCAL_VARIABLE_READ_NODE // Assert here that the flags are the same so that we can safely switch the type // of the node without having to move the flags. @@ -15273,7 +15987,7 @@ parse_unescaped_encoding(const pm_parser_t *parser) { * parsed as a string part, then NULL is returned. */ static pm_node_t * -parse_string_part(pm_parser_t *parser) { +parse_string_part(pm_parser_t *parser, uint16_t depth) { switch (parser->current.type) { // Here the lexer has returned to us plain string content. In this case // we'll create a string node that has no opening or closing and return that @@ -15298,6 +16012,10 @@ parse_string_part(pm_parser_t *parser) { // "aaa #{bbb} #@ccc ddd" // ^^^^^^ case PM_TOKEN_EMBEXPR_BEGIN: { + // Ruby disallows seeing encoding around interpolation in strings, + // even though it is known at parse time. + parser->explicit_encoding = NULL; + pm_lex_state_t state = parser->lex_state; int brace_nesting = parser->brace_nesting; @@ -15310,7 +16028,7 @@ parse_string_part(pm_parser_t *parser) { if (!match1(parser, PM_TOKEN_EMBEXPR_END)) { pm_accepts_block_stack_push(parser, true); - statements = parse_statements(parser, PM_CONTEXT_EMBEXPR); + statements = parse_statements(parser, PM_CONTEXT_EMBEXPR, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); } @@ -15320,6 +16038,13 @@ parse_string_part(pm_parser_t *parser) { expect1(parser, PM_TOKEN_EMBEXPR_END, PM_ERR_EMBEXPR_END); pm_token_t closing = parser->previous; + // If this set of embedded statements only contains a single + // statement, then Ruby does not consider it as a possible statement + // that could emit a line event. + if (statements != NULL && statements->body.size == 1) { + pm_node_flag_unset(statements->body.nodes[0], PM_NODE_FLAG_NEWLINE); + } + return (pm_node_t *) pm_embedded_statements_node_create(parser, &opening, statements, &closing); } @@ -15330,6 +16055,10 @@ parse_string_part(pm_parser_t *parser) { // "aaa #{bbb} #@ccc ddd" // ^^^^^ case PM_TOKEN_EMBVAR: { + // Ruby disallows seeing encoding around interpolation in strings, + // even though it is known at parse time. + parser->explicit_encoding = NULL; + lex_state_set(parser, PM_LEX_STATE_BEG); parser_lex(parser); @@ -15424,7 +16153,7 @@ parse_operator_symbol(pm_parser_t *parser, const pm_token_t *opening, pm_lex_sta * symbols. */ static pm_node_t * -parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_state) { +parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_state, uint16_t depth) { const pm_token_t opening = parser->previous; if (lex_mode->mode != PM_LEX_STRING) { @@ -15470,7 +16199,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s } // Now we can parse the first part of the symbol. - pm_node_t *part = parse_string_part(parser); + pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1)); // If we got a string part, then it's possible that we could transform // what looks like an interpolated symbol into a regular symbol. @@ -15485,7 +16214,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s if (part) pm_interpolated_symbol_node_append(symbol, part); while (!match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) { - if ((part = parse_string_part(parser)) != NULL) { + if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) { pm_interpolated_symbol_node_append(symbol, part); } } @@ -15561,7 +16290,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s * constant, or an interpolated symbol. */ static inline pm_node_t * -parse_undef_argument(pm_parser_t *parser) { +parse_undef_argument(pm_parser_t *parser, uint16_t depth) { switch (parser->current.type) { case PM_CASE_OPERATOR: { const pm_token_t opening = not_provided(parser); @@ -15586,7 +16315,7 @@ parse_undef_argument(pm_parser_t *parser) { pm_lex_mode_t lex_mode = *parser->lex_modes.current; parser_lex(parser); - return parse_symbol(parser, &lex_mode, PM_LEX_STATE_NONE); + return parse_symbol(parser, &lex_mode, PM_LEX_STATE_NONE, (uint16_t) (depth + 1)); } default: pm_parser_err_current(parser, PM_ERR_UNDEF_ARGUMENT); @@ -15601,7 +16330,7 @@ parse_undef_argument(pm_parser_t *parser) { * between the first and second arguments. */ static inline pm_node_t * -parse_alias_argument(pm_parser_t *parser, bool first) { +parse_alias_argument(pm_parser_t *parser, bool first, uint16_t depth) { switch (parser->current.type) { case PM_CASE_OPERATOR: { const pm_token_t opening = not_provided(parser); @@ -15627,7 +16356,7 @@ parse_alias_argument(pm_parser_t *parser, bool first) { pm_lex_mode_t lex_mode = *parser->lex_modes.current; parser_lex(parser); - return parse_symbol(parser, &lex_mode, first ? PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM : PM_LEX_STATE_NONE); + return parse_symbol(parser, &lex_mode, first ? PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM : PM_LEX_STATE_NONE, (uint16_t) (depth + 1)); } case PM_TOKEN_BACK_REFERENCE: parser_lex(parser); @@ -15644,75 +16373,44 @@ parse_alias_argument(pm_parser_t *parser, bool first) { } } -/** - * Return true if any of the visible scopes to the current context are using - * numbered parameters. - */ -static bool -outer_scope_using_numbered_parameters_p(pm_parser_t *parser) { - for (pm_scope_t *scope = parser->current_scope->previous; scope != NULL && !scope->closed; scope = scope->previous) { - if (scope->numbered_parameters > 0) return true; - } - - return false; -} - -/** - * These are the names of the various numbered parameters. We have them here so - * that when we insert them into the constant pool we can use a constant string - * and not have to allocate. - */ -static const char * const pm_numbered_parameter_names[] = { - "_1", "_2", "_3", "_4", "_5", "_6", "_7", "_8", "_9" -}; - /** * Parse an identifier into either a local variable read. If the local variable * is not found, it returns NULL instead. */ -static pm_local_variable_read_node_t * +static pm_node_t * parse_variable(pm_parser_t *parser) { + pm_constant_id_t name_id = pm_parser_constant_id_token(parser, &parser->previous); int depth; - if ((depth = pm_parser_local_depth(parser, &parser->previous)) != -1) { - return pm_local_variable_read_node_create(parser, &parser->previous, (uint32_t) depth); + + if ((depth = pm_parser_local_depth_constant_id(parser, name_id)) != -1) { + return (pm_node_t *) pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, (uint32_t) depth, false); } pm_scope_t *current_scope = parser->current_scope; - if (!current_scope->closed && current_scope->numbered_parameters != PM_SCOPE_NUMBERED_PARAMETERS_DISALLOWED && pm_token_is_numbered_parameter(parser->previous.start, parser->previous.end)) { - // Now that we know we have a numbered parameter, we need to check - // if it's allowed in this context. If it is, then we will create a - // local variable read. If it's not, then we'll create a normal call - // node but add an error. - if (current_scope->parameters & PM_SCOPE_PARAMETERS_ORDINARY) { - pm_parser_err_previous(parser, PM_ERR_NUMBERED_PARAMETER_ORDINARY); - } else if (current_scope->parameters & PM_SCOPE_PARAMETERS_IT) { - pm_parser_err_previous(parser, PM_ERR_NUMBERED_PARAMETER_IT); - } else if (outer_scope_using_numbered_parameters_p(parser)) { - pm_parser_err_previous(parser, PM_ERR_NUMBERED_PARAMETER_OUTER_SCOPE); - } else { - // Indicate that this scope is using numbered params so that child - // scopes cannot. We subtract the value for the character '0' to get - // the actual integer value of the number (only _1 through _9 are - // valid). - int8_t numbered_parameters = (int8_t) (parser->previous.start[1] - '0'); - current_scope->parameters |= PM_SCOPE_PARAMETERS_NUMBERED; - - if (numbered_parameters > current_scope->numbered_parameters) { - current_scope->numbered_parameters = numbered_parameters; + if (!current_scope->closed && !(current_scope->parameters & PM_SCOPE_PARAMETERS_IMPLICIT_DISALLOWED)) { + if (pm_token_is_numbered_parameter(parser->previous.start, parser->previous.end)) { + // When you use a numbered parameter, it implies the existence of + // all of the locals that exist before it. For example, referencing + // _2 means that _1 must exist. Therefore here we loop through all + // of the possibilities and add them into the constant pool. + uint8_t maximum = (uint8_t) (parser->previous.start[1] - '0'); + for (uint8_t number = 1; number <= maximum; number++) { + pm_parser_local_add_constant(parser, pm_numbered_parameter_names[number - 1], 2); } - // When you use a numbered parameter, it implies the existence - // of all of the locals that exist before it. For example, - // referencing _2 means that _1 must exist. Therefore here we - // loop through all of the possibilities and add them into the - // constant pool. - for (int8_t numbered_param = 1; numbered_param <= numbered_parameters - 1; numbered_param++) { - pm_parser_local_add_constant(parser, pm_numbered_parameter_names[numbered_param - 1], 2); + if (!match1(parser, PM_TOKEN_EQUAL)) { + parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_NUMBERED_FOUND; } - // Finally we can create the local variable read node. - pm_constant_id_t name_id = pm_parser_local_add_constant(parser, pm_numbered_parameter_names[numbered_parameters - 1], 2); - return pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, 0, false); + pm_node_t *node = (pm_node_t *) pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, 0, false); + pm_node_list_append(¤t_scope->implicit_parameters, node); + + return node; + } else if ((parser->version != PM_OPTIONS_VERSION_CRUBY_3_3) && pm_token_is_it(parser->previous.start, parser->previous.end)) { + pm_node_t *node = (pm_node_t *) pm_it_local_variable_read_node_create(parser, &parser->previous); + pm_node_list_append(¤t_scope->implicit_parameters, node); + + return node; } } @@ -15727,8 +16425,8 @@ parse_variable_call(pm_parser_t *parser) { pm_node_flags_t flags = 0; if (!match1(parser, PM_TOKEN_PARENTHESIS_LEFT) && (parser->previous.end[-1] != '!') && (parser->previous.end[-1] != '?')) { - pm_local_variable_read_node_t *node = parse_variable(parser); - if (node != NULL) return (pm_node_t *) node; + pm_node_t *node = parse_variable(parser); + if (node != NULL) return node; flags |= PM_CALL_NODE_FLAGS_VARIABLE_CALL; } @@ -15846,77 +16544,310 @@ parse_heredoc_dedent(pm_parser_t *parser, pm_node_list_t *nodes, size_t common_w nodes->size = write_index; } -static pm_node_t * -parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, bool top_pattern, pm_diagnostic_id_t diag_id); - /** - * Add the newly created local to the list of captures for this pattern matching - * expression. If it is duplicated from a previous local, then we'll need to add - * an error to the parser. + * Return a string content token at a particular location that is empty. */ -static void -parse_pattern_capture(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_constant_id_t capture, const pm_location_t *location) { - // Skip this capture if it starts with an underscore. - if (*location->start == '_') return; - - if (pm_constant_id_list_includes(captures, capture)) { - pm_parser_err(parser, location->start, location->end, PM_ERR_PATTERN_CAPTURE_DUPLICATE); - } else { - pm_constant_id_list_append(captures, capture); - } +static pm_token_t +parse_strings_empty_content(const uint8_t *location) { + return (pm_token_t) { .type = PM_TOKEN_STRING_CONTENT, .start = location, .end = location }; } /** - * Accept any number of constants joined by :: delimiters. + * Parse a set of strings that could be concatenated together. */ -static pm_node_t * -parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node_t *node) { - // Now, if there are any :: operators that follow, parse them as constant - // path nodes. - while (accept1(parser, PM_TOKEN_COLON_COLON)) { - pm_token_t delimiter = parser->previous; - expect1(parser, PM_TOKEN_CONSTANT, PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT); - node = (pm_node_t *) pm_constant_path_node_create(parser, node, &delimiter, &parser->previous); - } - - // If there is a [ or ( that follows, then this is part of a larger pattern - // expression. We'll parse the inner pattern here, then modify the returned - // inner pattern with our constant path attached. - if (!match2(parser, PM_TOKEN_BRACKET_LEFT, PM_TOKEN_PARENTHESIS_LEFT)) { - return node; - } - - pm_token_t opening; - pm_token_t closing; - pm_node_t *inner = NULL; +static inline pm_node_t * +parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint16_t depth) { + assert(parser->current.type == PM_TOKEN_STRING_BEGIN); + bool concating = false; - if (accept1(parser, PM_TOKEN_BRACKET_LEFT)) { - opening = parser->previous; - accept1(parser, PM_TOKEN_NEWLINE); + while (match1(parser, PM_TOKEN_STRING_BEGIN)) { + pm_node_t *node = NULL; - if (!accept1(parser, PM_TOKEN_BRACKET_RIGHT)) { - inner = parse_pattern(parser, captures, true, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET); - accept1(parser, PM_TOKEN_NEWLINE); - expect1(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_PATTERN_TERM_BRACKET); - } + // Here we have found a string literal. We'll parse it and add it to + // the list of strings. + const pm_lex_mode_t *lex_mode = parser->lex_modes.current; + assert(lex_mode->mode == PM_LEX_STRING); + bool lex_interpolation = lex_mode->as.string.interpolation; + bool label_allowed = lex_mode->as.string.label_allowed && accepts_label; - closing = parser->previous; - } else { + pm_token_t opening = parser->current; parser_lex(parser); - opening = parser->previous; - accept1(parser, PM_TOKEN_NEWLINE); - if (!accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { - inner = parse_pattern(parser, captures, true, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN); - accept1(parser, PM_TOKEN_NEWLINE); - expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN); - } - - closing = parser->previous; - } + if (match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) { + expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF); + // If we get here, then we have an end immediately after a + // start. In that case we'll create an empty content token and + // return an uninterpolated string. + pm_token_t content = parse_strings_empty_content(parser->previous.start); + pm_string_node_t *string = pm_string_node_create(parser, &opening, &content, &parser->previous); - if (!inner) { - // If there was no inner pattern, then we have something like Foo() or + pm_string_shared_init(&string->unescaped, content.start, content.end); + node = (pm_node_t *) string; + } else if (accept1(parser, PM_TOKEN_LABEL_END)) { + // If we get here, then we have an end of a label immediately + // after a start. In that case we'll create an empty symbol + // node. + pm_token_t content = parse_strings_empty_content(parser->previous.start); + pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &content, &parser->previous); + + pm_string_shared_init(&symbol->unescaped, content.start, content.end); + node = (pm_node_t *) symbol; + + if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL); + } else if (!lex_interpolation) { + // If we don't accept interpolation then we expect the string to + // start with a single string content node. + pm_string_t unescaped; + pm_token_t content; + + if (match1(parser, PM_TOKEN_EOF)) { + unescaped = PM_STRING_EMPTY; + content = not_provided(parser); + } else { + unescaped = parser->current_string; + expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_EXPECT_STRING_CONTENT); + content = parser->previous; + } + + // It is unfortunately possible to have multiple string content + // nodes in a row in the case that there's heredoc content in + // the middle of the string, like this cursed example: + // + // <<-END+'b + // a + // END + // c'+'d' + // + // In that case we need to switch to an interpolated string to + // be able to contain all of the parts. + if (match1(parser, PM_TOKEN_STRING_CONTENT)) { + pm_node_list_t parts = { 0 }; + + pm_token_t delimiters = not_provided(parser); + pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &delimiters, &content, &delimiters, &unescaped); + pm_node_list_append(&parts, part); + + do { + part = (pm_node_t *) pm_string_node_create_current_string(parser, &delimiters, &parser->current, &delimiters); + pm_node_list_append(&parts, part); + parser_lex(parser); + } while (match1(parser, PM_TOKEN_STRING_CONTENT)); + + expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF); + node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous); + + pm_node_list_free(&parts); + } else if (accept1(parser, PM_TOKEN_LABEL_END)) { + node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, true)); + if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL); + } else if (match1(parser, PM_TOKEN_EOF)) { + pm_parser_err_token(parser, &opening, PM_ERR_STRING_LITERAL_EOF); + node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped); + } else if (accept1(parser, PM_TOKEN_STRING_END)) { + node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped); + } else { + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, PM_ERR_STRING_LITERAL_TERM, pm_token_type_human(parser->previous.type)); + parser->previous.start = parser->previous.end; + parser->previous.type = PM_TOKEN_MISSING; + node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped); + } + } else if (match1(parser, PM_TOKEN_STRING_CONTENT)) { + // In this case we've hit string content so we know the string + // at least has something in it. We'll need to check if the + // following token is the end (in which case we can return a + // plain string) or if it's not then it has interpolation. + pm_token_t content = parser->current; + pm_string_t unescaped = parser->current_string; + parser_lex(parser); + + if (match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) { + node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped); + pm_node_flag_set(node, parse_unescaped_encoding(parser)); + + // Kind of odd behavior, but basically if we have an + // unterminated string and it ends in a newline, we back up one + // character so that the error message is on the last line of + // content in the string. + if (!accept1(parser, PM_TOKEN_STRING_END)) { + const uint8_t *location = parser->previous.end; + if (location > parser->start && location[-1] == '\n') location--; + pm_parser_err(parser, location, location, PM_ERR_STRING_LITERAL_EOF); + + parser->previous.start = parser->previous.end; + parser->previous.type = PM_TOKEN_MISSING; + } + } else if (accept1(parser, PM_TOKEN_LABEL_END)) { + node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, true)); + if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL); + } else { + // If we get here, then we have interpolation so we'll need + // to create a string or symbol node with interpolation. + pm_node_list_t parts = { 0 }; + pm_token_t string_opening = not_provided(parser); + pm_token_t string_closing = not_provided(parser); + + pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &string_opening, &parser->previous, &string_closing, &unescaped); + pm_node_flag_set(part, parse_unescaped_encoding(parser)); + pm_node_list_append(&parts, part); + + while (!match3(parser, PM_TOKEN_STRING_END, PM_TOKEN_LABEL_END, PM_TOKEN_EOF)) { + if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) { + pm_node_list_append(&parts, part); + } + } + + if (accept1(parser, PM_TOKEN_LABEL_END)) { + node = (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous); + if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL); + } else if (match1(parser, PM_TOKEN_EOF)) { + pm_parser_err_token(parser, &opening, PM_ERR_STRING_INTERPOLATED_TERM); + node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->current); + } else { + expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM); + node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous); + } + + pm_node_list_free(&parts); + } + } else { + // If we get here, then the first part of the string is not plain + // string content, in which case we need to parse the string as an + // interpolated string. + pm_node_list_t parts = { 0 }; + pm_node_t *part; + + while (!match3(parser, PM_TOKEN_STRING_END, PM_TOKEN_LABEL_END, PM_TOKEN_EOF)) { + if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) { + pm_node_list_append(&parts, part); + } + } + + if (accept1(parser, PM_TOKEN_LABEL_END)) { + node = (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous); + if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL); + } else if (match1(parser, PM_TOKEN_EOF)) { + pm_parser_err_token(parser, &opening, PM_ERR_STRING_INTERPOLATED_TERM); + node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->current); + } else { + expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM); + node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous); + } + + pm_node_list_free(&parts); + } + + if (current == NULL) { + // If the node we just parsed is a symbol node, then we can't + // concatenate it with anything else, so we can now return that + // node. + if (PM_NODE_TYPE_P(node, PM_SYMBOL_NODE) || PM_NODE_TYPE_P(node, PM_INTERPOLATED_SYMBOL_NODE)) { + return node; + } + + // If we don't already have a node, then it's fine and we can just + // set the result to be the node we just parsed. + current = node; + } else { + // Otherwise we need to check the type of the node we just parsed. + // If it cannot be concatenated with the previous node, then we'll + // need to add a syntax error. + if (!PM_NODE_TYPE_P(node, PM_STRING_NODE) && !PM_NODE_TYPE_P(node, PM_INTERPOLATED_STRING_NODE)) { + pm_parser_err_node(parser, node, PM_ERR_STRING_CONCATENATION); + } + + // If we haven't already created our container for concatenation, + // we'll do that now. + if (!concating) { + concating = true; + pm_token_t bounds = not_provided(parser); + + pm_interpolated_string_node_t *container = pm_interpolated_string_node_create(parser, &bounds, NULL, &bounds); + pm_interpolated_string_node_append(container, current); + current = (pm_node_t *) container; + } + + pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, node); + } + } + + return current; +} + +#define PM_PARSE_PATTERN_SINGLE 0 +#define PM_PARSE_PATTERN_TOP 1 +#define PM_PARSE_PATTERN_MULTI 2 + +static pm_node_t * +parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth); + +/** + * Add the newly created local to the list of captures for this pattern matching + * expression. If it is duplicated from a previous local, then we'll need to add + * an error to the parser. + */ +static void +parse_pattern_capture(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_constant_id_t capture, const pm_location_t *location) { + // Skip this capture if it starts with an underscore. + if (*location->start == '_') return; + + if (pm_constant_id_list_includes(captures, capture)) { + pm_parser_err(parser, location->start, location->end, PM_ERR_PATTERN_CAPTURE_DUPLICATE); + } else { + pm_constant_id_list_append(captures, capture); + } +} + +/** + * Accept any number of constants joined by :: delimiters. + */ +static pm_node_t * +parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node_t *node, uint16_t depth) { + // Now, if there are any :: operators that follow, parse them as constant + // path nodes. + while (accept1(parser, PM_TOKEN_COLON_COLON)) { + pm_token_t delimiter = parser->previous; + expect1(parser, PM_TOKEN_CONSTANT, PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT); + node = (pm_node_t *) pm_constant_path_node_create(parser, node, &delimiter, &parser->previous); + } + + // If there is a [ or ( that follows, then this is part of a larger pattern + // expression. We'll parse the inner pattern here, then modify the returned + // inner pattern with our constant path attached. + if (!match2(parser, PM_TOKEN_BRACKET_LEFT, PM_TOKEN_PARENTHESIS_LEFT)) { + return node; + } + + pm_token_t opening; + pm_token_t closing; + pm_node_t *inner = NULL; + + if (accept1(parser, PM_TOKEN_BRACKET_LEFT)) { + opening = parser->previous; + accept1(parser, PM_TOKEN_NEWLINE); + + if (!accept1(parser, PM_TOKEN_BRACKET_RIGHT)) { + inner = parse_pattern(parser, captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET, (uint16_t) (depth + 1)); + accept1(parser, PM_TOKEN_NEWLINE); + expect1(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_PATTERN_TERM_BRACKET); + } + + closing = parser->previous; + } else { + parser_lex(parser); + opening = parser->previous; + accept1(parser, PM_TOKEN_NEWLINE); + + if (!accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { + inner = parse_pattern(parser, captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN, (uint16_t) (depth + 1)); + accept1(parser, PM_TOKEN_NEWLINE); + expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN); + } + + closing = parser->previous; + } + + if (!inner) { + // If there was no inner pattern, then we have something like Foo() or // Foo[]. In that case we'll create an array pattern with no requireds. return (pm_node_t *) pm_array_pattern_node_constant_create(parser, node, &opening, &closing); } @@ -16055,6 +16986,33 @@ parse_pattern_keyword_rest(pm_parser_t *parser, pm_constant_id_list_t *captures) return (pm_node_t *) pm_assoc_splat_node_create(parser, value, &operator); } +/** + * Check that the slice of the source given by the bounds parameters constitutes + * a valid local variable name. + */ +static bool +pm_slice_is_valid_local(const pm_parser_t *parser, const uint8_t *start, const uint8_t *end) { + ptrdiff_t length = end - start; + if (length == 0) return false; + + // First ensure that it starts with a valid identifier starting character. + size_t width = char_is_identifier_start(parser, start); + if (width == 0) return false; + + // Next, ensure that it's not an uppercase character. + if (parser->encoding_changed) { + if (parser->encoding->isupper_char(start, length)) return false; + } else { + if (pm_encoding_utf_8_isupper_char(start, length)) return false; + } + + // Next, iterate through all of the bytes of the string to ensure that they + // are all valid identifier characters. + const uint8_t *cursor = start + width; + while ((cursor < end) && (width = char_is_identifier(parser, cursor))) cursor += width; + return cursor == end; +} + /** * Create an implicit node for the value of a hash pattern that has omitted the * value. This will use an implicit local variable target. @@ -16062,14 +17020,18 @@ parse_pattern_keyword_rest(pm_parser_t *parser, pm_constant_id_list_t *captures) static pm_node_t * parse_pattern_hash_implicit_value(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_symbol_node_t *key) { const pm_location_t *value_loc = &((pm_symbol_node_t *) key)->value_loc; - pm_constant_id_t constant_id = pm_parser_constant_id_location(parser, value_loc->start, value_loc->end); + pm_constant_id_t constant_id = pm_parser_constant_id_location(parser, value_loc->start, value_loc->end); int depth = -1; - if (value_loc->end[-1] == '!' || value_loc->end[-1] == '?') { - pm_parser_err(parser, key->base.location.start, key->base.location.end, PM_ERR_PATTERN_HASH_KEY_LOCALS); - PM_PARSER_ERR_LOCATION_FORMAT(parser, value_loc, PM_ERR_INVALID_LOCAL_VARIABLE_WRITE, (int) (value_loc->end - value_loc->start), (const char *) value_loc->start); - } else { + + if (pm_slice_is_valid_local(parser, value_loc->start, value_loc->end)) { depth = pm_parser_local_depth_constant_id(parser, constant_id); + } else { + pm_parser_err(parser, key->base.location.start, key->base.location.end, PM_ERR_PATTERN_HASH_KEY_LOCALS); + + if ((value_loc->end > value_loc->start) && ((value_loc->end[-1] == '!') || (value_loc->end[-1] == '?'))) { + PM_PARSER_ERR_LOCATION_FORMAT(parser, value_loc, PM_ERR_INVALID_LOCAL_VARIABLE_WRITE, (int) (value_loc->end - value_loc->start), (const char *) value_loc->start); + } } if (depth == -1) { @@ -16093,7 +17055,7 @@ parse_pattern_hash_implicit_value(pm_parser_t *parser, pm_constant_id_list_t *ca */ static void parse_pattern_hash_key(pm_parser_t *parser, pm_static_literals_t *keys, pm_node_t *node) { - if (pm_static_literals_add(&parser->newline_list, parser->start_line, keys, node) != NULL) { + if (pm_static_literals_add(&parser->newline_list, parser->start_line, keys, node, true) != NULL) { pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_KEY_DUPLICATE); } } @@ -16102,7 +17064,7 @@ parse_pattern_hash_key(pm_parser_t *parser, pm_static_literals_t *keys, pm_node_ * Parse a hash pattern. */ static pm_hash_pattern_node_t * -parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node_t *first_node) { +parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node_t *first_node, uint16_t depth) { pm_node_list_t assocs = { 0 }; pm_static_literals_t keys = { 0 }; pm_node_t *rest = NULL; @@ -16117,14 +17079,14 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node parse_pattern_hash_key(parser, &keys, first_node); pm_node_t *value; - if (match7(parser, PM_TOKEN_COMMA, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { + if (match8(parser, PM_TOKEN_COMMA, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_EOF)) { // Otherwise, we will create an implicit local variable // target for the value. value = parse_pattern_hash_implicit_value(parser, captures, (pm_symbol_node_t *) first_node); } else { // Here we have a value for the first assoc in the list, so // we will parse it now. - value = parse_pattern(parser, captures, false, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY); + value = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY, (uint16_t) (depth + 1)); } pm_token_t operator = not_provided(parser); @@ -16139,7 +17101,8 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node // If we get anything else, then this is an error. For this we'll // create a missing node for the value and create an assoc node for // the first node in the list. - pm_parser_err_node(parser, first_node, PM_ERR_PATTERN_HASH_KEY_LABEL); + pm_diagnostic_id_t diag_id = PM_NODE_TYPE_P(first_node, PM_INTERPOLATED_SYMBOL_NODE) ? PM_ERR_PATTERN_HASH_KEY_INTERPOLATED : PM_ERR_PATTERN_HASH_KEY_LABEL; + pm_parser_err_node(parser, first_node, diag_id); pm_token_t operator = not_provided(parser); pm_node_t *value = (pm_node_t *) pm_missing_node_create(parser, first_node->location.start, first_node->location.end); @@ -16153,7 +17116,12 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node // If there are any other assocs, then we'll parse them now. while (accept1(parser, PM_TOKEN_COMMA)) { // Here we need to break to support trailing commas. - if (match6(parser, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { + if (match7(parser, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_EOF)) { + // Trailing commas are not allowed to follow a rest pattern. + if (rest != NULL) { + pm_parser_err_token(parser, &parser->current, PM_ERR_PATTERN_EXPRESSION_AFTER_REST); + } + break; } @@ -16167,8 +17135,20 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node pm_node_list_append(&assocs, assoc); } } else { - expect1(parser, PM_TOKEN_LABEL, PM_ERR_PATTERN_LABEL_AFTER_COMMA); - pm_node_t *key = (pm_node_t *) pm_symbol_node_label_create(parser, &parser->previous); + pm_node_t *key; + + if (match1(parser, PM_TOKEN_STRING_BEGIN)) { + key = parse_strings(parser, NULL, true, (uint16_t) (depth + 1)); + + if (PM_NODE_TYPE_P(key, PM_INTERPOLATED_SYMBOL_NODE)) { + pm_parser_err_node(parser, key, PM_ERR_PATTERN_HASH_KEY_INTERPOLATED); + } else if (!pm_symbol_node_label_p(key)) { + pm_parser_err_node(parser, key, PM_ERR_PATTERN_LABEL_AFTER_COMMA); + } + } else { + expect1(parser, PM_TOKEN_LABEL, PM_ERR_PATTERN_LABEL_AFTER_COMMA); + key = (pm_node_t *) pm_symbol_node_label_create(parser, &parser->previous); + } parse_pattern_hash_key(parser, &keys, key); pm_node_t *value = NULL; @@ -16176,7 +17156,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node if (match7(parser, PM_TOKEN_COMMA, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { value = parse_pattern_hash_implicit_value(parser, captures, (pm_symbol_node_t *) key); } else { - value = parse_pattern(parser, captures, false, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY); + value = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY, (uint16_t) (depth + 1)); } pm_token_t operator = not_provided(parser); @@ -16201,7 +17181,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node * Parse a pattern expression primitive. */ static pm_node_t * -parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_diagnostic_id_t diag_id) { +parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_diagnostic_id_t diag_id, uint16_t depth) { switch (parser->current.type) { case PM_TOKEN_IDENTIFIER: case PM_TOKEN_METHOD_NAME: { @@ -16233,7 +17213,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm // Otherwise, we'll parse the inner pattern, then deal with it depending // on the type it returns. - pm_node_t *inner = parse_pattern(parser, captures, true, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET); + pm_node_t *inner = parse_pattern(parser, captures, PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET, (uint16_t) (depth + 1)); accept1(parser, PM_TOKEN_NEWLINE); expect1(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_PATTERN_TERM_BRACKET); @@ -16300,18 +17280,18 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm first_node = parse_pattern_keyword_rest(parser, captures); break; case PM_TOKEN_STRING_BEGIN: - first_node = parse_expression(parser, PM_BINDING_POWER_MAX, false, PM_ERR_PATTERN_HASH_KEY); + first_node = parse_expression(parser, PM_BINDING_POWER_MAX, false, true, PM_ERR_PATTERN_HASH_KEY_LABEL, (uint16_t) (depth + 1)); break; default: { + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_PATTERN_HASH_KEY, pm_token_type_human(parser->current.type)); parser_lex(parser); - pm_parser_err_previous(parser, PM_ERR_PATTERN_HASH_KEY); first_node = (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end); break; } } - node = parse_pattern_hash(parser, captures, first_node); + node = parse_pattern_hash(parser, captures, first_node, (uint16_t) (depth + 1)); accept1(parser, PM_TOKEN_NEWLINE); expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_PATTERN_TERM_BRACE); @@ -16336,7 +17316,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm // expression as the right side of the range. switch (parser->current.type) { case PM_CASE_PRIMITIVE: { - pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE); + pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, false, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE, (uint16_t) (depth + 1)); return (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right); } default: { @@ -16347,7 +17327,10 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm } } case PM_CASE_PRIMITIVE: { - pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_MAX, false, diag_id); + pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_MAX, false, true, diag_id, (uint16_t) (depth + 1)); + + // If we found a label, we need to immediately return to the caller. + if (pm_symbol_node_label_p(node)) return node; // Now that we have a primitive, we need to check if it's part of a range. if (accept2(parser, PM_TOKEN_DOT_DOT, PM_TOKEN_DOT_DOT_DOT)) { @@ -16358,7 +17341,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm // node. Otherwise, we'll create an endless range. switch (parser->current.type) { case PM_CASE_PRIMITIVE: { - pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE); + pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, false, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE, (uint16_t) (depth + 1)); return (pm_node_t *) pm_range_node_create(parser, node, &operator, right); } default: @@ -16380,19 +17363,8 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm pm_node_t *variable = (pm_node_t *) parse_variable(parser); if (variable == NULL) { - if ( - (parser->version != PM_OPTIONS_VERSION_CRUBY_3_3) && - !parser->current_scope->closed && - (parser->current_scope->numbered_parameters != PM_SCOPE_NUMBERED_PARAMETERS_DISALLOWED) && - pm_token_is_it(parser->previous.start, parser->previous.end) - ) { - pm_local_variable_read_node_t *read = pm_local_variable_read_node_create_it(parser, &parser->previous); - if (read == NULL) read = pm_local_variable_read_node_create(parser, &parser->previous, 0); - variable = (pm_node_t *) read; - } else { - PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, parser->previous, PM_ERR_NO_LOCAL_VARIABLE); - variable = (pm_node_t *) pm_local_variable_read_node_missing_create(parser, &parser->previous, 0); - } + PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, parser->previous, PM_ERR_NO_LOCAL_VARIABLE); + variable = (pm_node_t *) pm_local_variable_read_node_missing_create(parser, &parser->previous, 0); } return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable); @@ -16434,7 +17406,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm pm_token_t lparen = parser->current; parser_lex(parser); - pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN); + pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, true, false, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN, (uint16_t) (depth + 1)); parser->pattern_matching_newlines = previous_pattern_matching_newlines; accept1(parser, PM_TOKEN_NEWLINE); @@ -16457,14 +17429,14 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm expect1(parser, PM_TOKEN_CONSTANT, PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT); pm_constant_path_node_t *node = pm_constant_path_node_create(parser, NULL, &delimiter, &parser->previous); - return parse_pattern_constant_path(parser, captures, (pm_node_t *) node); + return parse_pattern_constant_path(parser, captures, (pm_node_t *) node, (uint16_t) (depth + 1)); } case PM_TOKEN_CONSTANT: { pm_token_t constant = parser->current; parser_lex(parser); pm_node_t *node = (pm_node_t *) pm_constant_read_node_create(parser, &constant); - return parse_pattern_constant_path(parser, captures, node); + return parse_pattern_constant_path(parser, captures, node, (uint16_t) (depth + 1)); } default: pm_parser_err_current(parser, diag_id); @@ -16477,10 +17449,10 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm * assignment. */ static pm_node_t * -parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_diagnostic_id_t diag_id) { - pm_node_t *node = NULL; +parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node_t *first_node, pm_diagnostic_id_t diag_id, uint16_t depth) { + pm_node_t *node = first_node; - do { + while ((node == NULL) || accept1(parser, PM_TOKEN_PIPE)) { pm_token_t operator = parser->previous; switch (parser->current.type) { @@ -16494,19 +17466,20 @@ parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, p case PM_TOKEN_UDOT_DOT_DOT: case PM_CASE_PRIMITIVE: { if (node == NULL) { - node = parse_pattern_primitive(parser, captures, diag_id); + node = parse_pattern_primitive(parser, captures, diag_id, (uint16_t) (depth + 1)); } else { - pm_node_t *right = parse_pattern_primitive(parser, captures, PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE); + pm_node_t *right = parse_pattern_primitive(parser, captures, PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE, (uint16_t) (depth + 1)); node = (pm_node_t *) pm_alternation_pattern_node_create(parser, node, right, &operator); } break; } - case PM_TOKEN_PARENTHESIS_LEFT: { + case PM_TOKEN_PARENTHESIS_LEFT: + case PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES: { pm_token_t opening = parser->current; parser_lex(parser); - pm_node_t *body = parse_pattern(parser, captures, false, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN); + pm_node_t *body = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN, (uint16_t) (depth + 1)); accept1(parser, PM_TOKEN_NEWLINE); expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN); pm_node_t *right = (pm_node_t *) pm_parentheses_node_create(parser, &opening, body, &parser->previous); @@ -16532,7 +17505,7 @@ parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, p break; } } - } while (accept1(parser, PM_TOKEN_PIPE)); + } // If we have an =>, then we are assigning this pattern to a variable. // In this case we should create an assignment node. @@ -16548,7 +17521,7 @@ parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, p } parse_pattern_capture(parser, captures, constant_id, &PM_LOCATION_TOKEN_VALUE(&parser->previous)); - pm_node_t *target = (pm_node_t *) pm_local_variable_target_node_create( + pm_local_variable_target_node_t *target = pm_local_variable_target_node_create( parser, &PM_LOCATION_TOKEN_VALUE(&parser->previous), constant_id, @@ -16565,7 +17538,7 @@ parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, p * Parse a pattern matching expression. */ static pm_node_t * -parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, bool top_pattern, pm_diagnostic_id_t diag_id) { +parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth) { pm_node_t *node = NULL; bool leading_rest = false; @@ -16575,329 +17548,159 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, bool top_pat case PM_TOKEN_LABEL: { parser_lex(parser); pm_node_t *key = (pm_node_t *) pm_symbol_node_label_create(parser, &parser->previous); - return (pm_node_t *) parse_pattern_hash(parser, captures, key); - } - case PM_TOKEN_USTAR_STAR: { - node = parse_pattern_keyword_rest(parser, captures); - return (pm_node_t *) parse_pattern_hash(parser, captures, node); - } - case PM_TOKEN_USTAR: { - if (top_pattern) { - parser_lex(parser); - node = (pm_node_t *) parse_pattern_rest(parser, captures); - leading_rest = true; - break; - } - } - /* fallthrough */ - default: - node = parse_pattern_primitives(parser, captures, diag_id); - break; - } + node = (pm_node_t *) parse_pattern_hash(parser, captures, key, (uint16_t) (depth + 1)); - // If we got a dynamic label symbol, then we need to treat it like the - // beginning of a hash pattern. - if (pm_symbol_node_label_p(node)) { - return (pm_node_t *) parse_pattern_hash(parser, captures, node); - } - - if (top_pattern && match1(parser, PM_TOKEN_COMMA)) { - // If we have a comma, then we are now parsing either an array pattern or a - // find pattern. We need to parse all of the patterns, put them into a big - // list, and then determine which type of node we have. - pm_node_list_t nodes = { 0 }; - pm_node_list_append(&nodes, node); - - // Gather up all of the patterns into the list. - while (accept1(parser, PM_TOKEN_COMMA)) { - // Break early here in case we have a trailing comma. - if (match6(parser, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_EOF)) { - node = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous); - pm_node_list_append(&nodes, node); - break; + if (!(flags & PM_PARSE_PATTERN_TOP)) { + pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_IMPLICIT); } - if (accept1(parser, PM_TOKEN_USTAR)) { - node = (pm_node_t *) parse_pattern_rest(parser, captures); - - // If we have already parsed a splat pattern, then this is an error. We - // will continue to parse the rest of the patterns, but we will indicate - // it as an error. - if (trailing_rest) { - pm_parser_err_previous(parser, PM_ERR_PATTERN_REST); - } + return node; + } + case PM_TOKEN_USTAR_STAR: { + node = parse_pattern_keyword_rest(parser, captures); + node = (pm_node_t *) parse_pattern_hash(parser, captures, node, (uint16_t) (depth + 1)); - trailing_rest = true; - } else { - node = parse_pattern_primitives(parser, captures, PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA); + if (!(flags & PM_PARSE_PATTERN_TOP)) { + pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_IMPLICIT); } - pm_node_list_append(&nodes, node); + return node; } + case PM_TOKEN_STRING_BEGIN: { + // We need special handling for string beginnings because they could + // be dynamic symbols leading to hash patterns. + node = parse_pattern_primitive(parser, captures, diag_id, (uint16_t) (depth + 1)); - // If the first pattern and the last pattern are rest patterns, then we will - // call this a find pattern, regardless of how many rest patterns are in - // between because we know we already added the appropriate errors. - // Otherwise we will create an array pattern. - if (PM_NODE_TYPE_P(nodes.nodes[0], PM_SPLAT_NODE) && PM_NODE_TYPE_P(nodes.nodes[nodes.size - 1], PM_SPLAT_NODE)) { - node = (pm_node_t *) pm_find_pattern_node_create(parser, &nodes); - } else { - node = (pm_node_t *) pm_array_pattern_node_node_list_create(parser, &nodes); - } + if (pm_symbol_node_label_p(node)) { + node = (pm_node_t *) parse_pattern_hash(parser, captures, node, (uint16_t) (depth + 1)); - xfree(nodes.nodes); - } else if (leading_rest) { - // Otherwise, if we parsed a single splat pattern, then we know we have an - // array pattern, so we can go ahead and create that node. - node = (pm_node_t *) pm_array_pattern_node_rest_create(parser, node); - } + if (!(flags & PM_PARSE_PATTERN_TOP)) { + pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_IMPLICIT); + } - return node; -} + return node; + } -/** - * Incorporate a negative sign into a numeric node by subtracting 1 character - * from its start bounds. If it's a compound node, then we will recursively - * apply this function to its value. - */ -static inline void -parse_negative_numeric(pm_node_t *node) { - switch (PM_NODE_TYPE(node)) { - case PM_INTEGER_NODE: { - pm_integer_node_t *cast = (pm_integer_node_t *) node; - cast->base.location.start--; - cast->value.negative = true; - break; - } - case PM_FLOAT_NODE: { - pm_float_node_t *cast = (pm_float_node_t *) node; - cast->base.location.start--; - cast->value = -cast->value; + node = parse_pattern_primitives(parser, captures, node, diag_id, (uint16_t) (depth + 1)); break; } - case PM_RATIONAL_NODE: - node->location.start--; - parse_negative_numeric(((pm_rational_node_t *) node)->numeric); - break; - case PM_IMAGINARY_NODE: - node->location.start--; - parse_negative_numeric(((pm_imaginary_node_t *) node)->numeric); - break; - default: - assert(false && "unreachable"); - break; - } -} - -/** - * Return a string content token at a particular location that is empty. - */ -static pm_token_t -parse_strings_empty_content(const uint8_t *location) { - return (pm_token_t) { .type = PM_TOKEN_STRING_CONTENT, .start = location, .end = location }; -} - -/** - * Parse a set of strings that could be concatenated together. - */ -static inline pm_node_t * -parse_strings(pm_parser_t *parser, pm_node_t *current) { - assert(parser->current.type == PM_TOKEN_STRING_BEGIN); - - bool concating = false; - bool state_is_arg_labeled = lex_state_arg_labeled_p(parser); - - while (match1(parser, PM_TOKEN_STRING_BEGIN)) { - pm_node_t *node = NULL; - - // Here we have found a string literal. We'll parse it and add it to - // the list of strings. - const pm_lex_mode_t *lex_mode = parser->lex_modes.current; - assert(lex_mode->mode == PM_LEX_STRING); - bool lex_interpolation = lex_mode->as.string.interpolation; - - pm_token_t opening = parser->current; - parser_lex(parser); - - if (match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) { - expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF); - // If we get here, then we have an end immediately after a - // start. In that case we'll create an empty content token and - // return an uninterpolated string. - pm_token_t content = parse_strings_empty_content(parser->previous.start); - pm_string_node_t *string = pm_string_node_create(parser, &opening, &content, &parser->previous); - - pm_string_shared_init(&string->unescaped, content.start, content.end); - node = (pm_node_t *) string; - } else if (accept1(parser, PM_TOKEN_LABEL_END)) { - // If we get here, then we have an end of a label immediately - // after a start. In that case we'll create an empty symbol - // node. - pm_token_t content = parse_strings_empty_content(parser->previous.start); - pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &content, &parser->previous); - - pm_string_shared_init(&symbol->unescaped, content.start, content.end); - node = (pm_node_t *) symbol; - } else if (!lex_interpolation) { - // If we don't accept interpolation then we expect the string to - // start with a single string content node. - pm_string_t unescaped; - pm_token_t content; - if (match1(parser, PM_TOKEN_EOF)) { - unescaped = PM_STRING_EMPTY; - content = not_provided(parser); - } else { - unescaped = parser->current_string; - expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_EXPECT_STRING_CONTENT); - content = parser->previous; - } - - // It is unfortunately possible to have multiple string content - // nodes in a row in the case that there's heredoc content in - // the middle of the string, like this cursed example: - // - // <<-END+'b - // a - // END - // c'+'d' - // - // In that case we need to switch to an interpolated string to - // be able to contain all of the parts. - if (match1(parser, PM_TOKEN_STRING_CONTENT)) { - pm_node_list_t parts = { 0 }; - - pm_token_t delimiters = not_provided(parser); - pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &delimiters, &content, &delimiters, &unescaped); - pm_node_list_append(&parts, part); - - do { - part = (pm_node_t *) pm_string_node_create_current_string(parser, &delimiters, &parser->current, &delimiters); - pm_node_list_append(&parts, part); - parser_lex(parser); - } while (match1(parser, PM_TOKEN_STRING_CONTENT)); - - expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF); - node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous); - - pm_node_list_free(&parts); - } else if (accept1(parser, PM_TOKEN_LABEL_END) && !state_is_arg_labeled) { - node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, true)); - } else if (match1(parser, PM_TOKEN_EOF)) { - pm_parser_err_token(parser, &opening, PM_ERR_STRING_LITERAL_EOF); - node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped); - } else if (accept1(parser, PM_TOKEN_STRING_END)) { - node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped); - } else { - PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, PM_ERR_STRING_LITERAL_TERM, pm_token_type_human(parser->previous.type)); - parser->previous.start = parser->previous.end; - parser->previous.type = PM_TOKEN_MISSING; - node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped); - } - } else if (match1(parser, PM_TOKEN_STRING_CONTENT)) { - // In this case we've hit string content so we know the string - // at least has something in it. We'll need to check if the - // following token is the end (in which case we can return a - // plain string) or if it's not then it has interpolation. - pm_token_t content = parser->current; - pm_string_t unescaped = parser->current_string; - parser_lex(parser); - - if (match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) { - node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped); - pm_node_flag_set(node, parse_unescaped_encoding(parser)); - expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF); - } else if (accept1(parser, PM_TOKEN_LABEL_END)) { - node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, true)); - } else { - // If we get here, then we have interpolation so we'll need - // to create a string or symbol node with interpolation. - pm_node_list_t parts = { 0 }; - pm_token_t string_opening = not_provided(parser); - pm_token_t string_closing = not_provided(parser); - - pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &string_opening, &parser->previous, &string_closing, &unescaped); - pm_node_flag_set(part, parse_unescaped_encoding(parser)); - pm_node_list_append(&parts, part); + case PM_TOKEN_USTAR: { + if (flags & (PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI)) { + parser_lex(parser); + node = (pm_node_t *) parse_pattern_rest(parser, captures); + leading_rest = true; + break; + } + } + /* fallthrough */ + default: + node = parse_pattern_primitives(parser, captures, NULL, diag_id, (uint16_t) (depth + 1)); + break; + } - while (!match3(parser, PM_TOKEN_STRING_END, PM_TOKEN_LABEL_END, PM_TOKEN_EOF)) { - if ((part = parse_string_part(parser)) != NULL) { - pm_node_list_append(&parts, part); - } - } + // If we got a dynamic label symbol, then we need to treat it like the + // beginning of a hash pattern. + if (pm_symbol_node_label_p(node)) { + return (pm_node_t *) parse_pattern_hash(parser, captures, node, (uint16_t) (depth + 1)); + } - if (accept1(parser, PM_TOKEN_LABEL_END) && !state_is_arg_labeled) { - node = (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous); - } else if (match1(parser, PM_TOKEN_EOF)) { - pm_parser_err_token(parser, &opening, PM_ERR_STRING_INTERPOLATED_TERM); - node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->current); - } else { - expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM); - node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous); - } + if ((flags & PM_PARSE_PATTERN_MULTI) && match1(parser, PM_TOKEN_COMMA)) { + // If we have a comma, then we are now parsing either an array pattern + // or a find pattern. We need to parse all of the patterns, put them + // into a big list, and then determine which type of node we have. + pm_node_list_t nodes = { 0 }; + pm_node_list_append(&nodes, node); - pm_node_list_free(&parts); + // Gather up all of the patterns into the list. + while (accept1(parser, PM_TOKEN_COMMA)) { + // Break early here in case we have a trailing comma. + if (match6(parser, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE, PM_TOKEN_EOF)) { + node = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous); + pm_node_list_append(&nodes, node); + trailing_rest = true; + break; } - } else { - // If we get here, then the first part of the string is not plain - // string content, in which case we need to parse the string as an - // interpolated string. - pm_node_list_t parts = { 0 }; - pm_node_t *part; - while (!match3(parser, PM_TOKEN_STRING_END, PM_TOKEN_LABEL_END, PM_TOKEN_EOF)) { - if ((part = parse_string_part(parser)) != NULL) { - pm_node_list_append(&parts, part); + if (accept1(parser, PM_TOKEN_USTAR)) { + node = (pm_node_t *) parse_pattern_rest(parser, captures); + + // If we have already parsed a splat pattern, then this is an + // error. We will continue to parse the rest of the patterns, + // but we will indicate it as an error. + if (trailing_rest) { + pm_parser_err_previous(parser, PM_ERR_PATTERN_REST); } - } - if (accept1(parser, PM_TOKEN_LABEL_END)) { - node = (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous); - } else if (match1(parser, PM_TOKEN_EOF)) { - pm_parser_err_token(parser, &opening, PM_ERR_STRING_INTERPOLATED_TERM); - node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->current); + trailing_rest = true; } else { - expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM); - node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous); + node = parse_pattern_primitives(parser, captures, NULL, PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1)); } - pm_node_list_free(&parts); + pm_node_list_append(&nodes, node); } - if (current == NULL) { - // If the node we just parsed is a symbol node, then we can't - // concatenate it with anything else, so we can now return that - // node. - if (PM_NODE_TYPE_P(node, PM_SYMBOL_NODE) || PM_NODE_TYPE_P(node, PM_INTERPOLATED_SYMBOL_NODE)) { - return node; - } + // If the first pattern and the last pattern are rest patterns, then we + // will call this a find pattern, regardless of how many rest patterns + // are in between because we know we already added the appropriate + // errors. Otherwise we will create an array pattern. + if (leading_rest && PM_NODE_TYPE_P(nodes.nodes[nodes.size - 1], PM_SPLAT_NODE)) { + node = (pm_node_t *) pm_find_pattern_node_create(parser, &nodes); - // If we don't already have a node, then it's fine and we can just - // set the result to be the node we just parsed. - current = node; + if (nodes.size == 2) { + pm_parser_err_node(parser, node, PM_ERR_PATTERN_FIND_MISSING_INNER); + } } else { - // Otherwise we need to check the type of the node we just parsed. - // If it cannot be concatenated with the previous node, then we'll - // need to add a syntax error. - if (!PM_NODE_TYPE_P(node, PM_STRING_NODE) && !PM_NODE_TYPE_P(node, PM_INTERPOLATED_STRING_NODE)) { - pm_parser_err_node(parser, node, PM_ERR_STRING_CONCATENATION); + node = (pm_node_t *) pm_array_pattern_node_node_list_create(parser, &nodes); + + if (leading_rest && trailing_rest) { + pm_parser_err_node(parser, node, PM_ERR_PATTERN_ARRAY_MULTIPLE_RESTS); } + } - // If we haven't already created our container for concatenation, - // we'll do that now. - if (!concating) { - concating = true; - pm_token_t bounds = not_provided(parser); + xfree(nodes.nodes); + } else if (leading_rest) { + // Otherwise, if we parsed a single splat pattern, then we know we have + // an array pattern, so we can go ahead and create that node. + node = (pm_node_t *) pm_array_pattern_node_rest_create(parser, node); + } - pm_interpolated_string_node_t *container = pm_interpolated_string_node_create(parser, &bounds, NULL, &bounds); - pm_interpolated_string_node_append(container, current); - current = (pm_node_t *) container; - } + return node; +} - pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, node); +/** + * Incorporate a negative sign into a numeric node by subtracting 1 character + * from its start bounds. If it's a compound node, then we will recursively + * apply this function to its value. + */ +static inline void +parse_negative_numeric(pm_node_t *node) { + switch (PM_NODE_TYPE(node)) { + case PM_INTEGER_NODE: { + pm_integer_node_t *cast = (pm_integer_node_t *) node; + cast->base.location.start--; + cast->value.negative = true; + break; + } + case PM_FLOAT_NODE: { + pm_float_node_t *cast = (pm_float_node_t *) node; + cast->base.location.start--; + cast->value = -cast->value; + break; + } + case PM_RATIONAL_NODE: { + pm_rational_node_t *cast = (pm_rational_node_t *) node; + cast->base.location.start--; + cast->numerator.negative = true; + break; } + case PM_IMAGINARY_NODE: + node->location.start--; + parse_negative_numeric(((pm_imaginary_node_t *) node)->numeric); + break; + default: + assert(false && "unreachable"); + break; } - - return current; } /** @@ -16912,11 +17715,21 @@ pm_parser_err_prefix(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, diag_id, pm_token_type_human(parser->previous.type)); break; } + case PM_ERR_HASH_VALUE: + case PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR: { + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, diag_id, pm_token_type_human(parser->current.type)); + break; + } case PM_ERR_UNARY_RECEIVER: { const char *human = (parser->current.type == PM_TOKEN_EOF ? "end-of-input" : pm_token_type_human(parser->current.type)); PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, diag_id, human, parser->previous.start[0]); break; } + case PM_ERR_UNARY_DISALLOWED: + case PM_ERR_EXPECT_ARGUMENT: { + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, diag_id, pm_token_type_human(parser->current.type)); + break; + } default: pm_parser_err_previous(parser, diag_id); break; @@ -16928,7 +17741,12 @@ pm_parser_err_prefix(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { */ static void parse_retry(pm_parser_t *parser, const pm_node_t *node) { +#define CONTEXT_NONE 0 +#define CONTEXT_THROUGH_ENSURE 1 +#define CONTEXT_THROUGH_ELSE 2 + pm_context_node_t *context_node = parser->current_context; + int context = CONTEXT_NONE; while (context_node != NULL) { switch (context_node->context) { @@ -16952,7 +17770,13 @@ parse_retry(pm_parser_t *parser, const pm_node_t *node) { case PM_CONTEXT_SCLASS: // These are the bad cases. We're not allowed to have a retry in // these contexts. - pm_parser_err_node(parser, node, PM_ERR_INVALID_RETRY_WITHOUT_RESCUE); + if (context == CONTEXT_NONE) { + pm_parser_err_node(parser, node, PM_ERR_INVALID_RETRY_WITHOUT_RESCUE); + } else if (context == CONTEXT_THROUGH_ENSURE) { + pm_parser_err_node(parser, node, PM_ERR_INVALID_RETRY_AFTER_ENSURE); + } else if (context == CONTEXT_THROUGH_ELSE) { + pm_parser_err_node(parser, node, PM_ERR_INVALID_RETRY_AFTER_ELSE); + } return; case PM_CONTEXT_BEGIN_ELSE: case PM_CONTEXT_BLOCK_ELSE: @@ -16963,8 +17787,8 @@ parse_retry(pm_parser_t *parser, const pm_node_t *node) { case PM_CONTEXT_SCLASS_ELSE: // These are also bad cases, but with a more specific error // message indicating the else. - pm_parser_err_node(parser, node, PM_ERR_INVALID_RETRY_AFTER_ELSE); - return; + context = CONTEXT_THROUGH_ELSE; + break; case PM_CONTEXT_BEGIN_ENSURE: case PM_CONTEXT_BLOCK_ENSURE: case PM_CONTEXT_CLASS_ENSURE: @@ -16974,8 +17798,8 @@ parse_retry(pm_parser_t *parser, const pm_node_t *node) { case PM_CONTEXT_SCLASS_ENSURE: // These are also bad cases, but with a more specific error // message indicating the ensure. - pm_parser_err_node(parser, node, PM_ERR_INVALID_RETRY_AFTER_ENSURE); - return; + context = CONTEXT_THROUGH_ENSURE; + break; case PM_CONTEXT_NONE: // This case should never happen. assert(false && "unreachable"); @@ -16994,6 +17818,8 @@ parse_retry(pm_parser_t *parser, const pm_node_t *node) { case PM_CONTEXT_IF: case PM_CONTEXT_LAMBDA_BRACES: case PM_CONTEXT_LAMBDA_DO_END: + case PM_CONTEXT_LOOP_PREDICATE: + case PM_CONTEXT_MULTI_TARGET: case PM_CONTEXT_PARENS: case PM_CONTEXT_POSTEXE: case PM_CONTEXT_PREDICATE: @@ -17008,6 +17834,10 @@ parse_retry(pm_parser_t *parser, const pm_node_t *node) { context_node = context_node->prev; } + +#undef CONTEXT_NONE +#undef CONTEXT_ENSURE +#undef CONTEXT_ELSE } /** @@ -17072,6 +17902,8 @@ parse_yield(pm_parser_t *parser, const pm_node_t *node) { case PM_CONTEXT_LAMBDA_ELSE: case PM_CONTEXT_LAMBDA_ENSURE: case PM_CONTEXT_LAMBDA_RESCUE: + case PM_CONTEXT_LOOP_PREDICATE: + case PM_CONTEXT_MULTI_TARGET: case PM_CONTEXT_PARENS: case PM_CONTEXT_POSTEXE: case PM_CONTEXT_PREDICATE: @@ -17090,11 +17922,68 @@ parse_yield(pm_parser_t *parser, const pm_node_t *node) { } } +/** + * This struct is used to pass information between the regular expression parser + * and the error callback. + */ +typedef struct { + /** The parser that we are parsing the regular expression for. */ + pm_parser_t *parser; + + /** The start of the regular expression. */ + const uint8_t *start; + + /** The end of the regular expression. */ + const uint8_t *end; + + /** + * Whether or not the source of the regular expression is shared. This + * impacts the location of error messages, because if it is shared then we + * can use the location directly and if it is not, then we use the bounds of + * the regular expression itself. + */ + bool shared; +} parse_regular_expression_error_data_t; + +/** + * This callback is called when the regular expression parser encounters a + * syntax error. + */ +static void +parse_regular_expression_error(const uint8_t *start, const uint8_t *end, const char *message, void *data) { + parse_regular_expression_error_data_t *callback_data = (parse_regular_expression_error_data_t *) data; + pm_location_t location; + + if (callback_data->shared) { + location = (pm_location_t) { .start = start, .end = end }; + } else { + location = (pm_location_t) { .start = callback_data->start, .end = callback_data->end }; + } + + PM_PARSER_ERR_FORMAT(callback_data->parser, location.start, location.end, PM_ERR_REGEXP_PARSE_ERROR, message); +} + +/** + * Parse the errors for the regular expression and add them to the parser. + */ +static void +parse_regular_expression_errors(pm_parser_t *parser, pm_regular_expression_node_t *node) { + const pm_string_t *unescaped = &node->unescaped; + parse_regular_expression_error_data_t error_data = { + .parser = parser, + .start = node->base.location.start, + .end = node->base.location.end, + .shared = unescaped->type == PM_STRING_SHARED + }; + + pm_regexp_parse(parser, pm_string_source(unescaped), pm_string_length(unescaped), PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED), NULL, NULL, parse_regular_expression_error, &error_data); +} + /** * Parse an expression that begins with the previous node that we just lexed. */ static inline pm_node_t * -parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) { +parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth) { switch (parser->current.type) { case PM_TOKEN_BRACKET_LEFT_ARRAY: { parser_lex(parser); @@ -17104,14 +17993,31 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b bool parsed_bare_hash = false; while (!match2(parser, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_EOF)) { + bool accepted_newline = accept1(parser, PM_TOKEN_NEWLINE); + // Handle the case where we don't have a comma and we have a // newline followed by a right bracket. - if (accept1(parser, PM_TOKEN_NEWLINE) && match1(parser, PM_TOKEN_BRACKET_RIGHT)) { + if (accepted_newline && match1(parser, PM_TOKEN_BRACKET_RIGHT)) { break; } - if (pm_array_node_size(array) != 0) { - expect1(parser, PM_TOKEN_COMMA, PM_ERR_ARRAY_SEPARATOR); + // Ensure that we have a comma between elements in the array. + if (array->elements.size > 0) { + if (accept1(parser, PM_TOKEN_COMMA)) { + // If there was a comma but we also accepts a newline, + // then this is a syntax error. + if (accepted_newline) { + pm_parser_err_previous(parser, PM_ERR_INVALID_COMMA); + } + } else { + // If there was no comma, then we need to add a syntax + // error. + const uint8_t *location = parser->previous.end; + PM_PARSER_ERR_FORMAT(parser, location, location, PM_ERR_ARRAY_SEPARATOR, pm_token_type_human(parser->current.type)); + + parser->previous.start = location; + parser->previous.type = PM_TOKEN_MISSING; + } } // If we have a right bracket immediately following a comma, @@ -17128,7 +18034,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (match3(parser, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_COMMA, PM_TOKEN_EOF)) { pm_parser_scope_forwarding_positionals_check(parser, &operator); } else { - expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_ARRAY_EXPRESSION_AFTER_STAR); + expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_ARRAY_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); } element = (pm_node_t *) pm_splat_node_create(parser, &operator, expression); @@ -17141,13 +18047,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_static_literals_t hash_keys = { 0 }; if (!match8(parser, PM_TOKEN_EOF, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_EOF, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_KEYWORD_DO, PM_TOKEN_PARENTHESIS_RIGHT)) { - parse_assocs(parser, &hash_keys, element); + parse_assocs(parser, &hash_keys, element, (uint16_t) (depth + 1)); } pm_static_literals_free(&hash_keys); parsed_bare_hash = true; } else { - element = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_ARRAY_EXPRESSION); + element = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, true, PM_ERR_ARRAY_EXPRESSION, (uint16_t) (depth + 1)); if (pm_symbol_node_label_p(element) || accept1(parser, PM_TOKEN_EQUAL_GREATER)) { if (parsed_bare_hash) { @@ -17165,13 +18071,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b operator = not_provided(parser); } - pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_VALUE); + pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); pm_node_t *assoc = (pm_node_t *) pm_assoc_node_create(parser, element, &operator, value); pm_keyword_hash_node_elements_append(hash, assoc); element = (pm_node_t *) hash; if (accept1(parser, PM_TOKEN_COMMA) && !match1(parser, PM_TOKEN_BRACKET_RIGHT)) { - parse_assocs(parser, &hash_keys, element); + parse_assocs(parser, &hash_keys, element, (uint16_t) (depth + 1)); } pm_static_literals_free(&hash_keys); @@ -17184,7 +18090,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } accept1(parser, PM_TOKEN_NEWLINE); - expect1(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_ARRAY_TERM); + + if (!accept1(parser, PM_TOKEN_BRACKET_RIGHT)) { + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_ARRAY_TERM, pm_token_type_human(parser->current.type)); + parser->previous.start = parser->previous.end; + parser->previous.type = PM_TOKEN_MISSING; + } + pm_array_node_close_set(array, &parser->previous); pm_accepts_block_stack_pop(parser); @@ -17215,7 +18127,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // of statements within the parentheses. pm_accepts_block_stack_push(parser, true); context_push(parser, PM_CONTEXT_PARENS); - pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_CANNOT_PARSE_EXPRESSION); + pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, false, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1)); context_pop(parser); // Determine if this statement is followed by a terminator. In the @@ -17261,21 +18173,39 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b multi_target->base.location.start = lparen_loc.start; multi_target->base.location.end = rparen_loc.end; - if (match1(parser, PM_TOKEN_COMMA)) { - if (binding_power == PM_BINDING_POWER_STATEMENT) { - return parse_targets_validate(parser, (pm_node_t *) multi_target, PM_BINDING_POWER_INDEX); - } - return (pm_node_t *) multi_target; + pm_node_t *result; + if (match1(parser, PM_TOKEN_COMMA) && (binding_power == PM_BINDING_POWER_STATEMENT)) { + result = parse_targets(parser, (pm_node_t *) multi_target, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1)); + accept1(parser, PM_TOKEN_NEWLINE); + } else { + result = (pm_node_t *) multi_target; + } + + if (context_p(parser, PM_CONTEXT_MULTI_TARGET)) { + // All set, this is explicitly allowed by the parent + // context. + } else if (context_p(parser, PM_CONTEXT_FOR_INDEX) && match1(parser, PM_TOKEN_KEYWORD_IN)) { + // All set, we're inside a for loop and we're parsing + // multiple targets. + } else if (binding_power != PM_BINDING_POWER_STATEMENT) { + // Multi targets are not allowed when it's not a + // statement level. + pm_parser_err_node(parser, result, PM_ERR_WRITE_TARGET_UNEXPECTED); + } else if (!match2(parser, PM_TOKEN_EQUAL, PM_TOKEN_PARENTHESIS_RIGHT)) { + // Multi targets must be followed by an equal sign in + // order to be valid (or a right parenthesis if they are + // nested). + pm_parser_err_node(parser, result, PM_ERR_WRITE_TARGET_UNEXPECTED); } - return parse_target_validate(parser, (pm_node_t *) multi_target, false); + return result; } // If we have a single statement and are ending on a right parenthesis // and we didn't return a multiple assignment node, then we can return a // regular parentheses node now. pm_statements_node_t *statements = pm_statements_node_create(parser); - pm_statements_node_body_append(parser, statements, statement); + pm_statements_node_body_append(parser, statements, statement, true); return (pm_node_t *) pm_parentheses_node_create(parser, &opening, (pm_node_t *) statements, &parser->previous); } @@ -17285,18 +18215,18 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // We'll do that here. context_push(parser, PM_CONTEXT_PARENS); pm_statements_node_t *statements = pm_statements_node_create(parser); - pm_statements_node_body_append(parser, statements, statement); + pm_statements_node_body_append(parser, statements, statement, true); // If we didn't find a terminator and we didn't find a right // parenthesis, then this is a syntax error. - if (!terminator_found) { + if (!terminator_found && !match1(parser, PM_TOKEN_EOF)) { PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); } // Parse each statement within the parentheses. while (true) { - pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_CANNOT_PARSE_EXPRESSION); - pm_statements_node_body_append(parser, statements, node); + pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, false, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1)); + pm_statements_node_body_append(parser, statements, node, true); // If we're recovering from a syntax error, then we need to stop // parsing the statements now. @@ -17318,7 +18248,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) break; } else if (match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { break; - } else { + } else if (!match1(parser, PM_TOKEN_EOF)) { + // If we're at the end of the file, then we're going to add + // an error after this for the ) anyway. PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); } } @@ -17327,10 +18259,37 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_accepts_block_stack_pop(parser); expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN); + // When we're parsing multi targets, we allow them to be followed by + // a right parenthesis if they are at the statement level. This is + // only possible if they are the final statement in a parentheses. + // We need to explicitly reject that here. + { + pm_node_t *statement = statements->body.nodes[statements->body.size - 1]; + + if (PM_NODE_TYPE_P(statement, PM_SPLAT_NODE)) { + pm_multi_target_node_t *multi_target = pm_multi_target_node_create(parser); + pm_multi_target_node_targets_append(parser, multi_target, statement); + + statement = (pm_node_t *) multi_target; + statements->body.nodes[statements->body.size - 1] = statement; + } + + if (PM_NODE_TYPE_P(statement, PM_MULTI_TARGET_NODE)) { + const uint8_t *offset = statement->location.end; + pm_token_t operator = { .type = PM_TOKEN_EQUAL, .start = offset, .end = offset }; + pm_node_t *value = (pm_node_t *) pm_missing_node_create(parser, offset, offset); + + statement = (pm_node_t *) pm_multi_write_node_create(parser, (pm_multi_target_node_t *) statement, &operator, value); + statements->body.nodes[statements->body.size - 1] = statement; + + pm_parser_err_node(parser, statement, PM_ERR_WRITE_TARGET_UNEXPECTED); + } + } + pop_block_exits(parser, previous_block_exits); pm_node_list_free(¤t_block_exits); - pm_void_statements_check(parser, statements); + pm_void_statements_check(parser, statements, true); return (pm_node_t *) pm_parentheses_node_create(parser, &opening, (pm_node_t *) statements, &parser->previous); } case PM_TOKEN_BRACE_LEFT: { @@ -17351,10 +18310,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (!match2(parser, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_EOF)) { if (current_hash_keys != NULL) { - parse_assocs(parser, current_hash_keys, (pm_node_t *) node); + parse_assocs(parser, current_hash_keys, (pm_node_t *) node, (uint16_t) (depth + 1)); } else { pm_static_literals_t hash_keys = { 0 }; - parse_assocs(parser, &hash_keys, (pm_node_t *) node); + parse_assocs(parser, &hash_keys, (pm_node_t *) node, (uint16_t) (depth + 1)); pm_static_literals_free(&hash_keys); } @@ -17385,7 +18344,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // Characters can be followed by strings in which case they are // automatically concatenated. if (match1(parser, PM_TOKEN_STRING_BEGIN)) { - return parse_strings(parser, node); + return parse_strings(parser, node, false, (uint16_t) (depth + 1)); } return node; @@ -17395,7 +18354,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *node = (pm_node_t *) pm_class_variable_read_node_create(parser, &parser->previous); if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) { - node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX); + node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1)); } return node; @@ -17413,7 +18372,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b match1(parser, PM_TOKEN_BRACE_LEFT) ) { pm_arguments_t arguments = { 0 }; - parse_arguments_list(parser, &arguments, true, accepts_command_call); + parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1)); return (pm_node_t *) pm_call_node_fcall_create(parser, &constant, &arguments); } @@ -17422,7 +18381,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if ((binding_power == PM_BINDING_POWER_STATEMENT) && match1(parser, PM_TOKEN_COMMA)) { // If we get here, then we have a comma immediately following a // constant, so we're going to parse this as a multiple assignment. - node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX); + node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1)); } return node; @@ -17435,7 +18394,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *node = (pm_node_t *) pm_constant_path_node_create(parser, NULL, &delimiter, &parser->previous); if ((binding_power == PM_BINDING_POWER_STATEMENT) && match1(parser, PM_TOKEN_COMMA)) { - node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX); + node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1)); } return node; @@ -17445,7 +18404,16 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_token_t operator = parser->current; parser_lex(parser); - pm_node_t *right = parse_expression(parser, pm_binding_powers[operator.type].left, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *right = parse_expression(parser, pm_binding_powers[operator.type].left, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + + // Unary .. and ... are special because these are non-associative + // operators that can also be unary operators. In this case we need + // to explicitly reject code that has a .. or ... that follows this + // expression. + if (match2(parser, PM_TOKEN_DOT_DOT, PM_TOKEN_DOT_DOT_DOT)) { + pm_parser_err_current(parser, PM_ERR_UNEXPECTED_RANGE_OPERATOR); + } + return (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right); } case PM_TOKEN_FLOAT: @@ -17465,7 +18433,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *node = (pm_node_t *) pm_numbered_reference_read_node_create(parser, &parser->previous); if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) { - node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX); + node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1)); } return node; @@ -17475,7 +18443,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *node = (pm_node_t *) pm_global_variable_read_node_create(parser, &parser->previous); if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) { - node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX); + node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1)); } return node; @@ -17485,7 +18453,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *node = (pm_node_t *) pm_back_reference_read_node_create(parser, &parser->previous); if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) { - node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX); + node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1)); } return node; @@ -17504,7 +18472,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_call_node_t *call = (pm_call_node_t *) node; pm_arguments_t arguments = { 0 }; - if (parse_arguments_list(parser, &arguments, true, accepts_command_call)) { + if (parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1))) { // Since we found arguments, we need to turn off the // variable call bit in the flags. pm_node_flag_unset((pm_node_t *)call, PM_CALL_NODE_FLAGS_VARIABLE_CALL); @@ -17536,41 +18504,36 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b match1(parser, PM_TOKEN_BRACE_LEFT) ) { pm_arguments_t arguments = { 0 }; - parse_arguments_list(parser, &arguments, true, accepts_command_call); - + parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1)); pm_call_node_t *fcall = pm_call_node_fcall_create(parser, &identifier, &arguments); + + if (PM_NODE_TYPE_P(node, PM_IT_LOCAL_VARIABLE_READ_NODE)) { + // If we're about to convert an 'it' implicit local + // variable read into a method call, we need to remove + // it from the list of implicit local variables. + parse_target_implicit_parameter(parser, node); + } else { + // Otherwise, we're about to convert a regular local + // variable read into a method call, in which case we + // need to indicate that this was not a read for the + // purposes of warnings. + assert(PM_NODE_TYPE_P(node, PM_LOCAL_VARIABLE_READ_NODE)); + + if (pm_token_is_numbered_parameter(identifier.start, identifier.end)) { + parse_target_implicit_parameter(parser, node); + } else { + pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node; + pm_locals_unread(&pm_parser_scope_find(parser, cast->depth)->locals, cast->name); + } + } + pm_node_destroy(parser, node); return (pm_node_t *) fcall; } } if ((binding_power == PM_BINDING_POWER_STATEMENT) && match1(parser, PM_TOKEN_COMMA)) { - node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX); - } else { - // Check if `it` is not going to be assigned. - switch (parser->current.type) { - case PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL: - case PM_TOKEN_AMPERSAND_EQUAL: - case PM_TOKEN_CARET_EQUAL: - case PM_TOKEN_EQUAL: - case PM_TOKEN_GREATER_GREATER_EQUAL: - case PM_TOKEN_LESS_LESS_EQUAL: - case PM_TOKEN_MINUS_EQUAL: - case PM_TOKEN_PARENTHESIS_RIGHT: - case PM_TOKEN_PERCENT_EQUAL: - case PM_TOKEN_PIPE_EQUAL: - case PM_TOKEN_PIPE_PIPE_EQUAL: - case PM_TOKEN_PLUS_EQUAL: - case PM_TOKEN_SLASH_EQUAL: - case PM_TOKEN_STAR_EQUAL: - case PM_TOKEN_STAR_STAR_EQUAL: - break; - default: - // Once we know it's neither a method call nor an - // assignment, we can finally create `it` default - // parameter. - node = pm_node_check_it(parser, node); - } + node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1)); } return node; @@ -17578,10 +18541,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b case PM_TOKEN_HEREDOC_START: { // Here we have found a heredoc. We'll parse it and add it to the // list of strings. - pm_lex_mode_t *lex_mode = parser->lex_modes.current; - assert(lex_mode->mode == PM_LEX_HEREDOC); - pm_heredoc_quote_t quote = lex_mode->as.heredoc.quote; - pm_heredoc_indent_t indent = lex_mode->as.heredoc.indent; + assert(parser->lex_modes.current->mode == PM_LEX_HEREDOC); + pm_heredoc_lex_mode_t lex_mode = parser->lex_modes.current->as.heredoc.base; + + size_t common_whitespace = (size_t) -1; + parser->lex_modes.current->as.heredoc.common_whitespace = &common_whitespace; parser_lex(parser); pm_token_t opening = parser->previous; @@ -17592,17 +18556,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (match2(parser, PM_TOKEN_HEREDOC_END, PM_TOKEN_EOF)) { // If we get here, then we have an empty heredoc. We'll create // an empty content token and return an empty string node. - expect1_heredoc_term(parser, lex_mode); + expect1_heredoc_term(parser, lex_mode.ident_start, lex_mode.ident_length); pm_token_t content = parse_strings_empty_content(parser->previous.start); - if (quote == PM_HEREDOC_QUOTE_BACKTICK) { + if (lex_mode.quote == PM_HEREDOC_QUOTE_BACKTICK) { node = (pm_node_t *) pm_xstring_node_create_unescaped(parser, &opening, &content, &parser->previous, &PM_STRING_EMPTY); } else { node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &PM_STRING_EMPTY); } node->location.end = opening.end; - } else if ((part = parse_string_part(parser)) == NULL) { + } else if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) == NULL) { // If we get here, then we tried to find something in the // heredoc but couldn't actually parse anything, so we'll just // return a missing node. @@ -17622,18 +18586,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b cast->closing_loc = PM_LOCATION_TOKEN_VALUE(&parser->current); cast->base.location = cast->opening_loc; - if (quote == PM_HEREDOC_QUOTE_BACKTICK) { + if (lex_mode.quote == PM_HEREDOC_QUOTE_BACKTICK) { assert(sizeof(pm_string_node_t) == sizeof(pm_x_string_node_t)); cast->base.type = PM_X_STRING_NODE; } - size_t common_whitespace = lex_mode->as.heredoc.common_whitespace; - if (indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) { + if (lex_mode.indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) { parse_heredoc_dedent_string(&cast->unescaped, common_whitespace); } node = (pm_node_t *) cast; - expect1_heredoc_term(parser, lex_mode); + expect1_heredoc_term(parser, lex_mode.ident_start, lex_mode.ident_length); } else { // If we get here, then we have multiple parts in the heredoc, // so we'll need to create an interpolated string node to hold @@ -17642,20 +18605,18 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_list_append(&parts, part); while (!match2(parser, PM_TOKEN_HEREDOC_END, PM_TOKEN_EOF)) { - if ((part = parse_string_part(parser)) != NULL) { + if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) { pm_node_list_append(&parts, part); } } - size_t common_whitespace = lex_mode->as.heredoc.common_whitespace; - // Now that we have all of the parts, create the correct type of // interpolated node. - if (quote == PM_HEREDOC_QUOTE_BACKTICK) { + if (lex_mode.quote == PM_HEREDOC_QUOTE_BACKTICK) { pm_interpolated_x_string_node_t *cast = pm_interpolated_xstring_node_create(parser, &opening, &opening); cast->parts = parts; - expect1_heredoc_term(parser, lex_mode); + expect1_heredoc_term(parser, lex_mode.ident_start, lex_mode.ident_length); pm_interpolated_xstring_node_closing_set(cast, &parser->previous); cast->base.location = cast->opening_loc; @@ -17664,7 +18625,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_interpolated_string_node_t *cast = pm_interpolated_string_node_create(parser, &opening, &parts, &opening); pm_node_list_free(&parts); - expect1_heredoc_term(parser, lex_mode); + expect1_heredoc_term(parser, lex_mode.ident_start, lex_mode.ident_length); pm_interpolated_string_node_closing_set(cast, &parser->previous); cast->base.location = cast->opening_loc; @@ -17673,9 +18634,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // If this is a heredoc that is indented with a ~, then we need // to dedent each line by the common leading whitespace. - if (indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) { + if (lex_mode.indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) { pm_node_list_t *nodes; - if (quote == PM_HEREDOC_QUOTE_BACKTICK) { + if (lex_mode.quote == PM_HEREDOC_QUOTE_BACKTICK) { nodes = &((pm_interpolated_x_string_node_t *) node)->parts; } else { nodes = &((pm_interpolated_string_node_t *) node)->parts; @@ -17686,7 +18647,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } if (match1(parser, PM_TOKEN_STRING_BEGIN)) { - return parse_strings(parser, node); + return parse_strings(parser, node, false, (uint16_t) (depth + 1)); } return node; @@ -17696,7 +18657,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *node = (pm_node_t *) pm_instance_variable_read_node_create(parser, &parser->previous); if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) { - node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX); + node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1)); } return node; @@ -17738,8 +18699,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t keyword = parser->previous; - pm_node_t *new_name = parse_alias_argument(parser, true); - pm_node_t *old_name = parse_alias_argument(parser, false); + pm_node_t *new_name = parse_alias_argument(parser, true, (uint16_t) (depth + 1)); + pm_node_t *old_name = parse_alias_argument(parser, false, (uint16_t) (depth + 1)); switch (PM_NODE_TYPE(new_name)) { case PM_BACK_REFERENCE_READ_NODE: @@ -17767,7 +18728,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } } case PM_TOKEN_KEYWORD_CASE: { + size_t opening_newline_index = token_newline_index(parser); parser_lex(parser); + pm_token_t case_keyword = parser->previous; pm_node_t *predicate = NULL; @@ -17782,11 +18745,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } else if (!token_begins_expression_p(parser->current.type)) { predicate = NULL; } else { - predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CASE_EXPRESSION_AFTER_CASE); + predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CASE_EXPRESSION_AFTER_CASE, (uint16_t) (depth + 1)); while (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)); } - if (accept1(parser, PM_TOKEN_KEYWORD_END)) { + if (match1(parser, PM_TOKEN_KEYWORD_END)) { + parser_warn_indentation_mismatch(parser, opening_newline_index, &case_keyword, false, false); + parser_lex(parser); + pop_block_exits(parser, previous_block_exits); pm_node_list_free(¤t_block_exits); @@ -17806,21 +18772,24 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // At this point we've seen a when keyword, so we know this is a // case-when node. We will continue to parse the when nodes // until we hit the end of the list. - while (accept1(parser, PM_TOKEN_KEYWORD_WHEN)) { + while (match1(parser, PM_TOKEN_KEYWORD_WHEN)) { + parser_warn_indentation_mismatch(parser, opening_newline_index, &case_keyword, false, true); + parser_lex(parser); + pm_token_t when_keyword = parser->previous; pm_when_node_t *when_node = pm_when_node_create(parser, &when_keyword); do { if (accept1(parser, PM_TOKEN_USTAR)) { pm_token_t operator = parser->previous; - pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR); + pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); pm_splat_node_t *splat_node = pm_splat_node_create(parser, &operator, expression); pm_when_node_conditions_append(when_node, (pm_node_t *) splat_node); if (PM_NODE_TYPE_P(expression, PM_MISSING_NODE)) break; } else { - pm_node_t *condition = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_CASE_EXPRESSION_AFTER_WHEN); + pm_node_t *condition = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_CASE_EXPRESSION_AFTER_WHEN, (uint16_t) (depth + 1)); pm_when_node_conditions_append(when_node, condition); // If we found a missing node, then this is a syntax @@ -17831,6 +18800,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // as frozen because when clause strings are frozen. if (PM_NODE_TYPE_P(condition, PM_STRING_NODE)) { pm_node_flag_set(condition, PM_STRING_FLAGS_FROZEN | PM_NODE_FLAG_STATIC_LITERAL); + } else if (PM_NODE_TYPE_P(condition, PM_SOURCE_FILE_NODE)) { + pm_node_flag_set(condition, PM_NODE_FLAG_STATIC_LITERAL); } pm_when_clause_static_literals_add(parser, &literals, condition); @@ -17847,7 +18818,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } if (!match3(parser, PM_TOKEN_KEYWORD_WHEN, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) { - pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_CASE_WHEN); + pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_CASE_WHEN, (uint16_t) (depth + 1)); if (statements != NULL) { pm_when_node_statements_set(when_node, statements); } @@ -17877,6 +18848,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // will continue to parse the in nodes until we hit the end of // the list. while (match1(parser, PM_TOKEN_KEYWORD_IN)) { + parser_warn_indentation_mismatch(parser, opening_newline_index, &case_keyword, false, true); + bool previous_pattern_matching_newlines = parser->pattern_matching_newlines; parser->pattern_matching_newlines = true; @@ -17887,7 +18860,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_token_t in_keyword = parser->previous; pm_constant_id_list_t captures = { 0 }; - pm_node_t *pattern = parse_pattern(parser, &captures, true, PM_ERR_PATTERN_EXPRESSION_AFTER_IN); + pm_node_t *pattern = parse_pattern(parser, &captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_IN, (uint16_t) (depth + 1)); parser->pattern_matching_newlines = previous_pattern_matching_newlines; pm_constant_id_list_free(&captures); @@ -17897,11 +18870,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // `unless` statements. if (accept1(parser, PM_TOKEN_KEYWORD_IF_MODIFIER)) { pm_token_t keyword = parser->previous; - pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CONDITIONAL_IF_PREDICATE); + pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CONDITIONAL_IF_PREDICATE, (uint16_t) (depth + 1)); pattern = (pm_node_t *) pm_if_node_modifier_create(parser, pattern, &keyword, predicate); } else if (accept1(parser, PM_TOKEN_KEYWORD_UNLESS_MODIFIER)) { pm_token_t keyword = parser->previous; - pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CONDITIONAL_UNLESS_PREDICATE); + pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CONDITIONAL_UNLESS_PREDICATE, (uint16_t) (depth + 1)); pattern = (pm_node_t *) pm_unless_node_modifier_create(parser, pattern, &keyword, predicate); } @@ -17916,7 +18889,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b then_keyword = not_provided(parser); } } else { - expect1(parser, PM_TOKEN_KEYWORD_THEN, PM_ERR_EXPECT_WHEN_DELIMITER); + expect1(parser, PM_TOKEN_KEYWORD_THEN, PM_ERR_EXPECT_IN_DELIMITER); then_keyword = parser->previous; } @@ -17926,7 +18899,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (match3(parser, PM_TOKEN_KEYWORD_IN, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) { statements = NULL; } else { - statements = parse_statements(parser, PM_CONTEXT_CASE_IN); + statements = parse_statements(parser, PM_CONTEXT_CASE_IN, (uint16_t) (depth + 1)); } // Now that we have the full pattern and statements, we can @@ -17950,19 +18923,21 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_else_node_t *else_node; if (!match1(parser, PM_TOKEN_KEYWORD_END)) { - else_node = pm_else_node_create(parser, &else_keyword, parse_statements(parser, PM_CONTEXT_ELSE), &parser->current); + else_node = pm_else_node_create(parser, &else_keyword, parse_statements(parser, PM_CONTEXT_ELSE, (uint16_t) (depth + 1)), &parser->current); } else { else_node = pm_else_node_create(parser, &else_keyword, NULL, &parser->current); } if (PM_NODE_TYPE_P(node, PM_CASE_NODE)) { - pm_case_node_consequent_set((pm_case_node_t *) node, else_node); + pm_case_node_else_clause_set((pm_case_node_t *) node, else_node); } else { - pm_case_match_node_consequent_set((pm_case_match_node_t *) node, else_node); + pm_case_match_node_else_clause_set((pm_case_match_node_t *) node, else_node); } } + parser_warn_indentation_mismatch(parser, opening_newline_index, &case_keyword, false, false); expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CASE_TERM); + if (PM_NODE_TYPE_P(node, PM_CASE_NODE)) { pm_case_node_end_keyword_loc_set((pm_case_node_t *) node, &parser->previous); } else { @@ -17975,6 +18950,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b return node; } case PM_TOKEN_KEYWORD_BEGIN: { + size_t opening_newline_index = token_newline_index(parser); parser_lex(parser); pm_token_t begin_keyword = parser->previous; @@ -17984,30 +18960,29 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_list_t *previous_block_exits = push_block_exits(parser, ¤t_block_exits); pm_statements_node_t *begin_statements = NULL; - if (!match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_END)) { + if (!match4(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) { pm_accepts_block_stack_push(parser, true); - begin_statements = parse_statements(parser, PM_CONTEXT_BEGIN); + begin_statements = parse_statements(parser, PM_CONTEXT_BEGIN, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); } pm_begin_node_t *begin_node = pm_begin_node_create(parser, &begin_keyword, begin_statements); - parse_rescues(parser, begin_node, PM_RESCUES_BEGIN); - + parse_rescues(parser, opening_newline_index, &begin_keyword, begin_node, PM_RESCUES_BEGIN, (uint16_t) (depth + 1)); expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_BEGIN_TERM); + begin_node->base.location.end = parser->previous.end; pm_begin_node_end_keyword_set(begin_node, &parser->previous); - if ((begin_node->else_clause != NULL) && (begin_node->rescue_clause == NULL)) { - pm_parser_err_node(parser, (pm_node_t *) begin_node->else_clause, PM_ERR_BEGIN_LONELY_ELSE); - } - pop_block_exits(parser, previous_block_exits); pm_node_list_free(¤t_block_exits); return (pm_node_t *) begin_node; } case PM_TOKEN_KEYWORD_BEGIN_UPCASE: { + pm_node_list_t current_block_exits = { 0 }; + pm_node_list_t *previous_block_exits = push_block_exits(parser, ¤t_block_exits); + if (binding_power != PM_BINDING_POWER_STATEMENT) { pm_parser_err_current(parser, PM_ERR_STATEMENT_PREEXE_BEGIN); } @@ -18017,13 +18992,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b expect1(parser, PM_TOKEN_BRACE_LEFT, PM_ERR_BEGIN_UPCASE_BRACE); pm_token_t opening = parser->previous; - pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_PREEXE); + pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_PREEXE, (uint16_t) (depth + 1)); expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_BEGIN_UPCASE_TERM); pm_context_t context = parser->current_context->context; if ((context != PM_CONTEXT_MAIN) && (context != PM_CONTEXT_PREEXE)) { pm_parser_err_token(parser, &keyword, PM_ERR_BEGIN_UPCASE_TOPLEVEL); } + + flush_block_exits(parser, previous_block_exits); + pm_node_list_free(¤t_block_exits); + return (pm_node_t *) pm_pre_execution_node_create(parser, &keyword, &opening, statements, &parser->previous); } case PM_TOKEN_KEYWORD_BREAK: @@ -18041,29 +19020,25 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_binding_power_t binding_power = pm_binding_powers[parser->current.type].left; if (binding_power == PM_BINDING_POWER_UNSET || binding_power >= PM_BINDING_POWER_RANGE) { - parse_arguments(parser, &arguments, false, PM_TOKEN_EOF); + parse_arguments(parser, &arguments, false, PM_TOKEN_EOF, (uint16_t) (depth + 1)); } } switch (keyword.type) { case PM_TOKEN_KEYWORD_BREAK: { pm_node_t *node = (pm_node_t *) pm_break_node_create(parser, &keyword, arguments.arguments); - if (!parser->parsing_eval) parse_block_exit(parser, node, "break"); + if (!parser->partial_script) parse_block_exit(parser, node); return node; } case PM_TOKEN_KEYWORD_NEXT: { pm_node_t *node = (pm_node_t *) pm_next_node_create(parser, &keyword, arguments.arguments); - if (!parser->parsing_eval) parse_block_exit(parser, node, "next"); + if (!parser->partial_script) parse_block_exit(parser, node); return node; } case PM_TOKEN_KEYWORD_RETURN: { - if ( - (parser->current_context->context == PM_CONTEXT_CLASS) || - (parser->current_context->context == PM_CONTEXT_MODULE) - ) { - pm_parser_err_previous(parser, PM_ERR_RETURN_INVALID); - } - return (pm_node_t *) pm_return_node_create(parser, &keyword, arguments.arguments); + pm_node_t *node = (pm_node_t *) pm_return_node_create(parser, &keyword, arguments.arguments); + parse_return(parser, node); + return node; } default: assert(false && "unreachable"); @@ -18075,7 +19050,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_token_t keyword = parser->previous; pm_arguments_t arguments = { 0 }; - parse_arguments_list(parser, &arguments, true, accepts_command_call); + parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1)); if ( arguments.opening_loc.start == NULL && @@ -18092,7 +19067,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_token_t keyword = parser->previous; pm_arguments_t arguments = { 0 }; - parse_arguments_list(parser, &arguments, false, accepts_command_call); + parse_arguments_list(parser, &arguments, false, accepts_command_call, (uint16_t) (depth + 1)); // It's possible that we've parsed a block argument through our // call to parse_arguments_list. If we found one, we should mark it @@ -18105,32 +19080,41 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pm_node_t *node = (pm_node_t *) pm_yield_node_create(parser, &keyword, &arguments.opening_loc, arguments.arguments, &arguments.closing_loc); - if (!parser->parsing_eval) parse_yield(parser, node); + if (!parser->parsing_eval && !parser->partial_script) parse_yield(parser, node); return node; } case PM_TOKEN_KEYWORD_CLASS: { + size_t opening_newline_index = token_newline_index(parser); parser_lex(parser); + pm_token_t class_keyword = parser->previous; pm_do_loop_stack_push(parser, false); + pm_node_list_t current_block_exits = { 0 }; + pm_node_list_t *previous_block_exits = push_block_exits(parser, ¤t_block_exits); + if (accept1(parser, PM_TOKEN_LESS_LESS)) { pm_token_t operator = parser->previous; - pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_NOT, true, PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS); + pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS, (uint16_t) (depth + 1)); pm_parser_scope_push(parser, true); - accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); + if (!match2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_EXPECT_SINGLETON_CLASS_DELIMITER, pm_token_type_human(parser->current.type)); + } pm_node_t *statements = NULL; - if (!match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_END)) { + if (!match4(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) { pm_accepts_block_stack_push(parser, true); - statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_SCLASS); + statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_SCLASS, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); } if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) { assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE)); - statements = (pm_node_t *) parse_rescues_implicit_begin(parser, class_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_SCLASS); + statements = (pm_node_t *) parse_rescues_implicit_begin(parser, opening_newline_index, &class_keyword, class_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_SCLASS, (uint16_t) (depth + 1)); + } else { + parser_warn_indentation_mismatch(parser, opening_newline_index, &class_keyword, false, false); } expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM); @@ -18141,13 +19125,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_parser_scope_pop(parser); pm_do_loop_stack_pop(parser); + flush_block_exits(parser, previous_block_exits); + pm_node_list_free(¤t_block_exits); + return (pm_node_t *) pm_singleton_class_node_create(parser, &locals, &class_keyword, &operator, expression, statements, &parser->previous); } - pm_node_list_t current_block_exits = { 0 }; - pm_node_list_t *previous_block_exits = push_block_exits(parser, ¤t_block_exits); - - pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_CLASS_NAME); + pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_CLASS_NAME, (uint16_t) (depth + 1)); pm_token_t name = parser->previous; if (name.type != PM_TOKEN_CONSTANT) { pm_parser_err_token(parser, &name, PM_ERR_CLASS_NAME); @@ -18163,7 +19147,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser->command_start = true; parser_lex(parser); - superclass = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CLASS_SUPERCLASS); + superclass = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CLASS_SUPERCLASS, (uint16_t) (depth + 1)); } else { inheritance_operator = not_provided(parser); superclass = NULL; @@ -18178,15 +19162,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pm_node_t *statements = NULL; - if (!match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_END)) { + if (!match4(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) { pm_accepts_block_stack_push(parser, true); - statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_CLASS); + statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_CLASS, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); } if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) { assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE)); - statements = (pm_node_t *) parse_rescues_implicit_begin(parser, class_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_CLASS); + statements = (pm_node_t *) parse_rescues_implicit_begin(parser, opening_newline_index, &class_keyword, class_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_CLASS, (uint16_t) (depth + 1)); + } else { + parser_warn_indentation_mismatch(parser, opening_newline_index, &class_keyword, false, false); } expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM); @@ -18211,7 +19197,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b return (pm_node_t *) pm_class_node_create(parser, &locals, &class_keyword, constant_path, &name, &inheritance_operator, superclass, statements, &parser->previous); } case PM_TOKEN_KEYWORD_DEF: { + pm_node_list_t current_block_exits = { 0 }; + pm_node_list_t *previous_block_exits = push_block_exits(parser, ¤t_block_exits); + pm_token_t def_keyword = parser->current; + size_t opening_newline_index = token_newline_index(parser); pm_node_t *receiver = NULL; pm_token_t operator = not_provided(parser); @@ -18236,7 +19226,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (match2(parser, PM_TOKEN_DOT, PM_TOKEN_COLON_COLON)) { receiver = parse_variable_call(parser); - receiver = pm_node_check_it(parser, receiver); pm_parser_scope_push(parser, true); lex_state_set(parser, PM_LEX_STATE_FNAME); @@ -18327,7 +19316,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t lparen = parser->previous; - pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_DEF_RECEIVER); + pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_DEF_RECEIVER, (uint16_t) (depth + 1)); accept1(parser, PM_TOKEN_NEWLINE); expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN); @@ -18364,13 +19353,19 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { params = NULL; } else { - params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, true, false, true); + params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, true, false, true, true, (uint16_t) (depth + 1)); } lex_state_set(parser, PM_LEX_STATE_BEG); parser->command_start = true; - expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_DEF_PARAMS_TERM_PAREN); + context_pop(parser); + if (!accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_DEF_PARAMS_TERM_PAREN, pm_token_type_human(parser->current.type)); + parser->previous.start = parser->previous.end; + parser->previous.type = PM_TOKEN_MISSING; + } + rparen = parser->previous; break; } @@ -18383,18 +19378,21 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b lparen = not_provided(parser); rparen = not_provided(parser); - params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, false, false, true); + params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, false, false, true, true, (uint16_t) (depth + 1)); + + context_pop(parser); break; } default: { lparen = not_provided(parser); rparen = not_provided(parser); params = NULL; + + context_pop(parser); break; } } - context_pop(parser); pm_node_t *statements = NULL; pm_token_t equal; pm_token_t end_keyword; @@ -18409,19 +19407,19 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_do_loop_stack_push(parser, false); statements = (pm_node_t *) pm_statements_node_create(parser); - pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, binding_power < PM_BINDING_POWER_COMPOSITION, PM_ERR_DEF_ENDLESS); + pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, binding_power < PM_BINDING_POWER_COMPOSITION, false, PM_ERR_DEF_ENDLESS, (uint16_t) (depth + 1)); if (accept1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) { context_push(parser, PM_CONTEXT_RESCUE_MODIFIER); pm_token_t rescue_keyword = parser->previous; - pm_node_t *value = parse_expression(parser, binding_power, false, PM_ERR_RESCUE_MODIFIER_VALUE); + pm_node_t *value = parse_expression(parser, binding_power, false, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); statement = (pm_node_t *) pm_rescue_modifier_node_create(parser, statement, &rescue_keyword, value); } - pm_statements_node_body_append(parser, (pm_statements_node_t *) statements, statement); + pm_statements_node_body_append(parser, (pm_statements_node_t *) statements, statement, false); pm_do_loop_stack_pop(parser); context_pop(parser); end_keyword = not_provided(parser); @@ -18439,19 +19437,22 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_accepts_block_stack_push(parser, true); pm_do_loop_stack_push(parser, false); - if (!match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_END)) { + if (!match4(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) { pm_accepts_block_stack_push(parser, true); - statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_DEF); + statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_DEF, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); } - if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) { + if (match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE)) { assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE)); - statements = (pm_node_t *) parse_rescues_implicit_begin(parser, def_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_DEF); + statements = (pm_node_t *) parse_rescues_implicit_begin(parser, opening_newline_index, &def_keyword, def_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_DEF, (uint16_t) (depth + 1)); + } else { + parser_warn_indentation_mismatch(parser, opening_newline_index, &def_keyword, false, false); } pm_accepts_block_stack_pop(parser); pm_do_loop_stack_pop(parser); + expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_DEF_TERM); end_keyword = parser->previous; } @@ -18467,6 +19468,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b */ pm_constant_id_t name_id = pm_parser_constant_id_location(parser, name.start, parse_operator_symbol_name(&name)); + flush_block_exits(parser, previous_block_exits); + pm_node_list_free(¤t_block_exits); + return (pm_node_t *) pm_def_node_create( parser, name_id, @@ -18494,7 +19498,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (accept1(parser, PM_TOKEN_PARENTHESIS_LEFT)) { lparen = parser->previous; - expression = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_DEFINED_EXPRESSION); + expression = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_DEFINED_EXPRESSION, (uint16_t) (depth + 1)); if (parser->recovering) { rparen = not_provided(parser); @@ -18506,7 +19510,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } else { lparen = not_provided(parser); rparen = not_provided(parser); - expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_DEFINED_EXPRESSION); + expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_DEFINED_EXPRESSION, (uint16_t) (depth + 1)); } context_pop(parser); @@ -18532,16 +19536,18 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b expect1(parser, PM_TOKEN_BRACE_LEFT, PM_ERR_END_UPCASE_BRACE); pm_token_t opening = parser->previous; - pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_POSTEXE); + pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_POSTEXE, (uint16_t) (depth + 1)); expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_END_UPCASE_TERM); return (pm_node_t *) pm_post_execution_node_create(parser, &keyword, &opening, statements, &parser->previous); } case PM_TOKEN_KEYWORD_FALSE: parser_lex(parser); - return (pm_node_t *)pm_false_node_create(parser, &parser->previous); + return (pm_node_t *) pm_false_node_create(parser, &parser->previous); case PM_TOKEN_KEYWORD_FOR: { + size_t opening_newline_index = token_newline_index(parser); parser_lex(parser); + pm_token_t for_keyword = parser->previous; pm_node_t *index; @@ -18553,12 +19559,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *name = NULL; if (token_begins_expression_p(parser->current.type)) { - name = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR); + name = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); } index = (pm_node_t *) pm_splat_node_create(parser, &star_operator, name); } else if (token_begins_expression_p(parser->current.type)) { - index = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA); + index = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1)); } else { pm_parser_err_token(parser, &for_keyword, PM_ERR_FOR_INDEX); index = (pm_node_t *) pm_missing_node_create(parser, for_keyword.start, for_keyword.end); @@ -18566,9 +19572,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // Now, if there are multiple index expressions, parse them out. if (match1(parser, PM_TOKEN_COMMA)) { - index = parse_targets(parser, index, PM_BINDING_POWER_INDEX); + index = parse_targets(parser, index, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1)); } else { - index = parse_target(parser, index, false); + index = parse_target(parser, index, false, false); } context_pop(parser); @@ -18577,7 +19583,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b expect1(parser, PM_TOKEN_KEYWORD_IN, PM_ERR_FOR_IN); pm_token_t in_keyword = parser->previous; - pm_node_t *collection = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_FOR_COLLECTION); + pm_node_t *collection = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_FOR_COLLECTION, (uint16_t) (depth + 1)); pm_do_loop_stack_pop(parser); pm_token_t do_keyword; @@ -18585,16 +19591,19 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b do_keyword = parser->previous; } else { do_keyword = not_provided(parser); + if (!match2(parser, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE)) { + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_EXPECT_FOR_DELIMITER, pm_token_type_human(parser->current.type)); + } } - accept2(parser, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE); pm_statements_node_t *statements = NULL; - - if (!accept1(parser, PM_TOKEN_KEYWORD_END)) { - statements = parse_statements(parser, PM_CONTEXT_FOR); - expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_FOR_TERM); + if (!match1(parser, PM_TOKEN_KEYWORD_END)) { + statements = parse_statements(parser, PM_CONTEXT_FOR, (uint16_t) (depth + 1)); } + parser_warn_indentation_mismatch(parser, opening_newline_index, &for_keyword, false, false); + expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_FOR_TERM); + return (pm_node_t *) pm_for_node_create(parser, index, collection, statements, &for_keyword, &in_keyword, &do_keyword, &parser->previous); } case PM_TOKEN_KEYWORD_IF: @@ -18602,8 +19611,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b PM_PARSER_WARN_TOKEN_FORMAT_CONTENT(parser, parser->current, PM_WARN_KEYWORD_EOL); } + size_t opening_newline_index = token_newline_index(parser); + bool if_after_else = parser->previous.type == PM_TOKEN_KEYWORD_ELSE; parser_lex(parser); - return parse_conditional(parser, PM_CONTEXT_IF); + + return parse_conditional(parser, PM_CONTEXT_IF, opening_newline_index, if_after_else, (uint16_t) (depth + 1)); case PM_TOKEN_KEYWORD_UNDEF: { if (binding_power != PM_BINDING_POWER_STATEMENT) { pm_parser_err_current(parser, PM_ERR_STATEMENT_UNDEF); @@ -18611,7 +19623,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_undef_node_t *undef = pm_undef_node_create(parser, &parser->previous); - pm_node_t *name = parse_undef_argument(parser); + pm_node_t *name = parse_undef_argument(parser, (uint16_t) (depth + 1)); if (PM_NODE_TYPE_P(name, PM_MISSING_NODE)) { pm_node_destroy(parser, name); @@ -18621,7 +19633,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b while (match1(parser, PM_TOKEN_COMMA)) { lex_state_set(parser, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM); parser_lex(parser); - name = parse_undef_argument(parser); + name = parse_undef_argument(parser, (uint16_t) (depth + 1)); if (PM_NODE_TYPE_P(name, PM_MISSING_NODE)) { pm_node_destroy(parser, name); @@ -18649,7 +19661,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { arguments.closing_loc = PM_LOCATION_TOKEN_VALUE(&parser->previous); } else { - receiver = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_NOT_EXPRESSION); + receiver = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); if (!parser->recovering) { accept1(parser, PM_TOKEN_NEWLINE); @@ -18658,22 +19670,26 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } } } else { - receiver = parse_expression(parser, PM_BINDING_POWER_NOT, true, PM_ERR_NOT_EXPRESSION); + receiver = parse_expression(parser, PM_BINDING_POWER_NOT, true, false, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); } return (pm_node_t *) pm_call_node_not_create(parser, receiver, &message, &arguments); } - case PM_TOKEN_KEYWORD_UNLESS: + case PM_TOKEN_KEYWORD_UNLESS: { + size_t opening_newline_index = token_newline_index(parser); parser_lex(parser); - return parse_conditional(parser, PM_CONTEXT_UNLESS); + + return parse_conditional(parser, PM_CONTEXT_UNLESS, opening_newline_index, false, (uint16_t) (depth + 1)); + } case PM_TOKEN_KEYWORD_MODULE: { pm_node_list_t current_block_exits = { 0 }; pm_node_list_t *previous_block_exits = push_block_exits(parser, ¤t_block_exits); + size_t opening_newline_index = token_newline_index(parser); parser_lex(parser); pm_token_t module_keyword = parser->previous; - pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_MODULE_NAME); + pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_MODULE_NAME, (uint16_t) (depth + 1)); pm_token_t name; // If we can recover from a syntax error that occurred while parsing @@ -18705,15 +19721,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b accept2(parser, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE); pm_node_t *statements = NULL; - if (!match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_END)) { + if (!match4(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) { pm_accepts_block_stack_push(parser, true); - statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_MODULE); + statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_MODULE, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); } - if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) { + if (match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE)) { assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE)); - statements = (pm_node_t *) parse_rescues_implicit_begin(parser, module_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_MODULE); + statements = (pm_node_t *) parse_rescues_implicit_begin(parser, opening_newline_index, &module_keyword, module_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_MODULE, (uint16_t) (depth + 1)); + } else { + parser_warn_indentation_mismatch(parser, opening_newline_index, &module_keyword, false, false); } pm_constant_id_list_t locals; @@ -18738,7 +19756,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_node_t *node = (pm_node_t *) pm_redo_node_create(parser, &parser->previous); - if (!parser->parsing_eval) parse_block_exit(parser, node, "redo"); + if (!parser->partial_script) parse_block_exit(parser, node); return node; } @@ -18757,45 +19775,59 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); return (pm_node_t *) pm_true_node_create(parser, &parser->previous); case PM_TOKEN_KEYWORD_UNTIL: { + size_t opening_newline_index = token_newline_index(parser); + + context_push(parser, PM_CONTEXT_LOOP_PREDICATE); pm_do_loop_stack_push(parser, true); + parser_lex(parser); pm_token_t keyword = parser->previous; + pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CONDITIONAL_UNTIL_PREDICATE, (uint16_t) (depth + 1)); - pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CONDITIONAL_UNTIL_PREDICATE); pm_do_loop_stack_pop(parser); + context_pop(parser); expect3(parser, PM_TOKEN_KEYWORD_DO_LOOP, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_ERR_CONDITIONAL_UNTIL_PREDICATE); pm_statements_node_t *statements = NULL; - if (!accept1(parser, PM_TOKEN_KEYWORD_END)) { + if (!match1(parser, PM_TOKEN_KEYWORD_END)) { pm_accepts_block_stack_push(parser, true); - statements = parse_statements(parser, PM_CONTEXT_UNTIL); + statements = parse_statements(parser, PM_CONTEXT_UNTIL, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); - expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_UNTIL_TERM); } + parser_warn_indentation_mismatch(parser, opening_newline_index, &keyword, false, false); + expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_UNTIL_TERM); + return (pm_node_t *) pm_until_node_create(parser, &keyword, &parser->previous, predicate, statements, 0); } case PM_TOKEN_KEYWORD_WHILE: { + size_t opening_newline_index = token_newline_index(parser); + + context_push(parser, PM_CONTEXT_LOOP_PREDICATE); pm_do_loop_stack_push(parser, true); + parser_lex(parser); pm_token_t keyword = parser->previous; + pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CONDITIONAL_WHILE_PREDICATE, (uint16_t) (depth + 1)); - pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CONDITIONAL_WHILE_PREDICATE); pm_do_loop_stack_pop(parser); + context_pop(parser); expect3(parser, PM_TOKEN_KEYWORD_DO_LOOP, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_ERR_CONDITIONAL_WHILE_PREDICATE); pm_statements_node_t *statements = NULL; - if (!accept1(parser, PM_TOKEN_KEYWORD_END)) { + if (!match1(parser, PM_TOKEN_KEYWORD_END)) { pm_accepts_block_stack_push(parser, true); - statements = parse_statements(parser, PM_CONTEXT_WHILE); + statements = parse_statements(parser, PM_CONTEXT_WHILE, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); - expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_WHILE_TERM); } + parser_warn_indentation_mismatch(parser, opening_newline_index, &keyword, false, false); + expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_WHILE_TERM); + return (pm_node_t *) pm_while_node_create(parser, &keyword, &parser->previous, predicate, statements, 0); } case PM_TOKEN_PERCENT_LOWER_I: { @@ -18921,7 +19953,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // interpolated string, then we'll just add the embedded variable. } - pm_node_t *part = parse_string_part(parser); + pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1)); pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, part); if (!start_location_set) { current->location.start = part->location.start; @@ -18958,7 +19990,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b assert(false && "unreachable"); } - pm_node_t *part = parse_string_part(parser); + pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1)); pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, part); if (!start_location_set) { current->location.start = part->location.start; @@ -19111,7 +20143,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // add the embedded variable. } - pm_node_t *part = parse_string_part(parser); + pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1)); pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, part); break; } @@ -19142,7 +20174,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b assert(false && "unreachable"); } - pm_node_t *part = parse_string_part(parser); + pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1)); pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, part); break; } @@ -19203,13 +20235,22 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b bool ascii_only = parser->current_regular_expression_ascii_only; parser_lex(parser); - // If we hit an end, then we can create a regular expression node - // without interpolation, which can be represented more succinctly and - // more easily compiled. + // If we hit an end, then we can create a regular expression + // node without interpolation, which can be represented more + // succinctly and more easily compiled. if (accept1(parser, PM_TOKEN_REGEXP_END)) { - pm_node_t *node = (pm_node_t *) pm_regular_expression_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped); - pm_node_flag_set(node, parse_and_validate_regular_expression_encoding(parser, &unescaped, ascii_only, node->flags)); - return node; + pm_regular_expression_node_t *node = (pm_regular_expression_node_t *) pm_regular_expression_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped); + + // If we're not immediately followed by a =~, then we want + // to parse all of the errors at this point. If it is + // followed by a =~, then it will get parsed higher up while + // parsing the named captures as well. + if (!match1(parser, PM_TOKEN_EQUAL_TILDE)) { + parse_regular_expression_errors(parser, node); + } + + pm_node_flag_set((pm_node_t *) node, parse_and_validate_regular_expression_encoding(parser, &unescaped, ascii_only, node->base.flags)); + return (pm_node_t *) node; } // If we get here, then we have interpolation so we'll need to create @@ -19219,6 +20260,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_token_t opening = not_provided(parser); pm_token_t closing = not_provided(parser); pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &parser->previous, &closing, &unescaped); + + if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) { + // This is extremely strange, but the first string part of a + // regular expression will always be tagged as binary if we + // are in a US-ASCII file, no matter its contents. + pm_node_flag_set(part, PM_STRING_FLAGS_FORCED_BINARY_ENCODING); + } + pm_interpolated_regular_expression_node_append(interpolated, part); } else { // If the first part of the body of the regular expression is not a @@ -19231,7 +20280,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // parts into the list. pm_node_t *part; while (!match2(parser, PM_TOKEN_REGEXP_END, PM_TOKEN_EOF)) { - if ((part = parse_string_part(parser)) != NULL) { + if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) { pm_interpolated_regular_expression_node_append(interpolated, part); } } @@ -19308,7 +20357,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *part; while (!match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) { - if ((part = parse_string_part(parser)) != NULL) { + if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) { pm_interpolated_xstring_node_append(node, part); } } @@ -19339,41 +20388,51 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *name = NULL; if (token_begins_expression_p(parser->current.type)) { - name = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR); + name = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); } pm_node_t *splat = (pm_node_t *) pm_splat_node_create(parser, &operator, name); if (match1(parser, PM_TOKEN_COMMA)) { - return parse_targets_validate(parser, splat, PM_BINDING_POWER_INDEX); + return parse_targets_validate(parser, splat, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1)); } else { return parse_target_validate(parser, splat, true); } } case PM_TOKEN_BANG: { + if (binding_power > PM_BINDING_POWER_UNARY) { + pm_parser_err_prefix(parser, PM_ERR_UNARY_DISALLOWED); + } + parser_lex(parser); pm_token_t operator = parser->previous; - pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, binding_power < PM_BINDING_POWER_MATCH, PM_ERR_UNARY_RECEIVER); + pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, binding_power < PM_BINDING_POWER_MATCH, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "!"); pm_conditional_predicate(parser, receiver, PM_CONDITIONAL_PREDICATE_TYPE_NOT); return (pm_node_t *) node; } case PM_TOKEN_TILDE: { + if (binding_power > PM_BINDING_POWER_UNARY) { + pm_parser_err_prefix(parser, PM_ERR_UNARY_DISALLOWED); + } parser_lex(parser); pm_token_t operator = parser->previous; - pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER); + pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "~"); return (pm_node_t *) node; } case PM_TOKEN_UMINUS: { + if (binding_power > PM_BINDING_POWER_UNARY) { + pm_parser_err_prefix(parser, PM_ERR_UNARY_DISALLOWED); + } parser_lex(parser); pm_token_t operator = parser->previous; - pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER); + pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "-@"); return (pm_node_t *) node; @@ -19382,11 +20441,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t operator = parser->previous; - pm_node_t *node = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER); + pm_node_t *node = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); if (accept1(parser, PM_TOKEN_STAR_STAR)) { pm_token_t exponent_operator = parser->previous; - pm_node_t *exponent = parse_expression(parser, pm_binding_powers[exponent_operator.type].right, false, PM_ERR_EXPECT_ARGUMENT); + pm_node_t *exponent = parse_expression(parser, pm_binding_powers[exponent_operator.type].right, false, false, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1)); node = (pm_node_t *) pm_call_node_binary_create(parser, node, &exponent_operator, exponent, 0); node = (pm_node_t *) pm_call_node_unary_create(parser, &operator, node, "-@"); } else { @@ -19409,6 +20468,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b int previous_lambda_enclosure_nesting = parser->lambda_enclosure_nesting; parser->lambda_enclosure_nesting = parser->enclosure_nesting; + size_t opening_newline_index = token_newline_index(parser); pm_accepts_block_stack_push(parser, true); parser_lex(parser); @@ -19419,16 +20479,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b switch (parser->current.type) { case PM_TOKEN_PARENTHESIS_LEFT: { - assert(parser->current_scope->parameters == PM_SCOPE_PARAMETERS_NONE); - parser->current_scope->parameters = PM_SCOPE_PARAMETERS_ORDINARY; - pm_token_t opening = parser->current; parser_lex(parser); if (match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { block_parameters = pm_block_parameters_node_create(parser, NULL, &opening); } else { - block_parameters = parse_block_parameters(parser, false, &opening, true); + block_parameters = parse_block_parameters(parser, false, &opening, true, true, (uint16_t) (depth + 1)); } accept1(parser, PM_TOKEN_NEWLINE); @@ -19438,12 +20495,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b break; } case PM_CASE_PARAMETER: { - assert(parser->current_scope->parameters == PM_SCOPE_PARAMETERS_NONE); - parser->current_scope->parameters = PM_SCOPE_PARAMETERS_ORDINARY; - pm_accepts_block_stack_push(parser, false); pm_token_t opening = not_provided(parser); - block_parameters = parse_block_parameters(parser, false, &opening, true); + block_parameters = parse_block_parameters(parser, false, &opening, true, false, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); break; } @@ -19460,23 +20514,27 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (accept1(parser, PM_TOKEN_LAMBDA_BEGIN)) { opening = parser->previous; - if (!accept1(parser, PM_TOKEN_BRACE_RIGHT)) { - body = (pm_node_t *) parse_statements(parser, PM_CONTEXT_LAMBDA_BRACES); - expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_LAMBDA_TERM_BRACE); + if (!match1(parser, PM_TOKEN_BRACE_RIGHT)) { + body = (pm_node_t *) parse_statements(parser, PM_CONTEXT_LAMBDA_BRACES, (uint16_t) (depth + 1)); } + + parser_warn_indentation_mismatch(parser, opening_newline_index, &operator, false, false); + expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_LAMBDA_TERM_BRACE); } else { expect1(parser, PM_TOKEN_KEYWORD_DO, PM_ERR_LAMBDA_OPEN); opening = parser->previous; if (!match3(parser, PM_TOKEN_KEYWORD_END, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) { pm_accepts_block_stack_push(parser, true); - body = (pm_node_t *) parse_statements(parser, PM_CONTEXT_LAMBDA_DO_END); + body = (pm_node_t *) parse_statements(parser, PM_CONTEXT_LAMBDA_DO_END, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); } if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) { assert(body == NULL || PM_NODE_TYPE_P(body, PM_STATEMENTS_NODE)); - body = (pm_node_t *) parse_rescues_implicit_begin(parser, opening.start, (pm_statements_node_t *) body, PM_RESCUES_LAMBDA); + body = (pm_node_t *) parse_rescues_implicit_begin(parser, opening_newline_index, &operator, opening.start, (pm_statements_node_t *) body, PM_RESCUES_LAMBDA, (uint16_t) (depth + 1)); + } else { + parser_warn_indentation_mismatch(parser, opening_newline_index, &operator, false, false); } expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_LAMBDA_TERM_END); @@ -19492,21 +20550,24 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b return (pm_node_t *) pm_lambda_node_create(parser, &locals, &operator, &opening, &parser->previous, parameters, body); } case PM_TOKEN_UPLUS: { + if (binding_power > PM_BINDING_POWER_UNARY) { + pm_parser_err_prefix(parser, PM_ERR_UNARY_DISALLOWED); + } parser_lex(parser); pm_token_t operator = parser->previous; - pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER); + pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "+@"); return (pm_node_t *) node; } case PM_TOKEN_STRING_BEGIN: - return parse_strings(parser, NULL); + return parse_strings(parser, NULL, accepts_label, (uint16_t) (depth + 1)); case PM_TOKEN_SYMBOL_BEGIN: { pm_lex_mode_t lex_mode = *parser->lex_modes.current; parser_lex(parser); - return parse_symbol(parser, &lex_mode, PM_LEX_STATE_END); + return parse_symbol(parser, &lex_mode, PM_LEX_STATE_END, (uint16_t) (depth + 1)); } default: { pm_context_t recoverable = context_recoverable(parser, &parser->current); @@ -19549,8 +20610,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b * or any of the binary operators that can be written to a variable. */ static pm_node_t * -parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) { - pm_node_t *value = parse_value_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MATCH, diag_id); +parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id, uint16_t depth) { + pm_node_t *value = parse_value_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MATCH, false, diag_id, (uint16_t) (depth + 1)); // Contradicting binding powers, the right-hand-side value of the assignment // allows the `rescue` modifier. @@ -19560,7 +20621,7 @@ parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_ pm_token_t rescue = parser->current; parser_lex(parser); - pm_node_t *right = parse_expression(parser, binding_power, false, PM_ERR_RESCUE_MODIFIER_VALUE); + pm_node_t *right = parse_expression(parser, binding_power, false, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); return (pm_node_t *) pm_rescue_modifier_node_create(parser, value, &rescue, right); @@ -19618,11 +20679,16 @@ parse_assignment_value_local(pm_parser_t *parser, const pm_node_t *node) { * operator that allows multiple values after it. */ static pm_node_t * -parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) { - pm_node_t *value = parse_starred_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MATCH, diag_id); - parse_assignment_value_local(parser, value); +parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id, uint16_t depth) { + bool permitted = true; + if (previous_binding_power != PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_USTAR)) permitted = false; + pm_node_t *value = parse_starred_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MATCH, diag_id, (uint16_t) (depth + 1)); + if (!permitted) pm_parser_err_node(parser, value, PM_ERR_UNEXPECTED_MULTI_WRITE); + + parse_assignment_value_local(parser, value); bool single_value = true; + if (previous_binding_power == PM_BINDING_POWER_STATEMENT && (PM_NODE_TYPE_P(value, PM_SPLAT_NODE) || match1(parser, PM_TOKEN_COMMA))) { single_value = false; @@ -19633,7 +20699,7 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding value = (pm_node_t *) array; while (accept1(parser, PM_TOKEN_COMMA)) { - pm_node_t *element = parse_starred_expression(parser, binding_power, false, PM_ERR_ARRAY_ELEMENT); + pm_node_t *element = parse_starred_expression(parser, binding_power, false, PM_ERR_ARRAY_ELEMENT, (uint16_t) (depth + 1)); pm_array_node_elements_append(array, element); if (PM_NODE_TYPE_P(element, PM_MISSING_NODE)) break; @@ -19661,7 +20727,7 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding } } - pm_node_t *right = parse_expression(parser, binding_power, accepts_command_call_inner, PM_ERR_RESCUE_MODIFIER_VALUE); + pm_node_t *right = parse_expression(parser, binding_power, accepts_command_call_inner, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); return (pm_node_t *) pm_rescue_modifier_node_create(parser, value, &rescue, right); @@ -19693,126 +20759,130 @@ parse_call_operator_write(pm_parser_t *parser, pm_call_node_t *call_node, const } /** - * Returns true if the name of the capture group is a valid local variable that - * can be written to. + * This struct is used to pass information between the regular expression parser + * and the named capture callback. */ -static bool -parse_regular_expression_named_capture(pm_parser_t *parser, const uint8_t *source, size_t length) { - if (length == 0) { - return false; - } +typedef struct { + /** The parser that is parsing the regular expression. */ + pm_parser_t *parser; - // First ensure that it starts with a valid identifier starting character. - size_t width = char_is_identifier_start(parser, source); - if (!width) { - return false; - } + /** The call node wrapping the regular expression node. */ + pm_call_node_t *call; - // Next, ensure that it's not an uppercase character. - if (parser->encoding_changed) { - if (parser->encoding->isupper_char(source, (ptrdiff_t) length)) return false; - } else { - if (pm_encoding_utf_8_isupper_char(source, (ptrdiff_t) length)) return false; - } + /** The match write node that is being created. */ + pm_match_write_node_t *match; - // Next, iterate through all of the bytes of the string to ensure that they - // are all valid identifier characters. - const uint8_t *cursor = source + width; - while (cursor < source + length && (width = char_is_identifier(parser, cursor))) { - cursor += width; - } + /** The list of names that have been parsed. */ + pm_constant_id_list_t names; - return cursor == source + length; -} + /** + * Whether the content of the regular expression is shared. This impacts + * whether or not we used owned constants or shared constants in the + * constant pool for the names of the captures. + */ + bool shared; +} parse_regular_expression_named_capture_data_t; /** - * Potentially change a =~ with a regular expression with named captures into a - * match write node. + * This callback is called when the regular expression parser encounters a named + * capture group. */ -static pm_node_t * -parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t *content, pm_call_node_t *call) { - pm_string_list_t named_captures = { 0 }; - pm_node_t *result; - - if (pm_regexp_named_capture_group_names(pm_string_source(content), pm_string_length(content), &named_captures, parser->encoding_changed, parser->encoding) && (named_captures.length > 0)) { - // Since we should not create a MatchWriteNode when all capture names - // are invalid, creating a MatchWriteNode is delaid here. - pm_match_write_node_t *match = NULL; - pm_constant_id_list_t names = { 0 }; - - for (size_t index = 0; index < named_captures.length; index++) { - pm_string_t *string = &named_captures.strings[index]; - - const uint8_t *source = pm_string_source(string); - size_t length = pm_string_length(string); - - pm_location_t location; - pm_constant_id_t name; - - // If the name of the capture group isn't a valid identifier, we do - // not add it to the local table. - if (!parse_regular_expression_named_capture(parser, source, length)) continue; - - if (content->type == PM_STRING_SHARED) { - // If the unescaped string is a slice of the source, then we can - // copy the names directly. The pointers will line up. - location = (pm_location_t) { .start = source, .end = source + length }; - name = pm_parser_constant_id_location(parser, location.start, location.end); - } else { - // Otherwise, the name is a slice of the malloc-ed owned string, - // in which case we need to copy it out into a new string. - location = call->receiver->location; +static void +parse_regular_expression_named_capture(const pm_string_t *capture, void *data) { + parse_regular_expression_named_capture_data_t *callback_data = (parse_regular_expression_named_capture_data_t *) data; - void *memory = xmalloc(length); - if (memory == NULL) abort(); + pm_parser_t *parser = callback_data->parser; + pm_call_node_t *call = callback_data->call; + pm_constant_id_list_t *names = &callback_data->names; - memcpy(memory, source, length); - name = pm_parser_constant_id_owned(parser, (uint8_t *) memory, length); - } + const uint8_t *source = pm_string_source(capture); + size_t length = pm_string_length(capture); - if (name != 0) { - // We dont want to create duplicate targets if the capture name - // is duplicated. - if (pm_constant_id_list_includes(&names, name)) continue; - pm_constant_id_list_append(&names, name); + pm_location_t location; + pm_constant_id_t name; - int depth; - if ((depth = pm_parser_local_depth_constant_id(parser, name)) == -1) { - // If the identifier is not already a local, then we'll add - // it to the local table unless it's a keyword. - if (pm_local_is_keyword((const char *) source, length)) continue; + // If the name of the capture group isn't a valid identifier, we do + // not add it to the local table. + if (!pm_slice_is_valid_local(parser, source, source + length)) return; - pm_parser_local_add(parser, name, location.start, location.end, 0); - } + if (callback_data->shared) { + // If the unescaped string is a slice of the source, then we can + // copy the names directly. The pointers will line up. + location = (pm_location_t) { .start = source, .end = source + length }; + name = pm_parser_constant_id_location(parser, location.start, location.end); + } else { + // Otherwise, the name is a slice of the malloc-ed owned string, + // in which case we need to copy it out into a new string. + location = (pm_location_t) { .start = call->receiver->location.start, .end = call->receiver->location.end }; + + void *memory = xmalloc(length); + if (memory == NULL) abort(); + + memcpy(memory, source, length); + name = pm_parser_constant_id_owned(parser, (uint8_t *) memory, length); + } - // Here we lazily create the MatchWriteNode since we know we're - // about to add a target. - if (match == NULL) match = pm_match_write_node_create(parser, call); + // Add this name to the list of constants if it is valid, not duplicated, + // and not a keyword. + if (name != 0 && !pm_constant_id_list_includes(names, name)) { + pm_constant_id_list_append(names, name); - // Next, create the local variable target and add it to the - // list of targets for the match. - pm_node_t *target = (pm_node_t *) pm_local_variable_target_node_create(parser, &location, name, depth == -1 ? 0 : (uint32_t) depth); - pm_node_list_append(&match->targets, target); - } + int depth; + if ((depth = pm_parser_local_depth_constant_id(parser, name)) == -1) { + // If the local is not already a local but it is a keyword, then we + // do not want to add a capture for this. + if (pm_local_is_keyword((const char *) source, length)) return; + + // If the identifier is not already a local, then we will add it to + // the local table. + pm_parser_local_add(parser, name, location.start, location.end, 0); } - if (match != NULL) { - result = (pm_node_t *) match; - } else { - result = (pm_node_t *) call; + // Here we lazily create the MatchWriteNode since we know we're + // about to add a target. + if (callback_data->match == NULL) { + callback_data->match = pm_match_write_node_create(parser, call); } - pm_constant_id_list_free(&names); - } else { - result = (pm_node_t *) call; + // Next, create the local variable target and add it to the list of + // targets for the match. + pm_node_t *target = (pm_node_t *) pm_local_variable_target_node_create(parser, &location, name, depth == -1 ? 0 : (uint32_t) depth); + pm_node_list_append(&callback_data->match->targets, target); } +} - pm_string_list_free(&named_captures); - return result; +/** + * Potentially change a =~ with a regular expression with named captures into a + * match write node. + */ +static pm_node_t * +parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t *content, pm_call_node_t *call, bool extended_mode) { + parse_regular_expression_named_capture_data_t callback_data = { + .parser = parser, + .call = call, + .names = { 0 }, + .shared = content->type == PM_STRING_SHARED + }; + + parse_regular_expression_error_data_t error_data = { + .parser = parser, + .start = call->receiver->location.start, + .end = call->receiver->location.end, + .shared = content->type == PM_STRING_SHARED + }; + + pm_regexp_parse(parser, pm_string_source(content), pm_string_length(content), extended_mode, parse_regular_expression_named_capture, &callback_data, parse_regular_expression_error, &error_data); + pm_constant_id_list_free(&callback_data.names); + + if (callback_data.match != NULL) { + return (pm_node_t *) callback_data.match; + } else { + return (pm_node_t *) call; + } } static inline pm_node_t * -parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call) { +parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, uint16_t depth) { pm_token_t token = parser->current; switch (token.type) { @@ -19831,7 +20901,12 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t /* fallthrough */ case PM_CASE_WRITABLE: { parser_lex(parser); - pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_NODE_TYPE_P(node, PM_MULTI_TARGET_NODE) ? PM_BINDING_POWER_MULTI_ASSIGNMENT + 1 : binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL); + pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_NODE_TYPE_P(node, PM_MULTI_TARGET_NODE) ? PM_BINDING_POWER_MULTI_ASSIGNMENT + 1 : binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1)); + + if (PM_NODE_TYPE_P(node, PM_MULTI_TARGET_NODE) && previous_binding_power != PM_BINDING_POWER_STATEMENT) { + pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_MULTI_WRITE); + } + return parse_write(parser, node, &token, value); } case PM_SPLAT_NODE: { @@ -19839,7 +20914,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_multi_target_node_targets_append(parser, multi_target, node); parser_lex(parser); - pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_BINDING_POWER_MULTI_ASSIGNMENT + 1, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL); + pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_BINDING_POWER_MULTI_ASSIGNMENT + 1, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1)); return parse_write(parser, (pm_node_t *) multi_target, &token, value); } case PM_SOURCE_ENCODING_NODE: @@ -19852,7 +20927,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // In these special cases, we have specific error messages // and we will replace them with local variable writes. parser_lex(parser); - pm_node_t *value = parse_assignment_values(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL); + pm_node_t *value = parse_assignment_values(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1)); return parse_unwriteable_write(parser, node, &token, value); } default: @@ -19873,7 +20948,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_GLOBAL_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = (pm_node_t *) pm_global_variable_and_write_node_create(parser, node, &token, value); pm_node_destroy(parser, node); @@ -19882,7 +20957,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CLASS_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = (pm_node_t *) pm_class_variable_and_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value); pm_node_destroy(parser, node); @@ -19891,7 +20966,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CONSTANT_PATH_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *write = (pm_node_t *) pm_constant_path_and_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value); return parse_shareable_constant_write(parser, write); @@ -19899,7 +20974,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CONSTANT_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *write = (pm_node_t *) pm_constant_and_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value); pm_node_destroy(parser, node); @@ -19908,7 +20983,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_INSTANCE_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = (pm_node_t *) pm_instance_variable_and_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value); pm_node_destroy(parser, node); @@ -19918,14 +20993,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node; parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = (pm_node_t *) pm_local_variable_and_write_node_create(parser, node, &token, value, cast->name, cast->depth); pm_node_destroy(parser, node); return result; } case PM_CALL_NODE: { - parser_lex(parser); pm_call_node_t *cast = (pm_call_node_t *) node; // If we have a vcall (a method with no arguments and no @@ -19936,18 +21010,24 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_refute_numbered_parameter(parser, message_loc->start, message_loc->end); pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc->start, message_loc->end, 1); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ); + parser_lex(parser); + + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = (pm_node_t *) pm_local_variable_and_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0); pm_node_destroy(parser, (pm_node_t *) cast); return result; } + // Move past the token here so that we have already added + // the local variable by this point. + parser_lex(parser); + // If there is no call operator and the message is "[]" then // this is an aref expression, and we can transform it into // an aset expression. if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_INDEX)) { - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); return (pm_node_t *) pm_index_and_write_node_create(parser, cast, &token, value); } @@ -19959,7 +21039,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t } parse_call_operator_write(parser, cast, &token); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); return (pm_node_t *) pm_call_and_write_node_create(parser, cast, &token, value); } case PM_MULTI_WRITE_NODE: { @@ -19986,7 +21066,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_GLOBAL_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = (pm_node_t *) pm_global_variable_or_write_node_create(parser, node, &token, value); pm_node_destroy(parser, node); @@ -19995,7 +21075,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CLASS_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = (pm_node_t *) pm_class_variable_or_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value); pm_node_destroy(parser, node); @@ -20004,7 +21084,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CONSTANT_PATH_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *write = (pm_node_t *) pm_constant_path_or_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value); return parse_shareable_constant_write(parser, write); @@ -20012,7 +21092,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CONSTANT_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *write = (pm_node_t *) pm_constant_or_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value); pm_node_destroy(parser, node); @@ -20021,7 +21101,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_INSTANCE_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = (pm_node_t *) pm_instance_variable_or_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value); pm_node_destroy(parser, node); @@ -20031,14 +21111,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node; parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = (pm_node_t *) pm_local_variable_or_write_node_create(parser, node, &token, value, cast->name, cast->depth); pm_node_destroy(parser, node); return result; } case PM_CALL_NODE: { - parser_lex(parser); pm_call_node_t *cast = (pm_call_node_t *) node; // If we have a vcall (a method with no arguments and no @@ -20049,18 +21128,24 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_refute_numbered_parameter(parser, message_loc->start, message_loc->end); pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc->start, message_loc->end, 1); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ); + parser_lex(parser); + + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = (pm_node_t *) pm_local_variable_or_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0); pm_node_destroy(parser, (pm_node_t *) cast); return result; } + // Move past the token here so that we have already added + // the local variable by this point. + parser_lex(parser); + // If there is no call operator and the message is "[]" then // this is an aref expression, and we can transform it into // an aset expression. if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_INDEX)) { - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); return (pm_node_t *) pm_index_or_write_node_create(parser, cast, &token, value); } @@ -20072,7 +21157,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t } parse_call_operator_write(parser, cast, &token); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); return (pm_node_t *) pm_call_or_write_node_create(parser, cast, &token, value); } case PM_MULTI_WRITE_NODE: { @@ -20109,7 +21194,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_GLOBAL_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = (pm_node_t *) pm_global_variable_operator_write_node_create(parser, node, &token, value); pm_node_destroy(parser, node); @@ -20118,7 +21203,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CLASS_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = (pm_node_t *) pm_class_variable_operator_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value); pm_node_destroy(parser, node); @@ -20127,7 +21212,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CONSTANT_PATH_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *write = (pm_node_t *) pm_constant_path_operator_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value); return parse_shareable_constant_write(parser, write); @@ -20135,7 +21220,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CONSTANT_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *write = (pm_node_t *) pm_constant_operator_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value); pm_node_destroy(parser, node); @@ -20144,7 +21229,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_INSTANCE_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = (pm_node_t *) pm_instance_variable_operator_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value); pm_node_destroy(parser, node); @@ -20154,7 +21239,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node; parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = (pm_node_t *) pm_local_variable_operator_write_node_create(parser, node, &token, value, cast->name, cast->depth); pm_node_destroy(parser, node); @@ -20172,7 +21257,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_refute_numbered_parameter(parser, message_loc->start, message_loc->end); pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc->start, message_loc->end, 1); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = (pm_node_t *) pm_local_variable_operator_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0); pm_node_destroy(parser, (pm_node_t *) cast); @@ -20183,7 +21268,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // this is an aref expression, and we can transform it into // an aset expression. if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_INDEX)) { - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return (pm_node_t *) pm_index_operator_write_node_create(parser, cast, &token, value); } @@ -20195,7 +21280,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t } parse_call_operator_write(parser, cast, &token); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return (pm_node_t *) pm_call_operator_write_node_create(parser, cast, &token, value); } case PM_MULTI_WRITE_NODE: { @@ -20209,7 +21294,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // In this case we have an operator but we don't know what it's for. // We need to treat it as an error. For now, we'll mark it as an error // and just skip right past it. - pm_parser_err_previous(parser, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, pm_token_type_human(parser->current.type)); return node; } } @@ -20217,14 +21302,14 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_TOKEN_KEYWORD_AND: { parser_lex(parser); - pm_node_t *right = parse_expression(parser, binding_power, parser->previous.type == PM_TOKEN_KEYWORD_AND, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *right = parse_expression(parser, binding_power, parser->previous.type == PM_TOKEN_KEYWORD_AND, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return (pm_node_t *) pm_and_node_create(parser, node, &token, right); } case PM_TOKEN_KEYWORD_OR: case PM_TOKEN_PIPE_PIPE: { parser_lex(parser); - pm_node_t *right = parse_expression(parser, binding_power, parser->previous.type == PM_TOKEN_KEYWORD_OR, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *right = parse_expression(parser, binding_power, parser->previous.type == PM_TOKEN_KEYWORD_OR, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return (pm_node_t *) pm_or_node_create(parser, node, &token, right); } case PM_TOKEN_EQUAL_TILDE: { @@ -20236,7 +21321,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // // In this case, `foo` should be a method call and not a local yet. parser_lex(parser); - pm_node_t *argument = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *argument = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); // By default, we're going to create a call node and then return it. pm_call_node_t *call = pm_call_node_binary_create(parser, node, &token, argument, 0); @@ -20281,14 +21366,14 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_string_t owned; pm_string_owned_init(&owned, (uint8_t *) memory, total_length); - result = parse_regular_expression_named_captures(parser, &owned, call); + result = parse_regular_expression_named_captures(parser, &owned, call, PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)); pm_string_free(&owned); } } else if (PM_NODE_TYPE_P(node, PM_REGULAR_EXPRESSION_NODE)) { // If we have a regular expression node, then we can just parse // the named captures directly off the unescaped string. const pm_string_t *content = &((pm_regular_expression_node_t *) node)->unescaped; - result = parse_regular_expression_named_captures(parser, content, call); + result = parse_regular_expression_named_captures(parser, content, call, PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)); } return result; @@ -20315,7 +21400,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_TOKEN_STAR: case PM_TOKEN_STAR_STAR: { parser_lex(parser); - pm_node_t *argument = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *argument = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return (pm_node_t *) pm_call_node_binary_create(parser, node, &token, argument, 0); } case PM_TOKEN_GREATER: @@ -20327,7 +21412,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t } parser_lex(parser); - pm_node_t *argument = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + pm_node_t *argument = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return (pm_node_t *) pm_call_node_binary_create(parser, node, &token, argument, PM_CALL_NODE_FLAGS_COMPARISON); } case PM_TOKEN_AMPERSAND_DOT: @@ -20338,7 +21423,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // This if statement handles the foo.() syntax. if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) { - parse_arguments_list(parser, &arguments, true, false); + parse_arguments_list(parser, &arguments, true, false, (uint16_t) (depth + 1)); return (pm_node_t *) pm_call_node_shorthand_create(parser, node, &operator, &arguments); } @@ -20360,7 +21445,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t } } - parse_arguments_list(parser, &arguments, true, accepts_command_call); + parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1)); pm_call_node_t *call = pm_call_node_call_create(parser, node, &operator, &message, &arguments); if ( @@ -20369,7 +21454,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t arguments.opening_loc.start == NULL && match1(parser, PM_TOKEN_COMMA) ) { - return parse_targets_validate(parser, (pm_node_t *) call, PM_BINDING_POWER_INDEX); + return parse_targets_validate(parser, (pm_node_t *) call, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1)); } else { return (pm_node_t *) call; } @@ -20380,7 +21465,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *right = NULL; if (token_begins_expression_p(parser->current.type)) { - right = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + right = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); } return (pm_node_t *) pm_range_node_create(parser, node, &token, right); @@ -20389,30 +21474,30 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_token_t keyword = parser->current; parser_lex(parser); - pm_node_t *predicate = parse_value_expression(parser, binding_power, true, PM_ERR_CONDITIONAL_IF_PREDICATE); + pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_IF_PREDICATE, (uint16_t) (depth + 1)); return (pm_node_t *) pm_if_node_modifier_create(parser, node, &keyword, predicate); } case PM_TOKEN_KEYWORD_UNLESS_MODIFIER: { pm_token_t keyword = parser->current; parser_lex(parser); - pm_node_t *predicate = parse_value_expression(parser, binding_power, true, PM_ERR_CONDITIONAL_UNLESS_PREDICATE); + pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_UNLESS_PREDICATE, (uint16_t) (depth + 1)); return (pm_node_t *) pm_unless_node_modifier_create(parser, node, &keyword, predicate); } case PM_TOKEN_KEYWORD_UNTIL_MODIFIER: { parser_lex(parser); pm_statements_node_t *statements = pm_statements_node_create(parser); - pm_statements_node_body_append(parser, statements, node); + pm_statements_node_body_append(parser, statements, node, true); - pm_node_t *predicate = parse_value_expression(parser, binding_power, true, PM_ERR_CONDITIONAL_UNTIL_PREDICATE); + pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_UNTIL_PREDICATE, (uint16_t) (depth + 1)); return (pm_node_t *) pm_until_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0); } case PM_TOKEN_KEYWORD_WHILE_MODIFIER: { parser_lex(parser); pm_statements_node_t *statements = pm_statements_node_create(parser); - pm_statements_node_body_append(parser, statements, node); + pm_statements_node_body_append(parser, statements, node, true); - pm_node_t *predicate = parse_value_expression(parser, binding_power, true, PM_ERR_CONDITIONAL_WHILE_PREDICATE); + pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_WHILE_PREDICATE, (uint16_t) (depth + 1)); return (pm_node_t *) pm_while_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0); } case PM_TOKEN_QUESTION_MARK: { @@ -20423,7 +21508,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_token_t qmark = parser->current; parser_lex(parser); - pm_node_t *true_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_TERNARY_EXPRESSION_TRUE); + pm_node_t *true_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_TERNARY_EXPRESSION_TRUE, (uint16_t) (depth + 1)); if (parser->recovering) { // If parsing the true expression of this ternary resulted in a syntax @@ -20446,7 +21531,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t expect1(parser, PM_TOKEN_COLON, PM_ERR_TERNARY_COLON); pm_token_t colon = parser->previous; - pm_node_t *false_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_TERNARY_EXPRESSION_FALSE); + pm_node_t *false_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_TERNARY_EXPRESSION_FALSE, (uint16_t) (depth + 1)); context_pop(parser); pop_block_exits(parser, previous_block_exits); @@ -20465,7 +21550,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t if ( (parser->current.type == PM_TOKEN_PARENTHESIS_LEFT) || - (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR)) + (accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) ) { // If we have a constant immediately following a '::' operator, then // this can either be a constant path or a method call, depending on @@ -20476,7 +21561,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_token_t message = parser->previous; pm_arguments_t arguments = { 0 }; - parse_arguments_list(parser, &arguments, true, accepts_command_call); + parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1)); path = (pm_node_t *) pm_call_node_call_create(parser, node, &delimiter, &message, &arguments); } else { // Otherwise, this is a constant path. That would look like Foo::Bar. @@ -20485,7 +21570,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // If this is followed by a comma then it is a multiple assignment. if (previous_binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) { - return parse_targets_validate(parser, path, PM_BINDING_POWER_INDEX); + return parse_targets_validate(parser, path, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1)); } return path; @@ -20500,12 +21585,12 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // If we have an identifier following a '::' operator, then it is for // sure a method call. pm_arguments_t arguments = { 0 }; - parse_arguments_list(parser, &arguments, true, accepts_command_call); + parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1)); pm_call_node_t *call = pm_call_node_call_create(parser, node, &delimiter, &message, &arguments); // If this is followed by a comma then it is a multiple assignment. if (previous_binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) { - return parse_targets_validate(parser, (pm_node_t *) call, PM_BINDING_POWER_INDEX); + return parse_targets_validate(parser, (pm_node_t *) call, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1)); } return (pm_node_t *) call; @@ -20514,7 +21599,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // If we have a parenthesis following a '::' operator, then it is the // method call shorthand. That would look like Foo::(bar). pm_arguments_t arguments = { 0 }; - parse_arguments_list(parser, &arguments, true, false); + parse_arguments_list(parser, &arguments, true, false, (uint16_t) (depth + 1)); return (pm_node_t *) pm_call_node_shorthand_create(parser, node, &delimiter, &arguments); } @@ -20529,7 +21614,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t parser_lex(parser); accept1(parser, PM_TOKEN_NEWLINE); - pm_node_t *value = parse_expression(parser, binding_power, true, PM_ERR_RESCUE_MODIFIER_VALUE); + pm_node_t *value = parse_expression(parser, binding_power, true, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); return (pm_node_t *) pm_rescue_modifier_node_create(parser, node, &token, value); @@ -20542,7 +21627,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t if (!accept1(parser, PM_TOKEN_BRACKET_RIGHT)) { pm_accepts_block_stack_push(parser, true); - parse_arguments(parser, &arguments, false, PM_TOKEN_BRACKET_RIGHT); + parse_arguments(parser, &arguments, false, PM_TOKEN_BRACKET_RIGHT, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); expect1(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_EXPECT_RBRACKET); } @@ -20553,7 +21638,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // assignment and we should parse the targets. if (previous_binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) { pm_call_node_t *aref = pm_call_node_aref_create(parser, node, &arguments); - return parse_targets_validate(parser, (pm_node_t *) aref, PM_BINDING_POWER_INDEX); + return parse_targets_validate(parser, (pm_node_t *) aref, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1)); } // If we're at the end of the arguments, we can now check if there is a @@ -20561,10 +21646,10 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // add it to the arguments. pm_block_node_t *block = NULL; if (accept1(parser, PM_TOKEN_BRACE_LEFT)) { - block = parse_block(parser); + block = parse_block(parser, (uint16_t) (depth + 1)); pm_arguments_validate_block(parser, &arguments, block); } else if (pm_accepts_block_stack_p(parser) && accept1(parser, PM_TOKEN_KEYWORD_DO)) { - block = parse_block(parser); + block = parse_block(parser, (uint16_t) (depth + 1)); } if (block != NULL) { @@ -20591,7 +21676,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t parser_lex(parser); pm_constant_id_list_t captures = { 0 }; - pm_node_t *pattern = parse_pattern(parser, &captures, true, PM_ERR_PATTERN_EXPRESSION_AFTER_IN); + pm_node_t *pattern = parse_pattern(parser, &captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_IN, (uint16_t) (depth + 1)); parser->pattern_matching_newlines = previous_pattern_matching_newlines; pm_constant_id_list_free(&captures); @@ -20608,7 +21693,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t parser_lex(parser); pm_constant_id_list_t captures = { 0 }; - pm_node_t *pattern = parse_pattern(parser, &captures, true, PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET); + pm_node_t *pattern = parse_pattern(parser, &captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET, (uint16_t) (depth + 1)); parser->pattern_matching_newlines = previous_pattern_matching_newlines; pm_constant_id_list_free(&captures); @@ -20621,6 +21706,23 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t } } +#undef PM_PARSE_PATTERN_SINGLE +#undef PM_PARSE_PATTERN_TOP +#undef PM_PARSE_PATTERN_MULTI + +/** + * Determine if a given call node looks like a "command", which means it has + * arguments but does not have parentheses. + */ +static inline bool +pm_call_node_command_p(const pm_call_node_t *node) { + return ( + (node->opening_loc.start == NULL) && + (node->block == NULL || PM_NODE_TYPE_P(node->block, PM_BLOCK_ARGUMENT_NODE)) && + (node->arguments != NULL || node->block != NULL) + ); +} + /** * Parse an expression at the given point of the parser using the given binding * power to parse subsequent chains. If this function finds a syntax error, it @@ -20630,8 +21732,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t * determine if they need to perform additional cleanup. */ static pm_node_t * -parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) { - pm_node_t *node = parse_expression_prefix(parser, binding_power, accepts_command_call, diag_id); +parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth) { + if (PRISM_UNLIKELY(depth >= PRISM_DEPTH_MAXIMUM)) { + pm_parser_err_current(parser, PM_ERR_NESTING_TOO_DEEP); + return (pm_node_t *) pm_missing_node_create(parser, parser->current.start, parser->current.end); + } + + pm_node_t *node = parse_expression_prefix(parser, binding_power, accepts_command_call, accepts_label, diag_id, depth); switch (PM_NODE_TYPE(node)) { case PM_MISSING_NODE: @@ -20642,6 +21749,7 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc case PM_POST_EXECUTION_NODE: case PM_ALIAS_GLOBAL_VARIABLE_NODE: case PM_ALIAS_METHOD_NODE: + case PM_MULTI_WRITE_NODE: case PM_UNDEF_NODE: // These expressions are statements, and cannot be followed by // operators (except modifiers). @@ -20649,15 +21757,23 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc return node; } break; - case PM_RANGE_NODE: - // Range operators are non-associative, so that it does not - // associate with other range operators (i.e. `..1..` should be - // rejected). For this reason, we check such a case for unary ranges - // here, and if so, it returns the node immediately. - if ((((pm_range_node_t *) node)->left == NULL) && pm_binding_powers[parser->current.type].left >= PM_BINDING_POWER_RANGE) { + case PM_CALL_NODE: + // If we have a call node, then we need to check if it looks like a + // method call without parentheses that contains arguments. If it + // does, then it has different rules for parsing infix operators, + // namely that it only accepts composition (and/or) and modifiers + // (if/unless/etc.). + if ((pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_COMPOSITION) && pm_call_node_command_p((pm_call_node_t *) node)) { return node; } break; + case PM_SYMBOL_NODE: + // If we have a symbol node that is being parsed as a label, then we + // need to immediately return, because there should never be an + // infix operator following this node. + if (pm_symbol_node_label_p(node)) { + return node; + } default: break; } @@ -20665,23 +21781,75 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc // Otherwise we'll look and see if the next token can be parsed as an infix // operator. If it can, then we'll parse it using parse_expression_infix. pm_binding_powers_t current_binding_powers; + pm_token_type_t current_token_type; + while ( - current_binding_powers = pm_binding_powers[parser->current.type], + current_token_type = parser->current.type, + current_binding_powers = pm_binding_powers[current_token_type], binding_power <= current_binding_powers.left && current_binding_powers.binary ) { - node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, accepts_command_call); + node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, accepts_command_call, (uint16_t) (depth + 1)); + + switch (PM_NODE_TYPE(node)) { + case PM_MULTI_WRITE_NODE: + // Multi-write nodes are statements, and cannot be followed by + // operators except modifiers. + if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { + return node; + } + break; + case PM_CLASS_VARIABLE_WRITE_NODE: + case PM_CONSTANT_PATH_WRITE_NODE: + case PM_CONSTANT_WRITE_NODE: + case PM_GLOBAL_VARIABLE_WRITE_NODE: + case PM_INSTANCE_VARIABLE_WRITE_NODE: + case PM_LOCAL_VARIABLE_WRITE_NODE: + // These expressions are statements, by virtue of the right-hand + // side of their write being an implicit array. + if (PM_NODE_FLAG_P(node, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY) && pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { + return node; + } + break; + case PM_CALL_NODE: + // These expressions are also statements, by virtue of the + // right-hand side of the expression (i.e., the last argument to + // the call node) being an implicit array. + if (PM_NODE_FLAG_P(node, PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY) && pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { + return node; + } + break; + default: + break; + } + // If the operator is nonassoc and we should not be able to parse the + // upcoming infix operator, break. if (current_binding_powers.nonassoc) { - bool endless_range_p = PM_NODE_TYPE_P(node, PM_RANGE_NODE) && ((pm_range_node_t *) node)->right == NULL; - pm_binding_power_t left = endless_range_p ? PM_BINDING_POWER_TERM : current_binding_powers.left; - if ( - left <= pm_binding_powers[parser->current.type].left || - // Exceptionally to operator precedences, '1.. & 2' is rejected. - // '1.. || 2' is also an exception, but it is handled by the lexer. - // (Here, parser->current is PM_TOKEN_PIPE, not PM_TOKEN_PIPE_PIPE). - (endless_range_p && match1(parser, PM_TOKEN_AMPERSAND)) - ) { + // If this is a non-assoc operator and we are about to parse the + // exact same operator, then we need to add an error. + if (match1(parser, current_token_type)) { + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_NON_ASSOCIATIVE_OPERATOR, pm_token_type_human(parser->current.type), pm_token_type_human(current_token_type)); + break; + } + + // If this is an endless range, then we need to reject a couple of + // additional operators because it violates the normal operator + // precedence rules. Those patterns are: + // + // 1.. & 2 + // 1.. * 2 + // + if (PM_NODE_TYPE_P(node, PM_RANGE_NODE) && ((pm_range_node_t *) node)->right == NULL) { + if (match4(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_DOT, PM_TOKEN_AMPERSAND_DOT)) { + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_NON_ASSOCIATIVE_OPERATOR, pm_token_type_human(parser->current.type), pm_token_type_human(current_token_type)); + break; + } + + if (PM_BINDING_POWER_TERM <= pm_binding_powers[parser->current.type].left) { + break; + } + } else if (current_binding_powers.left <= pm_binding_powers[parser->current.type].left) { break; } } @@ -20757,7 +21925,7 @@ wrap_statements(pm_parser_t *parser, pm_statements_node_t *statements) { parser, arguments, pm_parser_constant_id_constant(parser, "print", 5) - )); + ), true); } if (PM_PARSER_COMMAND_LINE_OPTION_N(parser)) { @@ -20796,6 +21964,7 @@ wrap_statements(pm_parser_t *parser, pm_statements_node_t *statements) { )); pm_arguments_node_arguments_append(arguments, (pm_node_t *) keywords); + pm_node_flag_set((pm_node_t *) arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS); } pm_statements_node_t *wrapped_statements = pm_statements_node_create(parser); @@ -20803,7 +21972,7 @@ wrap_statements(pm_parser_t *parser, pm_statements_node_t *statements) { parser, (pm_node_t *) pm_call_node_fcall_synthesized_create(parser, arguments, pm_parser_constant_id_constant(parser, "gets", 4)), statements - )); + ), true); statements = wrapped_statements; } @@ -20823,8 +21992,11 @@ parse_program(pm_parser_t *parser) { pm_parser_scope_push(parser, true); } + pm_node_list_t current_block_exits = { 0 }; + pm_node_list_t *previous_block_exits = push_block_exits(parser, ¤t_block_exits); + parser_lex(parser); - pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_MAIN); + pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_MAIN, 0); if (statements == NULL) { statements = pm_statements_node_create(parser); @@ -20851,6 +22023,9 @@ parse_program(pm_parser_t *parser) { // node with a while loop based on the options. if (parser->command_line & (PM_OPTIONS_COMMAND_LINE_P | PM_OPTIONS_COMMAND_LINE_N)) { statements = wrap_statements(parser, statements); + } else { + flush_block_exits(parser, previous_block_exits); + pm_node_list_free(¤t_block_exits); } return (pm_node_t *) pm_program_node_create(parser, &locals, statements); @@ -20880,6 +22055,9 @@ pm_strnstr(const char *big, const char *little, size_t big_length) { return NULL; } +#ifdef _WIN32 +#define pm_parser_warn_shebang_carriage_return(parser, start, length) ((void) 0) +#else /** * Potentially warn the user if the shebang that has been found to include * "ruby" has a carriage return at the end, as that can cause problems on some @@ -20887,10 +22065,38 @@ pm_strnstr(const char *big, const char *little, size_t big_length) { */ static void pm_parser_warn_shebang_carriage_return(pm_parser_t *parser, const uint8_t *start, size_t length) { - if (length > 2 && start[length - 1] == '\n' && start[length - 2] == '\r') { + if (length > 2 && start[length - 2] == '\r' && start[length - 1] == '\n') { pm_parser_warn(parser, start, start + length, PM_WARN_SHEBANG_CARRIAGE_RETURN); } } +#endif + +/** + * Process the shebang when initializing the parser. This function assumes that + * the shebang_callback option has already been checked for nullability. + */ +static void +pm_parser_init_shebang(pm_parser_t *parser, const pm_options_t *options, const char *engine, size_t length) { + const char *switches = pm_strnstr(engine, " -", length); + if (switches == NULL) return; + + pm_options_t next_options = *options; + options->shebang_callback( + &next_options, + (const uint8_t *) (switches + 1), + length - ((size_t) (switches - engine)) - 1, + options->shebang_callback_data + ); + + size_t encoding_length; + if ((encoding_length = pm_string_length(&next_options.encoding)) > 0) { + const uint8_t *encoding_source = pm_string_source(&next_options.encoding); + parser_lex_magic_comment_encoding_value(parser, encoding_source, encoding_source + encoding_length); + } + + parser->command_line = next_options.command_line; + parser->frozen_string_literal = next_options.frozen_string_literal; +} /** * Initialize a parser with the given start and end pointers. @@ -20900,6 +22106,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm assert(source != NULL); *parser = (pm_parser_t) { + .node_id = 0, .lex_state = PM_LEX_STATE_BEG, .enclosure_nesting = 0, .lambda_enclosure_nesting = -1, @@ -20937,15 +22144,18 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm .explicit_encoding = NULL, .command_line = 0, .parsing_eval = false, + .partial_script = false, .command_start = true, .recovering = false, + .encoding_locked = false, .encoding_changed = false, .pattern_matching_newlines = false, .in_keyword_arg = false, .current_block_exits = NULL, .semantic_token_seen = false, .frozen_string_literal = PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET, - .current_regular_expression_ascii_only = false + .current_regular_expression_ascii_only = false, + .warn_mismatched_indentation = true }; // Initialize the constant pool. We're going to completely guess as to the @@ -20986,6 +22196,9 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm parser_lex_magic_comment_encoding_value(parser, encoding_source, encoding_source + encoding_length); } + // encoding_locked option + parser->encoding_locked = options->encoding_locked; + // frozen_string_literal option parser->frozen_string_literal = options->frozen_string_literal; @@ -20995,8 +22208,12 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm // version option parser->version = options->version; + // partial_script + parser->partial_script = options->partial_script; + // scopes option parser->parsing_eval = options->scopes_count > 0; + if (parser->parsing_eval) parser->warn_mismatched_indentation = false; for (size_t scope_index = 0; scope_index < options->scopes_count; scope_index++) { const pm_options_scope_t *scope = pm_options_scope_get(options, scope_index); @@ -21004,7 +22221,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm // Scopes given from the outside are not allowed to have numbered // parameters. - parser->current_scope->numbered_parameters = PM_SCOPE_NUMBERED_PARAMETERS_DISALLOWED; + parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_IMPLICIT_DISALLOWED; for (size_t local_index = 0; local_index < scope->locals_count; local_index++) { const pm_string_t *local = pm_options_scope_local_get(scope, local_index); @@ -21039,17 +22256,42 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm // "ruby" and start parsing from there. bool search_shebang = PM_PARSER_COMMAND_LINE_OPTION_X(parser); - // If the first two bytes of the source are a shebang, then we'll indicate - // that the encoding comment is at the end of the shebang. - if (peek(parser) == '#' && peek_offset(parser, 1) == '!') { - const uint8_t *newline = next_newline(parser->start, parser->end - parser->start); - size_t length = (size_t) ((newline != NULL ? newline : parser->end) - parser->start); + // If the first two bytes of the source are a shebang, then we will do a bit + // of extra processing. + // + // First, we'll indicate that the encoding comment is at the end of the + // shebang. This means that when a shebang is present the encoding comment + // can begin on the second line. + // + // Second, we will check if the shebang includes "ruby". If it does, then we + // we will start parsing from there. We will also potentially warning the + // user if there is a carriage return at the end of the shebang. We will + // also potentially call the shebang callback if this is the main script to + // allow the caller to parse the shebang and find any command-line options. + // If the shebang does not include "ruby" and this is the main script being + // parsed, then we will start searching the file for a shebang that does + // contain "ruby" as if -x were passed on the command line. + const uint8_t *newline = next_newline(parser->start, parser->end - parser->start); + size_t length = (size_t) ((newline != NULL ? newline : parser->end) - parser->start); + + if (length > 2 && parser->current.end[0] == '#' && parser->current.end[1] == '!') { + const char *engine; + + if ((engine = pm_strnstr((const char *) parser->start, "ruby", length)) != NULL) { + if (newline != NULL) { + parser->encoding_comment_start = newline + 1; + + if (options == NULL || options->main_script) { + pm_parser_warn_shebang_carriage_return(parser, parser->start, length + 1); + } + } + + if (options != NULL && options->main_script && options->shebang_callback != NULL) { + pm_parser_init_shebang(parser, options, engine, length - ((size_t) (engine - (const char *) parser->start))); + } - if (pm_strnstr((const char *) parser->start, "ruby", length) != NULL) { - pm_parser_warn_shebang_carriage_return(parser, parser->start, length); - if (newline != NULL) parser->encoding_comment_start = newline + 1; search_shebang = false; - } else { + } else if (options->main_script && !parser->parsing_eval) { search_shebang = true; } } @@ -21077,13 +22319,19 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm size_t length = (size_t) ((newline != NULL ? newline : parser->end) - cursor); if (length > 2 && cursor[0] == '#' && cursor[1] == '!') { - if (parser->newline_list.size == 1) { - pm_parser_warn_shebang_carriage_return(parser, cursor, length); - } - - if (pm_strnstr((const char *) cursor, "ruby", length) != NULL) { + const char *engine; + if ((engine = pm_strnstr((const char *) cursor, "ruby", length)) != NULL) { found_shebang = true; - parser->encoding_comment_start = newline + 1; + + if (newline != NULL) { + pm_parser_warn_shebang_carriage_return(parser, cursor, length + 1); + parser->encoding_comment_start = newline + 1; + } + + if (options != NULL && options->shebang_callback != NULL) { + pm_parser_init_shebang(parser, options, engine, length - ((size_t) (engine - (const char *) cursor))); + } + break; } } @@ -21187,18 +22435,21 @@ pm_parse_stream_read(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t #define LINE_SIZE 4096 char line[LINE_SIZE]; - while (fgets(line, LINE_SIZE, stream) != NULL) { - size_t length = strlen(line); + while (memset(line, '\n', LINE_SIZE), fgets(line, LINE_SIZE, stream) != NULL) { + size_t length = LINE_SIZE; + while (length > 0 && line[length - 1] == '\n') length--; - if (length == LINE_SIZE && line[length - 1] != '\n') { + if (length == LINE_SIZE) { // If we read a line that is the maximum size and it doesn't end // with a newline, then we'll just append it to the buffer and // continue reading. + length--; pm_buffer_append_string(buffer, line, length); continue; } // Append the line to the buffer. + length--; pm_buffer_append_string(buffer, line, length); // Check if the line matches the __END__ marker. If it does, then stop @@ -21393,330 +22644,165 @@ pm_serialize_parse_comments(pm_buffer_t *buffer, const uint8_t *source, size_t s #endif -/** An error that is going to be formatted into the output. */ -typedef struct { - /** A pointer to the diagnostic that was generated during parsing. */ - pm_diagnostic_t *error; +/******************************************************************************/ +/* Slice queries for the Ruby API */ +/******************************************************************************/ - /** The start line of the diagnostic message. */ - int32_t line; +/** The category of slice returned from pm_slice_type. */ +typedef enum { + /** Returned when the given encoding name is invalid. */ + PM_SLICE_TYPE_ERROR = -1, - /** The column start of the diagnostic message. */ - uint32_t column_start; + /** Returned when no other types apply to the slice. */ + PM_SLICE_TYPE_NONE, - /** The column end of the diagnostic message. */ - uint32_t column_end; -} pm_error_t; + /** Returned when the slice is a valid local variable name. */ + PM_SLICE_TYPE_LOCAL, -/** The format that will be used to format the errors into the output. */ -typedef struct { - /** The prefix that will be used for line numbers. */ - const char *number_prefix; - - /** The prefix that will be used for blank lines. */ - const char *blank_prefix; - - /** The divider that will be used between sections of source code. */ - const char *divider; - - /** The length of the blank prefix. */ - size_t blank_prefix_length; - - /** The length of the divider. */ - size_t divider_length; -} pm_error_format_t; - -#define PM_COLOR_GRAY "\033[38;5;102m" -#define PM_COLOR_RED "\033[1;31m" -#define PM_COLOR_RESET "\033[m" - -static inline pm_error_t * -pm_parser_errors_format_sort(const pm_parser_t *parser, const pm_list_t *error_list, const pm_newline_list_t *newline_list) { - pm_error_t *errors = xcalloc(error_list->size, sizeof(pm_error_t)); - if (errors == NULL) return NULL; - - int32_t start_line = parser->start_line; - for (pm_diagnostic_t *error = (pm_diagnostic_t *) error_list->head; error != NULL; error = (pm_diagnostic_t *) error->node.next) { - pm_line_column_t start = pm_newline_list_line_column(newline_list, error->location.start, start_line); - pm_line_column_t end = pm_newline_list_line_column(newline_list, error->location.end, start_line); - - // We're going to insert this error into the array in sorted order. We - // do this by finding the first error that has a line number greater - // than the current error and then inserting the current error before - // that one. - size_t index = 0; - while ( - (index < error_list->size) && - (errors[index].error != NULL) && - ( - (errors[index].line < start.line) || - ((errors[index].line == start.line) && (errors[index].column_start < start.column)) - ) - ) index++; + /** Returned when the slice is a valid constant name. */ + PM_SLICE_TYPE_CONSTANT, - // Now we're going to shift all of the errors after this one down one - // index to make room for the new error. - if (index + 1 < error_list->size) { - memmove(&errors[index + 1], &errors[index], sizeof(pm_error_t) * (error_list->size - index - 1)); - } + /** Returned when the slice is a valid method name. */ + PM_SLICE_TYPE_METHOD_NAME +} pm_slice_type_t; + +/** + * Check that the slice is a valid local variable name or constant. + */ +pm_slice_type_t +pm_slice_type(const uint8_t *source, size_t length, const char *encoding_name) { + // first, get the right encoding object + const pm_encoding_t *encoding = pm_encoding_find((const uint8_t *) encoding_name, (const uint8_t *) (encoding_name + strlen(encoding_name))); + if (encoding == NULL) return PM_SLICE_TYPE_ERROR; - // Finally, we'll insert the error into the array. - uint32_t column_end; - if (start.line == end.line) { - column_end = end.column; + // check that there is at least one character + if (length == 0) return PM_SLICE_TYPE_NONE; + + size_t width; + if ((width = encoding->alpha_char(source, (ptrdiff_t) length)) != 0) { + // valid because alphabetical + } else if (*source == '_') { + // valid because underscore + width = 1; + } else if ((*source >= 0x80) && ((width = encoding->char_width(source, (ptrdiff_t) length)) > 0)) { + // valid because multibyte + } else { + // invalid because no match + return PM_SLICE_TYPE_NONE; + } + + // determine the type of the slice based on the first character + const uint8_t *end = source + length; + pm_slice_type_t result = encoding->isupper_char(source, end - source) ? PM_SLICE_TYPE_CONSTANT : PM_SLICE_TYPE_LOCAL; + + // next, iterate through all of the bytes of the string to ensure that they + // are all valid identifier characters + source += width; + + while (source < end) { + if ((width = encoding->alnum_char(source, end - source)) != 0) { + // valid because alphanumeric + source += width; + } else if (*source == '_') { + // valid because underscore + source++; + } else if ((*source >= 0x80) && ((width = encoding->char_width(source, end - source)) > 0)) { + // valid because multibyte + source += width; } else { - column_end = (uint32_t) (newline_list->offsets[start.line - start_line + 1] - newline_list->offsets[start.line - start_line] - 1); + // invalid because no match + break; } + } - // Ensure we have at least one column of error. - if (start.column == column_end) column_end++; - - errors[index] = (pm_error_t) { - .error = error, - .line = start.line, - .column_start = start.column, - .column_end = column_end - }; + // accept a ! or ? at the end of the slice as a method name + if (*source == '!' || *source == '?' || *source == '=') { + source++; + result = PM_SLICE_TYPE_METHOD_NAME; } - return errors; + // valid if we are at the end of the slice + return source == end ? result : PM_SLICE_TYPE_NONE; } -static inline void -pm_parser_errors_format_line(const pm_parser_t *parser, const pm_newline_list_t *newline_list, const char *number_prefix, int32_t line, pm_buffer_t *buffer) { - int32_t line_delta = line - parser->start_line; - assert(line_delta >= 0); - - size_t index = (size_t) line_delta; - assert(index < newline_list->size); - - const uint8_t *start = &parser->start[newline_list->offsets[index]]; - const uint8_t *end; - - if (index >= newline_list->size - 1) { - end = parser->end; - } else { - end = &parser->start[newline_list->offsets[index + 1]]; +/** + * Check that the slice is a valid local variable name. + */ +PRISM_EXPORTED_FUNCTION pm_string_query_t +pm_string_query_local(const uint8_t *source, size_t length, const char *encoding_name) { + switch (pm_slice_type(source, length, encoding_name)) { + case PM_SLICE_TYPE_ERROR: + return PM_STRING_QUERY_ERROR; + case PM_SLICE_TYPE_NONE: + case PM_SLICE_TYPE_CONSTANT: + case PM_SLICE_TYPE_METHOD_NAME: + return PM_STRING_QUERY_FALSE; + case PM_SLICE_TYPE_LOCAL: + return PM_STRING_QUERY_TRUE; } - pm_buffer_append_format(buffer, number_prefix, line); - pm_buffer_append_string(buffer, (const char *) start, (size_t) (end - start)); - - if (end == parser->end && end[-1] != '\n') { - pm_buffer_append_string(buffer, "\n", 1); - } + assert(false && "unreachable"); + return PM_STRING_QUERY_FALSE; } /** - * Format the errors on the parser into the given buffer. + * Check that the slice is a valid constant name. */ -PRISM_EXPORTED_FUNCTION void -pm_parser_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, pm_buffer_t *buffer, bool colorize, bool inline_messages) { - assert(error_list->size != 0); - - // First, we're going to sort all of the errors by line number using an - // insertion sort into a newly allocated array. - const int32_t start_line = parser->start_line; - const pm_newline_list_t *newline_list = &parser->newline_list; - - pm_error_t *errors = pm_parser_errors_format_sort(parser, error_list, newline_list); - if (errors == NULL) return; - - // Now we're going to determine how we're going to format line numbers and - // blank lines based on the maximum number of digits in the line numbers - // that are going to be displaid. - pm_error_format_t error_format; - int32_t first_line_number = errors[0].line; - int32_t last_line_number = errors[error_list->size - 1].line; - - // If we have a maximum line number that is negative, then we're going to - // use the absolute value for comparison but multiple by 10 to additionally - // have a column for the negative sign. - if (first_line_number < 0) first_line_number = (-first_line_number) * 10; - if (last_line_number < 0) last_line_number = (-last_line_number) * 10; - int32_t max_line_number = first_line_number > last_line_number ? first_line_number : last_line_number; - - if (max_line_number < 10) { - if (colorize) { - error_format = (pm_error_format_t) { - .number_prefix = PM_COLOR_GRAY "%1" PRIi32 " | " PM_COLOR_RESET, - .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, - .divider = PM_COLOR_GRAY " ~~~~~" PM_COLOR_RESET "\n" - }; - } else { - error_format = (pm_error_format_t) { - .number_prefix = "%1" PRIi32 " | ", - .blank_prefix = " | ", - .divider = " ~~~~~\n" - }; - } - } else if (max_line_number < 100) { - if (colorize) { - error_format = (pm_error_format_t) { - .number_prefix = PM_COLOR_GRAY "%2" PRIi32 " | " PM_COLOR_RESET, - .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, - .divider = PM_COLOR_GRAY " ~~~~~~" PM_COLOR_RESET "\n" - }; - } else { - error_format = (pm_error_format_t) { - .number_prefix = "%2" PRIi32 " | ", - .blank_prefix = " | ", - .divider = " ~~~~~~\n" - }; - } - } else if (max_line_number < 1000) { - if (colorize) { - error_format = (pm_error_format_t) { - .number_prefix = PM_COLOR_GRAY "%3" PRIi32 " | " PM_COLOR_RESET, - .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, - .divider = PM_COLOR_GRAY " ~~~~~~~" PM_COLOR_RESET "\n" - }; - } else { - error_format = (pm_error_format_t) { - .number_prefix = "%3" PRIi32 " | ", - .blank_prefix = " | ", - .divider = " ~~~~~~~\n" - }; - } - } else if (max_line_number < 10000) { - if (colorize) { - error_format = (pm_error_format_t) { - .number_prefix = PM_COLOR_GRAY "%4" PRIi32 " | " PM_COLOR_RESET, - .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, - .divider = PM_COLOR_GRAY " ~~~~~~~~" PM_COLOR_RESET "\n" - }; - } else { - error_format = (pm_error_format_t) { - .number_prefix = "%4" PRIi32 " | ", - .blank_prefix = " | ", - .divider = " ~~~~~~~~\n" - }; - } - } else { - if (colorize) { - error_format = (pm_error_format_t) { - .number_prefix = PM_COLOR_GRAY "%5" PRIi32 " | " PM_COLOR_RESET, - .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, - .divider = PM_COLOR_GRAY " ~~~~~~~~" PM_COLOR_RESET "\n" - }; - } else { - error_format = (pm_error_format_t) { - .number_prefix = "%5" PRIi32 " | ", - .blank_prefix = " | ", - .divider = " ~~~~~~~~\n" - }; - } +PRISM_EXPORTED_FUNCTION pm_string_query_t +pm_string_query_constant(const uint8_t *source, size_t length, const char *encoding_name) { + switch (pm_slice_type(source, length, encoding_name)) { + case PM_SLICE_TYPE_ERROR: + return PM_STRING_QUERY_ERROR; + case PM_SLICE_TYPE_NONE: + case PM_SLICE_TYPE_LOCAL: + case PM_SLICE_TYPE_METHOD_NAME: + return PM_STRING_QUERY_FALSE; + case PM_SLICE_TYPE_CONSTANT: + return PM_STRING_QUERY_TRUE; } - error_format.blank_prefix_length = strlen(error_format.blank_prefix); - error_format.divider_length = strlen(error_format.divider); - - // Now we're going to iterate through every error in our error list and - // display it. While we're iterating, we will display some padding lines of - // the source before the error to give some context. We'll be careful not to - // display the same line twice in case the errors are close enough in the - // source. - int32_t last_line = parser->start_line - 1; - const pm_encoding_t *encoding = parser->encoding; - - for (size_t index = 0; index < error_list->size; index++) { - pm_error_t *error = &errors[index]; - - // Here we determine how many lines of padding of the source to display, - // based on the difference from the last line that was displaid. - if (error->line - last_line > 1) { - if (error->line - last_line > 2) { - if ((index != 0) && (error->line - last_line > 3)) { - pm_buffer_append_string(buffer, error_format.divider, error_format.divider_length); - } - - pm_buffer_append_string(buffer, " ", 2); - pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, error->line - 2, buffer); - } - - pm_buffer_append_string(buffer, " ", 2); - pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, error->line - 1, buffer); - } - - // If this is the first error or we're on a new line, then we'll display - // the line that has the error in it. - if ((index == 0) || (error->line != last_line)) { - if (colorize) { - pm_buffer_append_string(buffer, PM_COLOR_RED "> " PM_COLOR_RESET, 12); - } else { - pm_buffer_append_string(buffer, "> ", 2); - } - pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, error->line, buffer); - } - - const uint8_t *start = &parser->start[newline_list->offsets[error->line - start_line]]; - if (start == parser->end) pm_buffer_append_byte(buffer, '\n'); - - // Now we'll display the actual error message. We'll do this by first - // putting the prefix to the line, then a bunch of blank spaces - // depending on the column, then as many carets as we need to display - // the width of the error, then the error message itself. - // - // Note that this doesn't take into account the width of the actual - // character when displaid in the terminal. For some east-asian - // languages or emoji, this means it can be thrown off pretty badly. We - // will need to solve this eventually. - pm_buffer_append_string(buffer, " ", 2); - pm_buffer_append_string(buffer, error_format.blank_prefix, error_format.blank_prefix_length); - - size_t column = 0; - while (column < error->column_start) { - pm_buffer_append_byte(buffer, ' '); - - size_t char_width = encoding->char_width(start + column, parser->end - (start + column)); - column += (char_width == 0 ? 1 : char_width); - } - - if (colorize) pm_buffer_append_string(buffer, PM_COLOR_RED, 7); - pm_buffer_append_byte(buffer, '^'); - - size_t char_width = encoding->char_width(start + column, parser->end - (start + column)); - column += (char_width == 0 ? 1 : char_width); - - while (column < error->column_end) { - pm_buffer_append_byte(buffer, '~'); - - size_t char_width = encoding->char_width(start + column, parser->end - (start + column)); - column += (char_width == 0 ? 1 : char_width); - } - - if (colorize) pm_buffer_append_string(buffer, PM_COLOR_RESET, 3); - - if (inline_messages) { - pm_buffer_append_byte(buffer, ' '); - assert(error->error != NULL); - - const char *message = error->error->message; - pm_buffer_append_string(buffer, message, strlen(message)); - } - - pm_buffer_append_byte(buffer, '\n'); + assert(false && "unreachable"); + return PM_STRING_QUERY_FALSE; +} - // Here we determine how many lines of padding to display after the - // error, depending on where the next error is in source. - last_line = error->line; - int32_t next_line = (index == error_list->size - 1) ? (((int32_t) newline_list->size) + parser->start_line) : errors[index + 1].line; +/** + * Check that the slice is a valid method name. + */ +PRISM_EXPORTED_FUNCTION pm_string_query_t +pm_string_query_method_name(const uint8_t *source, size_t length, const char *encoding_name) { +#define B(p) ((p) ? PM_STRING_QUERY_TRUE : PM_STRING_QUERY_FALSE) +#define C1(c) (*source == c) +#define C2(s) (memcmp(source, s, 2) == 0) +#define C3(s) (memcmp(source, s, 3) == 0) - if (next_line - last_line > 1) { - pm_buffer_append_string(buffer, " ", 2); - pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, ++last_line, buffer); - } + switch (pm_slice_type(source, length, encoding_name)) { + case PM_SLICE_TYPE_ERROR: + return PM_STRING_QUERY_ERROR; + case PM_SLICE_TYPE_NONE: + break; + case PM_SLICE_TYPE_LOCAL: + // numbered parameters are not valid method names + return B((length != 2) || (source[0] != '_') || (source[1] == '0') || !pm_char_is_decimal_digit(source[1])); + case PM_SLICE_TYPE_CONSTANT: + // all constants are valid method names + case PM_SLICE_TYPE_METHOD_NAME: + // all method names are valid method names + return PM_STRING_QUERY_TRUE; + } - if (next_line - last_line > 1) { - pm_buffer_append_string(buffer, " ", 2); - pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, ++last_line, buffer); - } + switch (length) { + case 1: + return B(C1('&') || C1('`') || C1('!') || C1('^') || C1('>') || C1('<') || C1('-') || C1('%') || C1('|') || C1('+') || C1('/') || C1('*') || C1('~')); + case 2: + return B(C2("!=") || C2("!~") || C2("[]") || C2("==") || C2("=~") || C2(">=") || C2(">>") || C2("<=") || C2("<<") || C2("**")); + case 3: + return B(C3("===") || C3("<=>") || C3("[]=")); + default: + return PM_STRING_QUERY_FALSE; } - // Finally, we'll free the array of errors that we allocated. - xfree(errors); +#undef B +#undef C1 +#undef C2 +#undef C3 } - -#undef PM_COLOR_GRAY -#undef PM_COLOR_RED -#undef PM_COLOR_RESET diff --git a/src/regexp.c b/src/regexp.c index 6e0fdd295c2..e4bf74c1423 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -1,9 +1,14 @@ #include "prism/regexp.h" +#define PM_REGEXP_PARSE_DEPTH_MAX 4096 + /** * This is the parser that is going to handle parsing regular expressions. */ typedef struct { + /** The parser that is currently being used. */ + pm_parser_t *parser; + /** A pointer to the start of the source that we are parsing. */ const uint8_t *start; @@ -13,39 +18,48 @@ typedef struct { /** A pointer to the end of the source that we are parsing. */ const uint8_t *end; - /** A list of named captures that we've found. */ - pm_string_list_t *named_captures; + /** + * Whether or not the regular expression currently being parsed is in + * extended mode, wherein whitespace is ignored and comments are allowed. + */ + bool extended_mode; /** Whether the encoding has changed from the default. */ bool encoding_changed; /** The encoding of the source. */ const pm_encoding_t *encoding; + + /** The callback to call when a named capture group is found. */ + pm_regexp_name_callback_t name_callback; + + /** The data to pass to the name callback. */ + void *name_data; + + /** The callback to call when a parse error is found. */ + pm_regexp_error_callback_t error_callback; + + /** The data to pass to the error callback. */ + void *error_data; } pm_regexp_parser_t; /** - * This initializes a new parser with the given source. + * Append an error to the parser. */ -static void -pm_regexp_parser_init(pm_regexp_parser_t *parser, const uint8_t *start, const uint8_t *end, pm_string_list_t *named_captures, bool encoding_changed, const pm_encoding_t *encoding) { - *parser = (pm_regexp_parser_t) { - .start = start, - .cursor = start, - .end = end, - .named_captures = named_captures, - .encoding_changed = encoding_changed, - .encoding = encoding - }; +static inline void +pm_regexp_parse_error(pm_regexp_parser_t *parser, const uint8_t *start, const uint8_t *end, const char *message) { + parser->error_callback(start, end, message, parser->error_data); } /** - * This appends a new string to the list of named captures. + * This appends a new string to the list of named captures. This function + * assumes the caller has already checked the validity of the name callback. */ static void pm_regexp_parser_named_capture(pm_regexp_parser_t *parser, const uint8_t *start, const uint8_t *end) { pm_string_t string; pm_string_shared_init(&string, start, end); - pm_string_list_append(parser->named_captures, &string); + parser->name_callback(&string, parser->name_data); pm_string_free(&string); } @@ -217,21 +231,24 @@ pm_regexp_parse_range_quantifier(pm_regexp_parser_t *parser) { */ static bool pm_regexp_parse_quantifier(pm_regexp_parser_t *parser) { - if (pm_regexp_char_is_eof(parser)) return true; - - switch (*parser->cursor) { - case '*': - case '+': - case '?': - parser->cursor++; - return true; - case '{': - parser->cursor++; - return pm_regexp_parse_range_quantifier(parser); - default: - // In this case there is no quantifier. - return true; + while (!pm_regexp_char_is_eof(parser)) { + switch (*parser->cursor) { + case '*': + case '+': + case '?': + parser->cursor++; + break; + case '{': + parser->cursor++; + if (!pm_regexp_parse_range_quantifier(parser)) return false; + break; + default: + // In this case there is no quantifier. + return true; + } } + + return true; } /** @@ -255,20 +272,20 @@ pm_regexp_parse_posix_class(pm_regexp_parser_t *parser) { // Forward declaration because character sets can be nested. static bool -pm_regexp_parse_lbracket(pm_regexp_parser_t *parser); +pm_regexp_parse_lbracket(pm_regexp_parser_t *parser, uint16_t depth); /** * match-char-set : '[' '^'? (match-range | match-char)* ']' * ; */ static bool -pm_regexp_parse_character_set(pm_regexp_parser_t *parser) { +pm_regexp_parse_character_set(pm_regexp_parser_t *parser, uint16_t depth) { pm_regexp_char_accept(parser, '^'); while (!pm_regexp_char_is_eof(parser) && *parser->cursor != ']') { switch (*parser->cursor++) { case '[': - pm_regexp_parse_lbracket(parser); + pm_regexp_parse_lbracket(parser, (uint16_t) (depth + 1)); break; case '\\': if (!pm_regexp_char_is_eof(parser)) { @@ -288,7 +305,18 @@ pm_regexp_parse_character_set(pm_regexp_parser_t *parser) { * A left bracket can either mean a POSIX class or a character set. */ static bool -pm_regexp_parse_lbracket(pm_regexp_parser_t *parser) { +pm_regexp_parse_lbracket(pm_regexp_parser_t *parser, uint16_t depth) { + if (depth >= PM_REGEXP_PARSE_DEPTH_MAX) { + pm_regexp_parse_error(parser, parser->start, parser->end, "parse depth limit over"); + return false; + } + + if ((parser->cursor < parser->end) && parser->cursor[0] == ']') { + parser->cursor++; + pm_regexp_parse_error(parser, parser->cursor - 1, parser->cursor, "empty char-class"); + return true; + } + const uint8_t *reset = parser->cursor; if ((parser->cursor + 2 < parser->end) && parser->cursor[0] == '[' && parser->cursor[1] == ':') { @@ -298,13 +326,13 @@ pm_regexp_parse_lbracket(pm_regexp_parser_t *parser) { parser->cursor = reset; } - return pm_regexp_parse_character_set(parser); + return pm_regexp_parse_character_set(parser, depth); } // Forward declaration here since parsing groups needs to go back up the grammar // to parse expressions within them. static bool -pm_regexp_parse_expression(pm_regexp_parser_t *parser); +pm_regexp_parse_expression(pm_regexp_parser_t *parser, uint16_t depth); /** * These are the states of the options that are configurable on the regular @@ -396,6 +424,19 @@ pm_regexp_options_remove(pm_regexp_options_t *options, uint8_t key) { return false; } +/** + * True if the given key is set in the options. + */ +static uint8_t +pm_regexp_options_state(pm_regexp_options_t *options, uint8_t key) { + if (key >= PRISM_REGEXP_OPTION_STATE_SLOT_MINIMUM && key <= PRISM_REGEXP_OPTION_STATE_SLOT_MAXIMUM) { + key = (uint8_t) (key - PRISM_REGEXP_OPTION_STATE_SLOT_MINIMUM); + return options->values[key]; + } + + return false; +} + /** * Groups can have quite a few different patterns for syntax. They basically * just wrap a set of expressions, but they can potentially have options after a @@ -418,17 +459,27 @@ pm_regexp_options_remove(pm_regexp_options_t *options, uint8_t key) { * * (?imxdau-imx:subexp) - turn on and off configuration for an expression */ static bool -pm_regexp_parse_group(pm_regexp_parser_t *parser) { +pm_regexp_parse_group(pm_regexp_parser_t *parser, uint16_t depth) { + const uint8_t *group_start = parser->cursor; + + pm_regexp_options_t options; + pm_regexp_options_init(&options); + // First, parse any options for the group. if (pm_regexp_char_accept(parser, '?')) { if (pm_regexp_char_is_eof(parser)) { + pm_regexp_parse_error(parser, group_start, parser->cursor, "end pattern in group"); return false; } - pm_regexp_options_t options; - pm_regexp_options_init(&options); switch (*parser->cursor) { case '#': { // inline comments + parser->cursor++; + if (pm_regexp_char_is_eof(parser)) { + pm_regexp_parse_error(parser, group_start, parser->cursor, "end pattern in group"); + return false; + } + if (parser->encoding_changed && parser->encoding->multibyte) { bool escaped = false; @@ -472,6 +523,7 @@ pm_regexp_parse_group(pm_regexp_parser_t *parser) { case '<': parser->cursor++; if (pm_regexp_char_is_eof(parser)) { + pm_regexp_parse_error(parser, group_start, parser->cursor, "end pattern with unmatched parenthesis"); return false; } @@ -485,7 +537,15 @@ pm_regexp_parse_group(pm_regexp_parser_t *parser) { if (!pm_regexp_char_find(parser, '>')) { return false; } - pm_regexp_parser_named_capture(parser, start, parser->cursor - 1); + + if (parser->cursor - start == 1) { + pm_regexp_parse_error(parser, start, parser->cursor, "group name is empty"); + } + + if (parser->name_callback != NULL) { + pm_regexp_parser_named_capture(parser, start, parser->cursor - 1); + } + break; } } @@ -496,7 +556,10 @@ pm_regexp_parse_group(pm_regexp_parser_t *parser) { return false; } - pm_regexp_parser_named_capture(parser, start, parser->cursor - 1); + if (parser->name_callback != NULL) { + pm_regexp_parser_named_capture(parser, start, parser->cursor - 1); + } + break; } case '(': // conditional expression @@ -516,6 +579,18 @@ pm_regexp_parse_group(pm_regexp_parser_t *parser) { return false; } + // If we are at the end of the group of options and there is no + // subexpression, then we are going to be setting the options + // for the parent group. In this case we are safe to return now. + if (*parser->cursor == ')') { + if (pm_regexp_options_state(&options, 'x') == PM_REGEXP_OPTION_STATE_ADDED) { + parser->extended_mode = true; + } + + parser->cursor++; + return true; + } + // If we hit a -, then we're done parsing options. if (*parser->cursor != '-') break; @@ -533,22 +608,57 @@ pm_regexp_parse_group(pm_regexp_parser_t *parser) { if (pm_regexp_char_is_eof(parser)) { return false; } + + // If we are at the end of the group of options and there is no + // subexpression, then we are going to be setting the options + // for the parent group. In this case we are safe to return now. + if (*parser->cursor == ')') { + switch (pm_regexp_options_state(&options, 'x')) { + case PM_REGEXP_OPTION_STATE_ADDED: + parser->extended_mode = true; + break; + case PM_REGEXP_OPTION_STATE_REMOVED: + parser->extended_mode = false; + break; + } + + parser->cursor++; + return true; + } + break; default: - return false; + parser->cursor++; + pm_regexp_parse_error(parser, parser->cursor - 1, parser->cursor, "undefined group option"); + break; } } + bool extended_mode = parser->extended_mode; + switch (pm_regexp_options_state(&options, 'x')) { + case PM_REGEXP_OPTION_STATE_ADDED: + parser->extended_mode = true; + break; + case PM_REGEXP_OPTION_STATE_REMOVED: + parser->extended_mode = false; + break; + } + // Now, parse the expressions within this group. while (!pm_regexp_char_is_eof(parser) && *parser->cursor != ')') { - if (!pm_regexp_parse_expression(parser)) { + if (!pm_regexp_parse_expression(parser, (uint16_t) (depth + 1))) { + parser->extended_mode = extended_mode; return false; } pm_regexp_char_accept(parser, '|'); } // Finally, make sure we have a closing parenthesis. - return pm_regexp_char_expect(parser, ')'); + parser->extended_mode = extended_mode; + if (pm_regexp_char_expect(parser, ')')) return true; + + pm_regexp_parse_error(parser, group_start, parser->cursor, "end pattern with unmatched parenthesis"); + return false; } /** @@ -564,12 +674,12 @@ pm_regexp_parse_group(pm_regexp_parser_t *parser) { * ; */ static bool -pm_regexp_parse_item(pm_regexp_parser_t *parser) { +pm_regexp_parse_item(pm_regexp_parser_t *parser, uint16_t depth) { switch (*parser->cursor) { case '^': case '$': parser->cursor++; - return true; + return pm_regexp_parse_quantifier(parser); case '\\': parser->cursor++; if (!pm_regexp_char_is_eof(parser)) { @@ -578,10 +688,26 @@ pm_regexp_parse_item(pm_regexp_parser_t *parser) { return pm_regexp_parse_quantifier(parser); case '(': parser->cursor++; - return pm_regexp_parse_group(parser) && pm_regexp_parse_quantifier(parser); + return pm_regexp_parse_group(parser, depth) && pm_regexp_parse_quantifier(parser); case '[': parser->cursor++; - return pm_regexp_parse_lbracket(parser) && pm_regexp_parse_quantifier(parser); + return pm_regexp_parse_lbracket(parser, depth) && pm_regexp_parse_quantifier(parser); + case '*': + case '?': + case '+': + parser->cursor++; + pm_regexp_parse_error(parser, parser->cursor - 1, parser->cursor, "target of repeat operator is not specified"); + return true; + case ')': + parser->cursor++; + pm_regexp_parse_error(parser, parser->cursor - 1, parser->cursor, "unmatched close parenthesis"); + return true; + case '#': + if (parser->extended_mode) { + if (!pm_regexp_char_find(parser, '\n')) parser->cursor = parser->end; + return true; + } + /* fallthrough */ default: { size_t width; if (!parser->encoding_changed) { @@ -603,13 +729,18 @@ pm_regexp_parse_item(pm_regexp_parser_t *parser) { * ; */ static bool -pm_regexp_parse_expression(pm_regexp_parser_t *parser) { - if (!pm_regexp_parse_item(parser)) { +pm_regexp_parse_expression(pm_regexp_parser_t *parser, uint16_t depth) { + if (depth >= PM_REGEXP_PARSE_DEPTH_MAX) { + pm_regexp_parse_error(parser, parser->start, parser->end, "parse depth limit over"); + return false; + } + + if (!pm_regexp_parse_item(parser, depth)) { return false; } while (!pm_regexp_char_is_eof(parser) && *parser->cursor != ')' && *parser->cursor != '|') { - if (!pm_regexp_parse_item(parser)) { + if (!pm_regexp_parse_item(parser, depth)) { return false; } } @@ -625,29 +756,31 @@ pm_regexp_parse_expression(pm_regexp_parser_t *parser) { */ static bool pm_regexp_parse_pattern(pm_regexp_parser_t *parser) { - return ( - ( - // Exit early if the pattern is empty. - pm_regexp_char_is_eof(parser) || - // Parse the first expression in the pattern. - pm_regexp_parse_expression(parser) - ) && - ( - // Return now if we've parsed the entire pattern. - pm_regexp_char_is_eof(parser) || - // Otherwise, we should have a pipe character. - (pm_regexp_char_expect(parser, '|') && pm_regexp_parse_pattern(parser)) - ) - ); + do { + if (pm_regexp_char_is_eof(parser)) return true; + if (!pm_regexp_parse_expression(parser, 0)) return false; + } while (pm_regexp_char_accept(parser, '|')); + + return pm_regexp_char_is_eof(parser); } /** * Parse a regular expression and extract the names of all of the named capture * groups. */ -PRISM_EXPORTED_FUNCTION bool -pm_regexp_named_capture_group_names(const uint8_t *source, size_t size, pm_string_list_t *named_captures, bool encoding_changed, const pm_encoding_t *encoding) { - pm_regexp_parser_t parser; - pm_regexp_parser_init(&parser, source, source + size, named_captures, encoding_changed, encoding); - return pm_regexp_parse_pattern(&parser); +PRISM_EXPORTED_FUNCTION void +pm_regexp_parse(pm_parser_t *parser, const uint8_t *source, size_t size, bool extended_mode, pm_regexp_name_callback_t name_callback, void *name_data, pm_regexp_error_callback_t error_callback, void *error_data) { + pm_regexp_parse_pattern(&(pm_regexp_parser_t) { + .parser = parser, + .start = source, + .cursor = source, + .end = source + size, + .extended_mode = extended_mode, + .encoding_changed = parser->encoding_changed, + .encoding = parser->encoding, + .name_callback = name_callback, + .name_data = name_data, + .error_callback = error_callback, + .error_data = error_data + }); } diff --git a/src/static_literals.c b/src/static_literals.c index 08f61c81fa1..b8604321c98 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -58,6 +58,25 @@ murmur_hash(const uint8_t *key, size_t length) { return hash; } +/** + * Hash the value of an integer and return it. + */ +static uint32_t +integer_hash(const pm_integer_t *integer) { + uint32_t hash; + if (integer->values) { + hash = murmur_hash((const uint8_t *) integer->values, sizeof(uint32_t) * integer->length); + } else { + hash = murmur_hash((const uint8_t *) &integer->value, sizeof(uint32_t)); + } + + if (integer->negative) { + hash ^= murmur_scramble((uint32_t) 1); + } + + return hash; +} + /** * Return the hash of the given node. It is important that nodes that have * equivalent static literal values have the same hash. This is because we use @@ -68,19 +87,8 @@ node_hash(const pm_static_literals_metadata_t *metadata, const pm_node_t *node) switch (PM_NODE_TYPE(node)) { case PM_INTEGER_NODE: { // Integers hash their value. - const pm_integer_t *integer = &((const pm_integer_node_t *) node)->value; - uint32_t hash; - if (integer->values) { - hash = murmur_hash((const uint8_t *) integer->values, sizeof(uint32_t) * integer->length); - } else { - hash = murmur_hash((const uint8_t *) &integer->value, sizeof(uint32_t)); - } - - if (integer->negative) { - hash ^= murmur_scramble((uint32_t) 1); - } - - return hash; + const pm_integer_node_t *cast = (const pm_integer_node_t *) node; + return integer_hash(&cast->value); } case PM_SOURCE_LINE_NODE: { // Source lines hash their line number. @@ -94,11 +102,9 @@ node_hash(const pm_static_literals_metadata_t *metadata, const pm_node_t *node) return murmur_hash((const uint8_t *) value, sizeof(double)); } case PM_RATIONAL_NODE: { - // Rationals hash their numeric value. Because their numeric value - // is stored as a subnode, we hash that node and then mix in the - // fact that this is a rational node. - const pm_node_t *numeric = ((const pm_rational_node_t *) node)->numeric; - return node_hash(metadata, numeric) ^ murmur_scramble((uint32_t) node->type); + // Rationals hash their numerator and denominator. + const pm_rational_node_t *cast = (const pm_rational_node_t *) node; + return integer_hash(&cast->numerator) ^ integer_hash(&cast->denominator) ^ murmur_scramble((uint32_t) cast->base.type); } case PM_IMAGINARY_NODE: { // Imaginaries hash their numeric value. Because their numeric value @@ -148,7 +154,7 @@ node_hash(const pm_static_literals_metadata_t *metadata, const pm_node_t *node) * and must be able to compare all node types that will be stored in this hash. */ static pm_node_t * -pm_node_hash_insert(pm_node_hash_t *hash, const pm_static_literals_metadata_t *metadata, pm_node_t *node, int (*compare)(const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right)) { +pm_node_hash_insert(pm_node_hash_t *hash, const pm_static_literals_metadata_t *metadata, pm_node_t *node, bool replace, int (*compare)(const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right)) { // If we are out of space, we need to resize the hash. This will cause all // of the nodes to be rehashed and reinserted into the new hash. if (hash->size * 2 >= hash->capacity) { @@ -196,9 +202,14 @@ pm_node_hash_insert(pm_node_hash_t *hash, const pm_static_literals_metadata_t *m // already in the hash. Otherwise, we can just increment the size and insert // the new node. pm_node_t *result = hash->nodes[index]; - if (result == NULL) hash->size++; - hash->nodes[index] = node; + if (result == NULL) { + hash->size++; + hash->nodes[index] = node; + } else if (replace) { + hash->nodes[index] = node; + } + return result; } @@ -275,8 +286,15 @@ pm_compare_number_nodes(const pm_static_literals_metadata_t *metadata, const pm_ switch (PM_NODE_TYPE(left)) { case PM_IMAGINARY_NODE: return pm_compare_number_nodes(metadata, ((const pm_imaginary_node_t *) left)->numeric, ((const pm_imaginary_node_t *) right)->numeric); - case PM_RATIONAL_NODE: - return pm_compare_number_nodes(metadata, ((const pm_rational_node_t *) left)->numeric, ((const pm_rational_node_t *) right)->numeric); + case PM_RATIONAL_NODE: { + const pm_rational_node_t *left_rational = (const pm_rational_node_t *) left; + const pm_rational_node_t *right_rational = (const pm_rational_node_t *) right; + + int result = pm_integer_compare(&left_rational->denominator, &right_rational->denominator); + if (result != 0) return result; + + return pm_integer_compare(&left_rational->numerator, &right_rational->numerator); + } case PM_INTEGER_NODE: return pm_compare_integer_nodes(metadata, left, right); case PM_FLOAT_NODE: @@ -335,7 +353,7 @@ pm_compare_regular_expression_nodes(PRISM_ATTRIBUTE_UNUSED const pm_static_liter * Add a node to the set of static literals. */ pm_node_t * -pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node) { +pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace) { switch (PM_NODE_TYPE(node)) { case PM_INTEGER_NODE: case PM_SOURCE_LINE_NODE: @@ -347,6 +365,7 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line .encoding_name = NULL }, node, + replace, pm_compare_integer_nodes ); case PM_FLOAT_NODE: @@ -358,6 +377,7 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line .encoding_name = NULL }, node, + replace, pm_compare_float_nodes ); case PM_RATIONAL_NODE: @@ -370,6 +390,7 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line .encoding_name = NULL }, node, + replace, pm_compare_number_nodes ); case PM_STRING_NODE: @@ -382,6 +403,7 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line .encoding_name = NULL }, node, + replace, pm_compare_string_nodes ); case PM_REGULAR_EXPRESSION_NODE: @@ -393,6 +415,7 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line .encoding_name = NULL }, node, + replace, pm_compare_regular_expression_nodes ); case PM_SYMBOL_NODE: @@ -404,26 +427,27 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line .encoding_name = NULL }, node, + replace, pm_compare_string_nodes ); case PM_TRUE_NODE: { pm_node_t *duplicated = literals->true_node; - literals->true_node = node; + if ((duplicated == NULL) || replace) literals->true_node = node; return duplicated; } case PM_FALSE_NODE: { pm_node_t *duplicated = literals->false_node; - literals->false_node = node; + if ((duplicated == NULL) || replace) literals->false_node = node; return duplicated; } case PM_NIL_NODE: { pm_node_t *duplicated = literals->nil_node; - literals->nil_node = node; + if ((duplicated == NULL) || replace) literals->nil_node = node; return duplicated; } case PM_SOURCE_ENCODING_NODE: { pm_node_t *duplicated = literals->source_encoding_node; - literals->source_encoding_node = node; + if ((duplicated == NULL) || replace) literals->source_encoding_node = node; return duplicated; } default: @@ -456,7 +480,7 @@ pm_static_literal_positive_p(const pm_node_t *node) { case PM_INTEGER_NODE: return !((const pm_integer_node_t *) node)->value.negative; case PM_RATIONAL_NODE: - return pm_static_literal_positive_p(((const pm_rational_node_t *) node)->numeric); + return !((const pm_rational_node_t *) node)->numerator.negative; case PM_IMAGINARY_NODE: return pm_static_literal_positive_p(((const pm_imaginary_node_t *) node)->numeric); default: @@ -465,43 +489,6 @@ pm_static_literal_positive_p(const pm_node_t *node) { } } -/** - * Inspect a rational node that wraps a float node. This is going to be a - * poor-man's version of the Ruby `Rational#to_s` method, because we're not - * going to try to reduce the rational by finding the GCD. We'll leave that for - * a future improvement. - */ -static void -pm_rational_inspect(pm_buffer_t *buffer, pm_rational_node_t *node) { - const uint8_t *start = node->base.location.start; - const uint8_t *end = node->base.location.end - 1; // r - - while (start < end && *start == '0') start++; // 0.1 -> .1 - while (end > start && end[-1] == '0') end--; // 1.0 -> 1. - size_t length = (size_t) (end - start); - - const uint8_t *point = memchr(start, '.', length); - assert(point && "should have a decimal point"); - - uint8_t *digits = malloc(length - 1); - if (digits == NULL) return; - - memcpy(digits, start, (unsigned long) (point - start)); - memcpy(digits + (point - start), point + 1, (unsigned long) (end - point - 1)); - - pm_integer_t numerator = { 0 }; - pm_integer_parse(&numerator, PM_INTEGER_BASE_DECIMAL, digits, digits + length - 1); - - pm_buffer_append_byte(buffer, '('); - pm_integer_string(buffer, &numerator); - pm_buffer_append_string(buffer, "/1", 2); - for (size_t index = 0; index < (size_t) (end - point - 1); index++) pm_buffer_append_byte(buffer, '0'); - pm_buffer_append_byte(buffer, ')'); - - pm_integer_free(&numerator); - free(digits); -} - /** * Create a string-based representation of the given static literal. */ @@ -544,7 +531,9 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met pm_buffer_append_string(buffer, "(0", 2); if (pm_static_literal_positive_p(numeric)) pm_buffer_append_byte(buffer, '+'); pm_static_literal_inspect_node(buffer, metadata, numeric); - if (PM_NODE_TYPE_P(numeric, PM_RATIONAL_NODE)) pm_buffer_append_byte(buffer, '*'); + if (PM_NODE_TYPE_P(numeric, PM_RATIONAL_NODE)) { + pm_buffer_append_byte(buffer, '*'); + } pm_buffer_append_string(buffer, "i)", 2); break; } @@ -555,22 +544,12 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met pm_buffer_append_string(buffer, "nil", 3); break; case PM_RATIONAL_NODE: { - const pm_node_t *numeric = ((const pm_rational_node_t *) node)->numeric; - - switch (PM_NODE_TYPE(numeric)) { - case PM_INTEGER_NODE: - pm_buffer_append_byte(buffer, '('); - pm_static_literal_inspect_node(buffer, metadata, numeric); - pm_buffer_append_string(buffer, "/1)", 3); - break; - case PM_FLOAT_NODE: - pm_rational_inspect(buffer, (pm_rational_node_t *) node); - break; - default: - assert(false && "unreachable"); - break; - } - + const pm_rational_node_t *rational = (const pm_rational_node_t *) node; + pm_buffer_append_byte(buffer, '('); + pm_integer_string(buffer, &rational->numerator); + pm_buffer_append_byte(buffer, '/'); + pm_integer_string(buffer, &rational->denominator); + pm_buffer_append_byte(buffer, ')'); break; } case PM_REGULAR_EXPRESSION_NODE: { @@ -624,7 +603,7 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met /** * Create a string-based representation of the given static literal. */ -PRISM_EXPORTED_FUNCTION void +void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_newline_list_t *newline_list, int32_t start_line, const char *encoding_name, const pm_node_t *node) { pm_static_literal_inspect_node( buffer, diff --git a/src/util/pm_constant_pool.c b/src/util/pm_constant_pool.c index 2a3203f4c46..624002cec9f 100644 --- a/src/util/pm_constant_pool.c +++ b/src/util/pm_constant_pool.c @@ -61,14 +61,6 @@ pm_constant_id_list_includes(pm_constant_id_list_t *list, pm_constant_id_t id) { return false; } -/** - * Get the memory size of a list of constant ids. - */ -size_t -pm_constant_id_list_memsize(pm_constant_id_list_t *list) { - return sizeof(pm_constant_id_list_t) + (list->capacity * sizeof(pm_constant_id_t)); -} - /** * Free the memory associated with a list of constant ids. */ diff --git a/src/util/pm_integer.c b/src/util/pm_integer.c index e523bae90b1..4170ecc58db 100644 --- a/src/util/pm_integer.c +++ b/src/util/pm_integer.c @@ -43,12 +43,12 @@ big_add(pm_integer_t *destination, pm_integer_t *left, pm_integer_t *right, uint length++; } - *destination = (pm_integer_t) { 0, length, values, false }; + *destination = (pm_integer_t) { length, values, 0, false }; } /** * Internal use for karatsuba_multiply. Calculates `a - b - c` with the given - * base. Assume a, b, c, a - b - c all to be poitive. + * base. Assume a, b, c, a - b - c all to be positive. * Return pm_integer_t with values allocated. Not normalized. */ static void @@ -87,7 +87,7 @@ big_sub2(pm_integer_t *destination, pm_integer_t *a, pm_integer_t *b, pm_integer } while (a_length > 1 && values[a_length - 1] == 0) a_length--; - *destination = (pm_integer_t) { 0, a_length, values, false }; + *destination = (pm_integer_t) { a_length, values, 0, false }; } /** @@ -130,7 +130,7 @@ karatsuba_multiply(pm_integer_t *destination, pm_integer_t *left, pm_integer_t * } while (length > 1 && values[length - 1] == 0) length--; - *destination = (pm_integer_t) { 0, length, values, false }; + *destination = (pm_integer_t) { length, values, 0, false }; return; } @@ -142,16 +142,16 @@ karatsuba_multiply(pm_integer_t *destination, pm_integer_t *left, pm_integer_t * if (end_offset > right_length) end_offset = right_length; pm_integer_t sliced_left = { - .value = 0, .length = left_length, .values = left_values, + .value = 0, .negative = false }; pm_integer_t sliced_right = { - .value = 0, .length = end_offset - start_offset, .values = right_values + start_offset, + .value = 0, .negative = false }; @@ -169,15 +169,15 @@ karatsuba_multiply(pm_integer_t *destination, pm_integer_t *left, pm_integer_t * pm_integer_free(&product); } - *destination = (pm_integer_t) { 0, left_length + right_length, values, false }; + *destination = (pm_integer_t) { left_length + right_length, values, 0, false }; return; } size_t half = left_length / 2; - pm_integer_t x0 = { 0, half, left_values, false }; - pm_integer_t x1 = { 0, left_length - half, left_values + half, false }; - pm_integer_t y0 = { 0, half, right_values, false }; - pm_integer_t y1 = { 0, right_length - half, right_values + half, false }; + pm_integer_t x0 = { half, left_values, 0, false }; + pm_integer_t x1 = { left_length - half, left_values + half, 0, false }; + pm_integer_t y0 = { half, right_values, 0, false }; + pm_integer_t y1 = { right_length - half, right_values + half, 0, false }; pm_integer_t z0 = { 0 }; karatsuba_multiply(&z0, &x0, &y0, base); @@ -229,7 +229,7 @@ karatsuba_multiply(pm_integer_t *destination, pm_integer_t *left, pm_integer_t * pm_integer_free(&y01); pm_integer_free(&xy); - *destination = (pm_integer_t) { 0, length, values, false }; + *destination = (pm_integer_t) { length, values, 0, false }; } /** @@ -323,7 +323,7 @@ pm_integer_normalize(pm_integer_t *integer) { bool negative = integer->negative && value != 0; pm_integer_free(integer); - *integer = (pm_integer_t) { .value = value, .length = 0, .values = NULL, .negative = negative }; + *integer = (pm_integer_t) { .values = NULL, .value = value, .length = 0, .negative = negative }; } /** @@ -412,7 +412,7 @@ pm_integer_parse_powof2(pm_integer_t *integer, uint32_t base, const uint8_t *dig } while (length > 1 && values[length - 1] == 0) length--; - *integer = (pm_integer_t) { .value = 0, .length = length, .values = values, .negative = false }; + *integer = (pm_integer_t) { .length = length, .values = values, .value = 0, .negative = false }; pm_integer_normalize(integer); } @@ -438,7 +438,7 @@ pm_integer_parse_decimal(pm_integer_t *integer, const uint8_t *digits, size_t di } // Convert base from 10**9 to 1<<32. - pm_integer_convert_base(integer, &((pm_integer_t) { .value = 0, .length = length, .values = values, .negative = false }), 1000000000, ((uint64_t) 1 << 32)); + pm_integer_convert_base(integer, &((pm_integer_t) { .length = length, .values = values, .value = 0, .negative = false }), 1000000000, ((uint64_t) 1 << 32)); xfree(values); } @@ -471,15 +471,18 @@ pm_integer_parse_big(pm_integer_t *integer, uint32_t multiplier, const uint8_t * * has already been validated, as internal validation checks are not performed * here. */ -PRISM_EXPORTED_FUNCTION void +void pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end) { - // Ignore unary +. Unary + is parsed differently and will not end up here. + // Ignore unary +. Unary - is parsed differently and will not end up here. // Instead, it will modify the parsed integer later. if (*start == '+') start++; // Determine the multiplier from the base, and skip past any prefixes. uint32_t multiplier = 10; switch (base) { + case PM_INTEGER_BASE_DEFAULT: + while (*start == '0') start++; // 01 -> 1 + break; case PM_INTEGER_BASE_BINARY: start += 2; // 0b multiplier = 2; @@ -533,14 +536,6 @@ pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *s integer->value = (uint32_t) value; } -/** - * Return the memory size of the integer. - */ -size_t -pm_integer_memsize(const pm_integer_t *integer) { - return sizeof(pm_integer_t) + integer->length * sizeof(uint32_t); -} - /** * Compare two integers. This function returns -1 if the left integer is less * than the right integer, 0 if they are equal, and 1 if the left integer is @@ -572,6 +567,39 @@ pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right) { return 0; } +/** + * Reduce a ratio of integers to its simplest form. + */ +void pm_integers_reduce(pm_integer_t *numerator, pm_integer_t *denominator) { + // If either the numerator or denominator do not fit into a 32-bit integer, + // then this function is a no-op. In the future, we may consider reducing + // even the larger numbers, but for now we're going to keep it simple. + if ( + // If the numerator doesn't fit into a 32-bit integer, return early. + numerator->length != 0 || + // If the denominator doesn't fit into a 32-bit integer, return early. + denominator->length != 0 || + // If the numerator is 0, then return early. + numerator->value == 0 || + // If the denominator is 1, then return early. + denominator->value == 1 + ) return; + + // Find the greatest common divisor of the numerator and denominator. + uint32_t divisor = numerator->value; + uint32_t remainder = denominator->value; + + while (remainder != 0) { + uint32_t temporary = remainder; + remainder = divisor % remainder; + divisor = temporary; + } + + // Divide the numerator and denominator by the greatest common divisor. + numerator->value /= divisor; + denominator->value /= divisor; +} + /** * Convert an integer to a decimal string. */ diff --git a/src/util/pm_newline_list.c b/src/util/pm_newline_list.c index ce07ce8c8e4..8331618f54f 100644 --- a/src/util/pm_newline_list.c +++ b/src/util/pm_newline_list.c @@ -54,6 +54,35 @@ pm_newline_list_append(pm_newline_list_t *list, const uint8_t *cursor) { return true; } +/** + * Returns the line of the given offset. If the offset is not in the list, the + * line of the closest offset less than the given offset is returned. + */ +int32_t +pm_newline_list_line(const pm_newline_list_t *list, const uint8_t *cursor, int32_t start_line) { + assert(cursor >= list->start); + size_t offset = (size_t) (cursor - list->start); + + size_t left = 0; + size_t right = list->size - 1; + + while (left <= right) { + size_t mid = left + (right - left) / 2; + + if (list->offsets[mid] == offset) { + return ((int32_t) mid) + start_line; + } + + if (list->offsets[mid] < offset) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + return ((int32_t) left) + start_line - 1; +} + /** * Returns the line and column of the given offset. If the offset is not in the * list, the line and column of the closest offset less than the given offset diff --git a/src/util/pm_string.c b/src/util/pm_string.c index 8342edc34ef..7e56dec9f7e 100644 --- a/src/util/pm_string.c +++ b/src/util/pm_string.c @@ -47,6 +47,62 @@ pm_string_constant_init(pm_string_t *string, const char *source, size_t length) }; } +#ifdef _WIN32 +/** + * Represents a file handle on Windows, where the path will need to be freed + * when the file is closed. + */ +typedef struct { + /** The path to the file, which will become allocated memory. */ + WCHAR *path; + + /** The handle to the file, which will start as uninitialized memory. */ + HANDLE file; +} pm_string_file_handle_t; + +/** + * Open the file indicated by the filepath parameter for reading on Windows. + * Perform any kind of normalization that needs to happen on the filepath. + */ +static pm_string_init_result_t +pm_string_file_handle_open(pm_string_file_handle_t *handle, const char *filepath) { + int length = MultiByteToWideChar(CP_UTF8, 0, filepath, -1, NULL, 0); + if (length == 0) return PM_STRING_INIT_ERROR_GENERIC; + + handle->path = xmalloc(sizeof(WCHAR) * ((size_t) length)); + if ((handle->path == NULL) || (MultiByteToWideChar(CP_UTF8, 0, filepath, -1, handle->path, length) == 0)) { + xfree(handle->path); + return PM_STRING_INIT_ERROR_GENERIC; + } + + handle->file = CreateFileW(handle->path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); + if (handle->file == INVALID_HANDLE_VALUE) { + pm_string_init_result_t result = PM_STRING_INIT_ERROR_GENERIC; + + if (GetLastError() == ERROR_ACCESS_DENIED) { + DWORD attributes = GetFileAttributesW(handle->path); + if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) { + result = PM_STRING_INIT_ERROR_DIRECTORY; + } + } + + xfree(handle->path); + return result; + } + + return PM_STRING_INIT_SUCCESS; +} + +/** + * Close the file handle and free the path. + */ +static void +pm_string_file_handle_close(pm_string_file_handle_t *handle) { + xfree(handle->path); + CloseHandle(handle->file); +} +#endif + /** * Read the file indicated by the filepath parameter into source and load its * contents and size into the given `pm_string_t`. The given `pm_string_t` @@ -58,62 +114,66 @@ pm_string_constant_init(pm_string_t *string, const char *source, size_t length) * `MapViewOfFile`, on POSIX systems that have access to `mmap` we'll use * `mmap`, and on other POSIX systems we'll use `read`. */ -PRISM_EXPORTED_FUNCTION bool +PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_t *string, const char *filepath) { #ifdef _WIN32 // Open the file for reading. - HANDLE file = CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (file == INVALID_HANDLE_VALUE) { - return false; - } + pm_string_file_handle_t handle; + pm_string_init_result_t result = pm_string_file_handle_open(&handle, filepath); + if (result != PM_STRING_INIT_SUCCESS) return result; // Get the file size. - DWORD file_size = GetFileSize(file, NULL); + DWORD file_size = GetFileSize(handle.file, NULL); if (file_size == INVALID_FILE_SIZE) { - CloseHandle(file); - return false; + pm_string_file_handle_close(&handle); + return PM_STRING_INIT_ERROR_GENERIC; } // If the file is empty, then we don't need to do anything else, we'll set // the source to a constant empty string and return. if (file_size == 0) { - CloseHandle(file); + pm_string_file_handle_close(&handle); const uint8_t source[] = ""; *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 }; - return true; + return PM_STRING_INIT_SUCCESS; } // Create a mapping of the file. - HANDLE mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL); + HANDLE mapping = CreateFileMapping(handle.file, NULL, PAGE_READONLY, 0, 0, NULL); if (mapping == NULL) { - CloseHandle(file); - return false; + pm_string_file_handle_close(&handle); + return PM_STRING_INIT_ERROR_GENERIC; } // Map the file into memory. uint8_t *source = (uint8_t *) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); CloseHandle(mapping); - CloseHandle(file); + pm_string_file_handle_close(&handle); if (source == NULL) { - return false; + return PM_STRING_INIT_ERROR_GENERIC; } *string = (pm_string_t) { .type = PM_STRING_MAPPED, .source = source, .length = (size_t) file_size }; - return true; + return PM_STRING_INIT_SUCCESS; #elif defined(_POSIX_MAPPED_FILES) // Open the file for reading int fd = open(filepath, O_RDONLY); if (fd == -1) { - return false; + return PM_STRING_INIT_ERROR_GENERIC; } // Stat the file to get the file size struct stat sb; if (fstat(fd, &sb) == -1) { close(fd); - return false; + return PM_STRING_INIT_ERROR_GENERIC; + } + + // Ensure it is a file and not a directory + if (S_ISDIR(sb.st_mode)) { + close(fd); + return PM_STRING_INIT_ERROR_DIRECTORY; } // mmap the file descriptor to virtually get the contents @@ -124,22 +184,19 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) { close(fd); const uint8_t source[] = ""; *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 }; - return true; + return PM_STRING_INIT_SUCCESS; } source = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); if (source == MAP_FAILED) { - return false; + return PM_STRING_INIT_ERROR_GENERIC; } close(fd); *string = (pm_string_t) { .type = PM_STRING_MAPPED, .source = source, .length = size }; - return true; + return PM_STRING_INIT_SUCCESS; #else - (void) string; - (void) filepath; - perror("pm_string_mapped_init is not implemented for this platform"); - return false; + return pm_string_file_init(string, filepath); #endif } @@ -148,115 +205,108 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) { * contents and size into the given `pm_string_t`. The given `pm_string_t` * should be freed using `pm_string_free` when it is no longer used. */ -PRISM_EXPORTED_FUNCTION bool +PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_file_init(pm_string_t *string, const char *filepath) { #ifdef _WIN32 // Open the file for reading. - HANDLE file = CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (file == INVALID_HANDLE_VALUE) { - return false; - } + pm_string_file_handle_t handle; + pm_string_init_result_t result = pm_string_file_handle_open(&handle, filepath); + if (result != PM_STRING_INIT_SUCCESS) return result; // Get the file size. - DWORD file_size = GetFileSize(file, NULL); + DWORD file_size = GetFileSize(handle.file, NULL); if (file_size == INVALID_FILE_SIZE) { - CloseHandle(file); - return false; + pm_string_file_handle_close(&handle); + return PM_STRING_INIT_ERROR_GENERIC; } // If the file is empty, then we don't need to do anything else, we'll set // the source to a constant empty string and return. if (file_size == 0) { - CloseHandle(file); + pm_string_file_handle_close(&handle); const uint8_t source[] = ""; *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 }; - return true; + return PM_STRING_INIT_SUCCESS; } // Create a buffer to read the file into. uint8_t *source = xmalloc(file_size); if (source == NULL) { - CloseHandle(file); - return false; + pm_string_file_handle_close(&handle); + return PM_STRING_INIT_ERROR_GENERIC; } // Read the contents of the file DWORD bytes_read; - if (!ReadFile(file, source, file_size, &bytes_read, NULL)) { - CloseHandle(file); - return false; + if (!ReadFile(handle.file, source, file_size, &bytes_read, NULL)) { + pm_string_file_handle_close(&handle); + return PM_STRING_INIT_ERROR_GENERIC; } // Check the number of bytes read if (bytes_read != file_size) { xfree(source); - CloseHandle(file); - return false; + pm_string_file_handle_close(&handle); + return PM_STRING_INIT_ERROR_GENERIC; } - CloseHandle(file); + pm_string_file_handle_close(&handle); *string = (pm_string_t) { .type = PM_STRING_OWNED, .source = source, .length = (size_t) file_size }; - return true; -#elif defined(_POSIX_MAPPED_FILES) - FILE *file = fopen(filepath, "rb"); - if (file == NULL) { - return false; + return PM_STRING_INIT_SUCCESS; +#elif defined(PRISM_HAS_FILESYSTEM) + // Open the file for reading + int fd = open(filepath, O_RDONLY); + if (fd == -1) { + return PM_STRING_INIT_ERROR_GENERIC; } - fseek(file, 0, SEEK_END); - long file_size = ftell(file); + // Stat the file to get the file size + struct stat sb; + if (fstat(fd, &sb) == -1) { + close(fd); + return PM_STRING_INIT_ERROR_GENERIC; + } - if (file_size == -1) { - fclose(file); - return false; + // Ensure it is a file and not a directory + if (S_ISDIR(sb.st_mode)) { + close(fd); + return PM_STRING_INIT_ERROR_DIRECTORY; } - if (file_size == 0) { - fclose(file); + // Check the size to see if it's empty + size_t size = (size_t) sb.st_size; + if (size == 0) { + close(fd); const uint8_t source[] = ""; *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 }; - return true; + return PM_STRING_INIT_SUCCESS; } - size_t length = (size_t) file_size; + size_t length = (size_t) size; uint8_t *source = xmalloc(length); if (source == NULL) { - fclose(file); - return false; + close(fd); + return PM_STRING_INIT_ERROR_GENERIC; } - fseek(file, 0, SEEK_SET); - size_t bytes_read = fread(source, length, 1, file); - fclose(file); + long bytes_read = (long) read(fd, source, length); + close(fd); - if (bytes_read != 1) { + if (bytes_read == -1) { xfree(source); - return false; + return PM_STRING_INIT_ERROR_GENERIC; } *string = (pm_string_t) { .type = PM_STRING_OWNED, .source = source, .length = length }; - return true; + return PM_STRING_INIT_SUCCESS; #else (void) string; (void) filepath; perror("pm_string_file_init is not implemented for this platform"); - return false; + return PM_STRING_INIT_ERROR_GENERIC; #endif } -/** - * Returns the memory size associated with the string. - */ -size_t -pm_string_memsize(const pm_string_t *string) { - size_t size = sizeof(pm_string_t); - if (string->type == PM_STRING_OWNED) { - size += string->length; - } - return size; -} - /** * Ensure the string is owned. If it is not, then reinitialize it as owned and * copy over the previous source. diff --git a/src/util/pm_string_list.c b/src/util/pm_string_list.c deleted file mode 100644 index f6c2145987f..00000000000 --- a/src/util/pm_string_list.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "prism/util/pm_string_list.h" - -/** - * Append a pm_string_t to the given string list. - */ -void -pm_string_list_append(pm_string_list_t *string_list, pm_string_t *string) { - if (string_list->length + 1 > string_list->capacity) { - if (string_list->capacity == 0) { - string_list->capacity = 1; - } else { - string_list->capacity *= 2; - } - - string_list->strings = xrealloc(string_list->strings, string_list->capacity * sizeof(pm_string_t)); - if (string_list->strings == NULL) abort(); - } - - string_list->strings[string_list->length++] = *string; -} - -/** - * Free the memory associated with the string list - */ -void -pm_string_list_free(pm_string_list_t *string_list) { - xfree(string_list->strings); -} diff --git a/src/util/pm_strpbrk.c b/src/util/pm_strpbrk.c index 6c8dea18367..916a4cc3fd3 100644 --- a/src/util/pm_strpbrk.c +++ b/src/util/pm_strpbrk.c @@ -8,6 +8,27 @@ pm_strpbrk_invalid_multibyte_character(pm_parser_t *parser, const uint8_t *start pm_diagnostic_list_append_format(&parser->error_list, start, end, PM_ERR_INVALID_MULTIBYTE_CHARACTER, *start); } +/** + * Set the explicit encoding for the parser to the current encoding. + */ +static inline void +pm_strpbrk_explicit_encoding_set(pm_parser_t *parser, const uint8_t *source, size_t width) { + if (parser->explicit_encoding != NULL) { + if (parser->explicit_encoding == parser->encoding) { + // Okay, we already locked to this encoding. + } else if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { + // Not okay, we already found a Unicode escape sequence and this + // conflicts. + pm_diagnostic_list_append_format(&parser->error_list, source, source + width, PM_ERR_MIXED_ENCODING, parser->encoding->name); + } else { + // Should not be anything else. + assert(false && "unreachable"); + } + } + + parser->explicit_encoding = parser->encoding; +} + /** * This is the default path. */ @@ -52,7 +73,7 @@ pm_strpbrk_utf8(pm_parser_t *parser, const uint8_t *source, const uint8_t *chars * This is the path when the encoding is ASCII-8BIT. */ static inline const uint8_t * -pm_strpbrk_ascii_8bit(const uint8_t *source, const uint8_t *charset, size_t maximum) { +pm_strpbrk_ascii_8bit(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) { size_t index = 0; while (index < maximum) { @@ -60,6 +81,7 @@ pm_strpbrk_ascii_8bit(const uint8_t *source, const uint8_t *charset, size_t maxi return source + index; } + if (validate && source[index] >= 0x80) pm_strpbrk_explicit_encoding_set(parser, source, 1); index++; } @@ -72,6 +94,7 @@ pm_strpbrk_ascii_8bit(const uint8_t *source, const uint8_t *charset, size_t maxi static inline const uint8_t * pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) { size_t index = 0; + const pm_encoding_t *encoding = parser->encoding; while (index < maximum) { if (strchr((const char *) charset, source[index]) != NULL) { @@ -81,7 +104,8 @@ pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t if (source[index] < 0x80) { index++; } else { - size_t width = parser->encoding->char_width(source + index, (ptrdiff_t) (maximum - index)); + size_t width = encoding->char_width(source + index, (ptrdiff_t) (maximum - index)); + if (validate) pm_strpbrk_explicit_encoding_set(parser, source, width); if (width > 0) { index += width; @@ -96,7 +120,7 @@ pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t do { index++; - } while (index < maximum && parser->encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0); + } while (index < maximum && encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0); pm_strpbrk_invalid_multibyte_character(parser, source + start, source + index); } @@ -113,6 +137,7 @@ pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t static inline const uint8_t * pm_strpbrk_single_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) { size_t index = 0; + const pm_encoding_t *encoding = parser->encoding; while (index < maximum) { if (strchr((const char *) charset, source[index]) != NULL) { @@ -122,7 +147,8 @@ pm_strpbrk_single_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t if (source[index] < 0x80 || !validate) { index++; } else { - size_t width = parser->encoding->char_width(source + index, (ptrdiff_t) (maximum - index)); + size_t width = encoding->char_width(source + index, (ptrdiff_t) (maximum - index)); + pm_strpbrk_explicit_encoding_set(parser, source, width); if (width > 0) { index += width; @@ -135,7 +161,7 @@ pm_strpbrk_single_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t do { index++; - } while (index < maximum && parser->encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0); + } while (index < maximum && encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0); pm_strpbrk_invalid_multibyte_character(parser, source + start, source + index); } @@ -171,7 +197,7 @@ pm_strpbrk(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, p } else if (!parser->encoding_changed) { return pm_strpbrk_utf8(parser, source, charset, (size_t) length, validate); } else if (parser->encoding == PM_ENCODING_ASCII_8BIT_ENTRY) { - return pm_strpbrk_ascii_8bit(source, charset, (size_t) length); + return pm_strpbrk_ascii_8bit(parser, source, charset, (size_t) length, validate); } else if (parser->encoding->multibyte) { return pm_strpbrk_multi_byte(parser, source, charset, (size_t) length, validate); } else { diff --git a/suppressions/ruby-3.supp b/suppressions/ruby-3.supp new file mode 100644 index 00000000000..97eb8e4ca7f --- /dev/null +++ b/suppressions/ruby-3.supp @@ -0,0 +1,10 @@ +{ + Ripper not freeing strterm in all cases (https://bugs.ruby-lang.org/issues/20521) + Memcheck:Leak + ... + fun:new_strterm + fun:parse_percent + ... + fun:ripper_parse + ... +} diff --git a/templates/ext/prism/api_node.c.erb b/templates/ext/prism/api_node.c.erb index 0e3e4d63cc2..03615b0ae24 100644 --- a/templates/ext/prism/api_node.c.erb +++ b/templates/ext/prism/api_node.c.erb @@ -1,4 +1,4 @@ -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" #include "prism/extension.h" extern VALUE rb_cPrism; @@ -142,7 +142,7 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi switch (PM_NODE_TYPE(node)) { <%- nodes.each do |node| -%> <%- if node.fields.any? { |field| [Prism::Template::NodeField, Prism::Template::OptionalNodeField, Prism::Template::NodeListField].include?(field.class) } -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" case <%= node.type %>: { pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node; <%- node.fields.each do |field| -%> @@ -162,80 +162,83 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi default: break; } -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" } else { const pm_node_t *node = pm_node_stack_pop(&node_stack); switch (PM_NODE_TYPE(node)) { <%- nodes.each do |node| -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" case <%= node.type %>: { - <%- if node.fields.any? { |field| ![Prism::Template::NodeField, Prism::Template::OptionalNodeField, Prism::Template::FlagsField].include?(field.class) } -%> + <%- if node.fields.any? { |field| ![Prism::Template::NodeField, Prism::Template::OptionalNodeField].include?(field.class) } -%> pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node; <%- end -%> - VALUE argv[<%= node.fields.length + 2 %>]; + VALUE argv[<%= node.fields.length + 4 %>]; // source argv[0] = source; - <%- node.fields.each.with_index(1) do |field, index| -%> + + // node_id + argv[1] = ULONG2NUM(node->node_id); + + // location + argv[2] = pm_location_new(parser, node->location.start, node->location.end); + + // flags + argv[3] = ULONG2NUM(node->flags); + <%- node.fields.each.with_index(4) do |field, index| -%> // <%= field.name %> <%- case field -%> <%- when Prism::Template::NodeField, Prism::Template::OptionalNodeField -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" argv[<%= index %>] = rb_ary_pop(value_stack); <%- when Prism::Template::NodeListField -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" argv[<%= index %>] = rb_ary_new_capa(cast-><%= field.name %>.size); for (size_t index = 0; index < cast-><%= field.name %>.size; index++) { rb_ary_push(argv[<%= index %>], rb_ary_pop(value_stack)); } <%- when Prism::Template::StringField -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" argv[<%= index %>] = pm_string_new(&cast-><%= field.name %>, encoding); <%- when Prism::Template::ConstantField -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" assert(cast-><%= field.name %> != 0); argv[<%= index %>] = RARRAY_AREF(constants, cast-><%= field.name %> - 1); <%- when Prism::Template::OptionalConstantField -%> argv[<%= index %>] = cast-><%= field.name %> == 0 ? Qnil : RARRAY_AREF(constants, cast-><%= field.name %> - 1); <%- when Prism::Template::ConstantListField -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" argv[<%= index %>] = rb_ary_new_capa(cast-><%= field.name %>.size); for (size_t index = 0; index < cast-><%= field.name %>.size; index++) { assert(cast-><%= field.name %>.ids[index] != 0); rb_ary_push(argv[<%= index %>], RARRAY_AREF(constants, cast-><%= field.name %>.ids[index] - 1)); } <%- when Prism::Template::LocationField -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" argv[<%= index %>] = pm_location_new(parser, cast-><%= field.name %>.start, cast-><%= field.name %>.end); <%- when Prism::Template::OptionalLocationField -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" argv[<%= index %>] = cast-><%= field.name %>.start == NULL ? Qnil : pm_location_new(parser, cast-><%= field.name %>.start, cast-><%= field.name %>.end); <%- when Prism::Template::UInt8Field -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" argv[<%= index %>] = UINT2NUM(cast-><%= field.name %>); <%- when Prism::Template::UInt32Field -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" argv[<%= index %>] = ULONG2NUM(cast-><%= field.name %>); - <%- when Prism::Template::FlagsField -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" - argv[<%= index %>] = ULONG2NUM(node->flags & ~PM_NODE_FLAG_COMMON_MASK); <%- when Prism::Template::IntegerField -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" argv[<%= index %>] = pm_integer_new(&cast-><%= field.name %>); <%- when Prism::Template::DoubleField -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" argv[<%= index %>] = DBL2NUM(cast-><%= field.name %>); <%- else -%> <%- raise -%> <%- end -%> <%- end -%> - // location - argv[<%= node.fields.length + 1 %>] = pm_location_new(parser, node->location.start, node->location.end); - - rb_ary_push(value_stack, rb_class_new_instance(<%= node.fields.length + 2 %>, argv, rb_cPrism<%= node.name %>)); + rb_ary_push(value_stack, rb_class_new_instance(<%= node.fields.length + 4 %>, argv, rb_cPrism<%= node.name %>)); break; } <%- end -%> diff --git a/templates/include/prism/ast.h.erb b/templates/include/prism/ast.h.erb index 0fe7905e404..751c0b43c2c 100644 --- a/templates/include/prism/ast.h.erb +++ b/templates/include/prism/ast.h.erb @@ -100,11 +100,8 @@ typedef uint16_t pm_node_flags_t; * We store the flags enum in every node in the tree. Some flags are common to * all nodes (the ones listed below). Others are specific to certain node types. */ -#define PM_NODE_FLAG_BITS (sizeof(pm_node_flags_t) * 8) - -static const pm_node_flags_t PM_NODE_FLAG_NEWLINE = (1 << (PM_NODE_FLAG_BITS - 1)); -static const pm_node_flags_t PM_NODE_FLAG_STATIC_LITERAL = (1 << (PM_NODE_FLAG_BITS - 2)); -static const pm_node_flags_t PM_NODE_FLAG_COMMON_MASK = (1 << (PM_NODE_FLAG_BITS - 1)) | (1 << (PM_NODE_FLAG_BITS - 2)); +static const pm_node_flags_t PM_NODE_FLAG_NEWLINE = 0x1; +static const pm_node_flags_t PM_NODE_FLAG_STATIC_LITERAL = 0x2; /** * Cast the type to an enum to allow the compiler to provide exhaustiveness @@ -139,6 +136,12 @@ typedef struct pm_node { */ pm_node_flags_t flags; + /** + * The unique identifier for this node, which is deterministic based on the + * source. It is used to identify unique nodes across parses. + */ + uint32_t node_id; + /** * This is the location of the node in the source. It's a range of bytes * containing a start and an end. @@ -150,12 +153,15 @@ typedef struct pm_node { /** * <%= node.name %> * - * Type: <%= node.type %> -<%- if (node_flags = node.fields.find { |field| field.is_a? Prism::Template::FlagsField }) -%> - * Flags: -<%- found = flags.find { |flag| flag.name == node_flags.kind }.tap { |found| raise "Expected to find #{field.kind}" unless found } -%> -<%- found.values.each do |value| -%> - * PM_<%= found.human.upcase %>_<%= value.name %> +<%- node.each_comment_line do |line| -%> + *<%= line %> +<%- end -%> + * + * Type: ::<%= node.type %> +<% if (node_flags = node.flags) %> + * Flags (#pm_<%= node_flags.human %>): +<%- node_flags.values.each do |value| -%> + * * ::PM_<%= node_flags.human.upcase %>_<%= value.name %> <%- end -%> <%- end -%> * @@ -164,7 +170,8 @@ typedef struct pm_node { typedef struct pm_<%= node.human %> { /** The embedded base node. */ pm_node_t base; -<%- node.fields.grep_v(Prism::Template::FlagsField).each do |field| -%> + +<%- node.fields.each do |field| -%> /** * <%= node.name %>#<%= field.name %> @@ -201,7 +208,7 @@ typedef enum pm_<%= flag.human %> { <%- flag.values.each_with_index do |value, index| -%> <%= "\n" if index > 0 -%> /** <%= value.comment %> */ - PM_<%= flag.human.upcase %>_<%= value.name %> = <%= 1 << index %>, + PM_<%= flag.human.upcase %>_<%= value.name %> = <%= 1 << (index + Prism::Template::COMMON_FLAGS_COUNT) %>, <%- end -%> } pm_<%= flag.human %>_t; <%- end -%> @@ -212,6 +219,6 @@ typedef enum pm_<%= flag.human %> { * to specify that through the environment. It will never be true except for in * those build systems. */ -#define PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS <%= Prism::Template::SERIALIZE_ONLY_SEMANTICS_FIELDS %> +#define PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS <%= Prism::Template::SERIALIZE_ONLY_SEMANTICS_FIELDS ? 1 : 0 %> #endif diff --git a/templates/java/org/prism/Loader.java.erb b/templates/java/org/prism/Loader.java.erb index 18265e57df1..032cf017c2b 100644 --- a/templates/java/org/prism/Loader.java.erb +++ b/templates/java/org/prism/Loader.java.erb @@ -100,8 +100,8 @@ public class Loader { expect((byte) 'S', "incorrect prism header"); expect((byte) 'M', "incorrect prism header"); - expect((byte) 0, "prism major version does not match"); - expect((byte) 28, "prism minor version does not match"); + expect((byte) 1, "prism major version does not match"); + expect((byte) 2, "prism minor version does not match"); expect((byte) 0, "prism patch version does not match"); expect((byte) 1, "Loader.java requires no location fields in the serialized output"); @@ -127,16 +127,21 @@ public class Loader { int constantPoolLength = loadVarUInt(); this.constantPool = new ConstantPool(this, source.bytes, constantPoolBufferOffset, constantPoolLength); - Nodes.Node node = loadNode(); + Nodes.Node node; + if (errors.length == 0) { + node = loadNode(); - int left = constantPoolBufferOffset - buffer.position(); - if (left != 0) { - throw new Error("Expected to consume all bytes while deserializing but there were " + left + " bytes left"); - } + int left = constantPoolBufferOffset - buffer.position(); + if (left != 0) { + throw new Error("Expected to consume all bytes while deserializing but there were " + left + " bytes left"); + } - boolean[] newlineMarked = new boolean[1 + source.getLineCount()]; - MarkNewlinesVisitor visitor = new MarkNewlinesVisitor(source, newlineMarked); - node.accept(visitor); + boolean[] newlineMarked = new boolean[1 + source.getLineCount()]; + MarkNewlinesVisitor visitor = new MarkNewlinesVisitor(source, newlineMarked); + node.accept(visitor); + } else { + node = null; + } return new ParseResult(node, magicComments, dataLocation, errors, warnings, source); } @@ -361,7 +366,9 @@ public class Loader { <%- nodes.each_with_index do |node, index| -%> case <%= index + 1 %>: <%- - params = node.needs_serialized_length? ? ["buffer.getInt()"] : [] + params = ["startOffset", "length"] + params << "buffer.getInt()" if node.needs_serialized_length? + params << "loadFlags()" if node.flags params.concat node.semantic_fields.map { |field| case field when Prism::Template::NodeField then "#{field.java_cast}loadNode()" @@ -378,13 +385,11 @@ public class Loader { when Prism::Template::OptionalLocationField then "loadOptionalLocation()" when Prism::Template::UInt8Field then "buffer.get()" when Prism::Template::UInt32Field then "loadVarUInt()" - when Prism::Template::FlagsField then "loadFlags()" when Prism::Template::IntegerField then "loadInteger()" when Prism::Template::DoubleField then "buffer.getDouble()" else raise end } - params.concat ["startOffset", "length"] -%> return new Nodes.<%= node.name %>(<%= params.join(", ") -%>); <%- end -%> diff --git a/templates/java/org/prism/Nodes.java.erb b/templates/java/org/prism/Nodes.java.erb index 48fbd66daca..2b956b95875 100644 --- a/templates/java/org/prism/Nodes.java.erb +++ b/templates/java/org/prism/Nodes.java.erb @@ -135,19 +135,19 @@ public abstract class Nodes { protected abstract String toString(String indent); } <%# FLAGS -%> - <%- flags.each do |group| -%> + <%- flags.each do |flag| -%> /** - * <%= Prism::Template::JavaDoc.escape(group.comment) %> + * <%= Prism::Template::JavaDoc.escape(flag.comment) %> */ - public static final class <%= group.name %> implements Comparable<<%= group.name %>> { - <%- group.values.each_with_index do |value, index| -%> + public static final class <%= flag.name %> implements Comparable<<%= flag.name %>> { + <%- flag.values.each_with_index do |value, index| -%> // <%= value.comment %> - public static final short <%= value.name %> = 1 << <%= index %>; + public static final short <%= value.name %> = 1 << <%= index + Prism::Template::COMMON_FLAGS_COUNT %>; <%- end -%> - <%- group.values.each do |value| -%> + <%- flag.values.each do |value| -%> public static boolean is<%= value.camelcase %>(short flags) { return (flags & <%= value.name %>) != 0; } @@ -155,7 +155,7 @@ public abstract class Nodes { <%- end -%> private final short flags; - public <%= group.name %>(short flags) { + public <%= flag.name %>(short flags) { this.flags = flags; } @@ -166,19 +166,19 @@ public abstract class Nodes { @Override public boolean equals(Object other) { - if (!(other instanceof <%= group.name %>)) { + if (!(other instanceof <%= flag.name %>)) { return false; } - return flags == ((<%= group.name %>) other).flags; + return flags == ((<%= flag.name %>) other).flags; } @Override - public int compareTo(<%= group.name %> other) { + public int compareTo(<%= flag.name %> other) { return flags - other.flags; } - <%- group.values.each do |value| -%> + <%- flag.values.each do |value| -%> public boolean is<%= value.camelcase %>() { return (flags & <%= value.name %>) != 0; } @@ -200,6 +200,9 @@ public abstract class Nodes { <%- if node.needs_serialized_length? -%> public final int serializedLength; <%- end -%> + <%- if node.flags -%> + public final short flags; + <%- end -%> <%- node.semantic_fields.each do |field| -%> <%- if field.comment -%> /** @@ -210,35 +213,39 @@ public abstract class Nodes { * */ <%- end -%> - <%- if field.class.name.include?('Optional') -%> + <%- if field.class.name.include?("Optional") -%> @Nullable <%- end -%> <%- if field.respond_to?(:union_kind) && field.union_kind -%> - @UnionType({ <%= field.union_kind.map { |t| "#{t}.class" }.join(', ') %> }) + @UnionType({ <%= field.union_kind.map { |t| "#{t}.class" }.join(", ") %> }) <%- end -%> public final <%= field.java_type %> <%= field.name %>; <%- end -%> <%- - params = node.needs_serialized_length? ? ["int serializedLength"] : [] - params.concat node.semantic_fields.map { |field| "#{field.java_type} #{field.name}" } - params.concat ["int startOffset", "int length"] + params = ["int startOffset", "int length"] + params << "int serializedLength" if node.needs_serialized_length? + params << "short flags" if node.flags + params.concat(node.semantic_fields.map { |field| "#{field.java_type} #{field.name}" }) -%> - public <%=node.name -%>(<%= params.join(", ") %>) { + public <%= node.name -%>(<%= params.join(", ") %>) { super(startOffset, length); <%- if node.needs_serialized_length? -%> this.serializedLength = serializedLength; <%- end -%> + <%- if node.flags -%> + this.flags = flags; + <%- end -%> <%- node.semantic_fields.each do |field| -%> this.<%= field.name %> = <%= field.name %>; <%- end -%> } <%# methods for flags -%> - <%- node.semantic_fields.grep(Prism::Template::FlagsField).each do |field| -%> - <%- flags.find { |flag| flag.name == field.kind }.tap { |flag| raise "Expected to find #{field.kind}" unless flag }.values.each do |value| -%> + <%- if (node_flags = node.flags) -%> + <%- node_flags.values.each do |value| -%> public boolean is<%= value.camelcase %>() { - return <%= field.kind %>.is<%= value.camelcase %>(this.<%= field.name %>); + return <%= node_flags.name %>.is<%= value.camelcase %>(flags); } <%- end -%> <%- end -%> @@ -321,7 +328,7 @@ public abstract class Nodes { <%- if node.fields.any?(Prism::Template::NodeListField) or node.fields.any?(Prism::Template::ConstantListField) -%> String nextNextIndent = nextIndent + " "; <%- end -%> - <%- node.fields.grep_v(Prism::Template::LocationField).grep_v(Prism::Template::OptionalLocationField).each do |field| -%> + <%- [*node.flags, *node.fields.grep_v(Prism::Template::LocationField).grep_v(Prism::Template::OptionalLocationField)].each do |field| -%> builder.append(nextIndent); builder.append("<%= field.name %>: "); <%- case field -%> @@ -348,7 +355,10 @@ public abstract class Nodes { for (<%= string_type %> constant : this.<%= field.name %>) { builder.append(nextNextIndent).append('"').append(constant).append('"').append('\n'); } - <%- when Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::FlagsField, Prism::Template::IntegerField, Prism::Template::DoubleField -%> + <%- when Prism::Template::Flags -%> + builder.append(flags); + builder.append('\n'); + <%- when Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::IntegerField, Prism::Template::DoubleField -%> builder.append(this.<%= field.name %>); builder.append('\n'); <%- else -%> diff --git a/templates/javascript/src/deserialize.js.erb b/templates/javascript/src/deserialize.js.erb index 12cac1badd6..36f5c8fc7c7 100644 --- a/templates/javascript/src/deserialize.js.erb +++ b/templates/javascript/src/deserialize.js.erb @@ -1,7 +1,7 @@ import * as nodes from "./nodes.js"; -const MAJOR_VERSION = 0; -const MINOR_VERSION = 28; +const MAJOR_VERSION = 1; +const MINOR_VERSION = 2; const PATCH_VERSION = 0; // The DataView getFloat64 function takes an optional second argument that @@ -22,10 +22,19 @@ const LITTLE_ENDIAN = (() => { })(); class SerializationBuffer { + FORCED_UTF8_ENCODING_FLAG = 1 << 2; + FORCED_BINARY_ENCODING_FLAG = 1 << 3; + + DECODER_MAP = new Map([ + ["ascii-8bit", "ascii"] + ]); + constructor(source, array) { this.source = source; this.array = array; this.index = 0; + this.fileEncoding = "utf-8"; + this.decoders = new Map(); } readByte() { @@ -40,8 +49,8 @@ class SerializationBuffer { return result; } - readString(length) { - return new TextDecoder().decode(this.readBytes(length)); + readString(length, flags) { + return this.decodeString(this.readBytes(length), flags).value; } // Read a 32-bit unsigned integer in little-endian format. @@ -85,17 +94,18 @@ class SerializationBuffer { } } - readStringField() { + readStringField(flags) { + if (flags === undefined) flags = 0; const type = this.readByte(); switch (type) { case 1: { const startOffset = this.readVarInt(); const length = this.readVarInt(); - return new TextDecoder().decode(this.source.slice(startOffset, startOffset + length)); + return this.decodeString(this.source.slice(startOffset, startOffset + length), flags); } case 2: - return this.readString(this.readVarInt()); + return this.decodeString(this.readBytes(this.readVarInt()), flags); default: throw new Error(`Unknown serialized string type: ${type}`); } @@ -122,6 +132,61 @@ class SerializationBuffer { return view.getFloat64(0, LITTLE_ENDIAN); } + + decodeString(bytes, flags) { + const forcedBin = (flags & this.FORCED_BINARY_ENCODING_FLAG) !== 0; + const forcedUtf8 = (flags & this.FORCED_UTF8_ENCODING_FLAG) !== 0; + + if (forcedBin) { + // just use raw bytes + return { + encoding: "ascii", + validEncoding: true, + value: this.asciiDecoder.decode(bytes) + }; + } else { + const encoding = forcedUtf8 ? "utf-8" : this.fileEncoding.toLowerCase(); + const decoder = this.getDecoder(encoding); + + try { + // decode with encoding + return { + encoding, + validEncoding: true, + value: decoder.decode(bytes) + }; + } catch(e) { + // just use raw bytes, capture what the encoding should be, set flag saying encoding is invalid + if (e.code === "ERR_ENCODING_INVALID_ENCODED_DATA") { + return { + encoding, + validEncoding: false, + value: this.asciiDecoder.decode(bytes) + }; + } + + throw e; + } + } + } + + getDecoder(encoding) { + encoding = this.DECODER_MAP.get(encoding) || encoding; + + if (!this.decoders.has(encoding)) { + this.decoders.set(encoding, new TextDecoder(encoding, {fatal: true})); + } + + return this.decoders.get(encoding); + } + + get asciiDecoder() { + if (!this._asciiDecoder) { + this._asciiDecoder = new TextDecoder("ascii"); + } + + return this._asciiDecoder; + } } /** @@ -248,8 +313,8 @@ export function deserialize(source, array) { throw new Error("Invalid serialization (location fields must be included but are not)"); } - // Skip past the encoding, it means nothing to us in JavaScript. - buffer.readString(buffer.readVarInt()); + // Read the file's encoding. + buffer.fileEncoding = buffer.readString(buffer.readVarInt()); // Skip past the start line, as we don't support that option yet in // JavaScript. @@ -295,7 +360,9 @@ export function deserialize(source, array) { function readRequiredNode() { const type = buffer.readByte(); + const nodeID = buffer.readVarInt(); const location = buffer.readLocation(); + let flags; switch (type) { <%- nodes.each.with_index(1) do |node, index| -%> @@ -303,11 +370,11 @@ export function deserialize(source, array) { <%- if node.needs_serialized_length? -%> buffer.readUint32(); <%- end -%> - return new nodes.<%= node.name %>(<%= (node.fields.map { |field| + return new nodes.<%= node.name %>(<%= ["nodeID", "location", "flags = buffer.readVarInt()", *node.fields.map { |field| case field when Prism::Template::NodeField then "readRequiredNode()" when Prism::Template::OptionalNodeField then "readOptionalNode()" - when Prism::Template::StringField then "buffer.readStringField()" + when Prism::Template::StringField then "buffer.readStringField(flags)" when Prism::Template::NodeListField then "Array.from({ length: buffer.readVarInt() }, readRequiredNode)" when Prism::Template::ConstantField then "readRequiredConstant()" when Prism::Template::OptionalConstantField then "readOptionalConstant()" @@ -315,12 +382,11 @@ export function deserialize(source, array) { when Prism::Template::LocationField then "buffer.readLocation()" when Prism::Template::OptionalLocationField then "buffer.readOptionalLocation()" when Prism::Template::UInt8Field then "buffer.readByte()" - when Prism::Template::UInt32Field, Prism::Template::FlagsField then "buffer.readVarInt()" + when Prism::Template::UInt32Field then "buffer.readVarInt()" when Prism::Template::IntegerField then "readInteger()" when Prism::Template::DoubleField then "buffer.readDouble()" - else raise end - } + ["location"]).join(", ") -%>); + }].join(", ") -%>); <%- end -%> default: throw new Error(`Unknown node type: ${type}`); diff --git a/templates/javascript/src/nodes.js.erb b/templates/javascript/src/nodes.js.erb index 6a535285b38..90c3a6e5e69 100644 --- a/templates/javascript/src/nodes.js.erb +++ b/templates/javascript/src/nodes.js.erb @@ -13,13 +13,13 @@ def jstype(field) when Prism::Template::NodeField then field.ruby_type when Prism::Template::OptionalNodeField then "#{field.ruby_type} | null" when Prism::Template::NodeListField then "Node[]" - when Prism::Template::StringField then "string" + when Prism::Template::StringField then "RubyString" when Prism::Template::ConstantField then "string" when Prism::Template::OptionalConstantField then "string | null" when Prism::Template::ConstantListField then "string[]" when Prism::Template::LocationField then "Location" when Prism::Template::OptionalLocationField then "Location | null" - when Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::FlagsField, Prism::Template::IntegerField, Prism::Template::DoubleField then "number" + when Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::IntegerField, Prism::Template::DoubleField then "number" else raise end end @@ -33,7 +33,7 @@ import * as visitors from "./visitor.js" */ const <%= flag.name %> = { <%- flag.values.each_with_index do |value, index| -%> - <%= value.name %>: 1 << <%= index %>, + <%= value.name %>: 1 << <%= index + Prism::Template::COMMON_FLAGS_COUNT %>, <%- end -%> }; <%- end -%> @@ -44,6 +44,12 @@ const <%= flag.name %> = { * @typedef {{ startOffset: number, length: number }} Location */ +/** + * An encoded Ruby string. + * + * @typedef {{ value: string, encoding: string, validEncoding: boolean }} RubyString + */ + /** * A generic node in the tree. * @@ -57,39 +63,48 @@ const <%= flag.name %> = { <%- end -%> */ export class <%= node.name -%> { - <%- node.fields.each do |field| -%> /** - * @type <%= jstype(field) %> + * @type {Integer} */ - <%= field.is_a?(Prism::Template::FlagsField) ? "#flags" : prop(field) %>; + nodeID; - <%- end -%> /** * @type {Location} */ location; + /** + * @type number + */ + #flags; + + <%- node.fields.each do |field| -%> + /** + * @type <%= jstype(field) %> + */ + <%= prop(field) %>; + + <%- end -%> /** * Construct a new <%= node.name %>. * + * @param {number} nodeID + * @param {Location} location + * @param {number} flags <%- node.fields.each do |field| -%> * @param {<%= jstype(field) %>} <%= prop(field) %> <%- end -%> - * @param {Location} location */ - constructor(<%= (node.fields.map { |field| prop(field) } + ["location"]).join(", ") %>) { - <%- node.fields.each do |field| -%> - <%- if field.is_a?(Prism::Template::FlagsField) -%> + constructor(<%= ["nodeID", "location", "flags", *node.fields.map { |field| prop(field) }].join(", ") %>) { + this.nodeID = nodeID; + this.location = location; this.#flags = flags; - <%- else -%> + <%- node.fields.each do |field| -%> this.<%= prop(field) %> = <%= prop(field) %>; <%- end -%> - <%- end -%> - this.location = location; } - <%- if (flags_field = node.fields.find { |field| field.is_a?(Prism::Template::FlagsField) }) -%> - <%- flag = flags.find { |flag| flag.name == flags_field.kind }.tap { |flag| raise "Expected to find #{field.kind}" unless flag } -%> - <%- flag.values.each do |value| -%> + <%- if (node_flags = node.flags) -%> + <%- node_flags.values.each do |value| -%> /** * True if this node has the <%= value.name %> flag. @@ -97,7 +112,7 @@ export class <%= node.name -%> { * @returns {boolean} */ is<%= value.camelcase %>() { - return (this.#flags & <%= flag.name %>.<%= value.name %>) !== 0; + return (this.#flags & <%= node_flags.name %>.<%= value.name %>) !== 0; } <%- end -%> <%- end -%> @@ -167,16 +182,15 @@ export class <%= node.name -%> { toJSON() { return { type: "<%= node.name %>", - <%- node.fields.each do |field| -%> - <%- if field.is_a?(Prism::Template::FlagsField) -%> + location: this.location, flags: this.#flags, - <%- elsif field.name == "arguments" -%> + <%- node.fields.each do |field| -%> + <%- if field.name == "arguments" -%> arguments: this.<%= prop(field) %>, <%- else -%> <%= prop(field) %>: this.<%= prop(field) %>, <%- end -%> <%- end -%> - location: this.location }; } } diff --git a/templates/lib/prism/dispatcher.rb.erb b/templates/lib/prism/dispatcher.rb.erb index 1370ca76364..0db00034642 100644 --- a/templates/lib/prism/dispatcher.rb.erb +++ b/templates/lib/prism/dispatcher.rb.erb @@ -14,7 +14,8 @@ module Prism # end # end # - # dispatcher = Dispatcher.new + # listener = OctalListener.new + # dispatcher = Prism::Dispatcher.new # dispatcher.register(listener, :on_integer_node_enter) # # Then, you can walk any number of trees and dispatch events to the listeners: diff --git a/templates/lib/prism/dot_visitor.rb.erb b/templates/lib/prism/dot_visitor.rb.erb index 93c94b19eed..e9c81e45450 100644 --- a/templates/lib/prism/dot_visitor.rb.erb +++ b/templates/lib/prism/dot_visitor.rb.erb @@ -109,6 +109,11 @@ module Prism def visit_<%= node.human %>(node) table = Table.new("<%= node.name %>") id = node_id(node) + <%- if (node_flags = node.flags) -%> + + # flags + table.field("flags", <%= node_flags.human %>_inspect(node)) + <%- end -%> <%- node.fields.each do |field| -%> # <%= field.name %> @@ -141,9 +146,6 @@ module Prism unless (<%= field.name %> = node.<%= field.name %>).nil? table.field("<%= field.name %>", location_inspect(<%= field.name %>)) end - <%- when Prism::Template::FlagsField -%> - <%- flag = flags.find { |flag| flag.name == field.kind }.tap { |flag| raise "Expected to find #{field.kind}" unless flag } -%> - table.field("<%= field.name %>", <%= flag.human %>_inspect(node)) <%- else -%> <%- raise -%> <%- end -%> diff --git a/templates/lib/prism/dsl.rb.erb b/templates/lib/prism/dsl.rb.erb index eff0d1c4fcf..e16ebb71101 100644 --- a/templates/lib/prism/dsl.rb.erb +++ b/templates/lib/prism/dsl.rb.erb @@ -5,45 +5,129 @@ module Prism # source = Prism::Source.for("[1]") # # Prism::ArrayNode.new( + # source, + # 0, + # Prism::Location.new(source, 0, 3), + # 0, # [ # Prism::IntegerNode.new( - # Prism::IntegerBaseFlags::DECIMAL, - # 1, + # source, + # 0, # Prism::Location.new(source, 1, 1), - # source + # Prism::IntegerBaseFlags::DECIMAL, + # 1 # ) # ], # Prism::Location.new(source, 0, 1), - # Prism::Location.new(source, 2, 1), - # source + # Prism::Location.new(source, 2, 1) # ) # # you could instead write: # - # source = Prism::Source.for("[1]") + # class Builder + # include Prism::DSL # - # ArrayNode( - # IntegerNode(Prism::IntegerBaseFlags::DECIMAL, 1, Location(source, 1, 1)), source), - # Location(source, 0, 1), - # Location(source, 2, 1), - # source - # ) + # attr_reader :default_source + # + # def initialize + # @default_source = source("[1]") + # end # - # This is mostly helpful in the context of writing tests, but can also be used - # to generate trees programmatically. + # def build + # array_node( + # location: location(start_offset: 0, length: 3), + # elements: [ + # integer_node( + # location: location(start_offset: 1, length: 1), + # flags: integer_base_flag(:decimal), + # value: 1 + # ) + # ], + # opening_loc: location(start_offset: 0, length: 1), + # closing_loc: location(start_offset: 2, length: 1) + # ) + # end + # end + # + # This is mostly helpful in the context of generating trees programmatically. module DSL - private + # Provide all of these methods as module methods as well, to allow for + # building nodes like Prism::DSL.nil_node. + extend self - # Create a new Location object - def Location(source = nil, start_offset = 0, length = 0) - Location.new(source, start_offset, length) # steep:ignore + # Create a new Source object. + def source(string) + Source.for(string) + end + + # Create a new Location object. + def location(source: default_source, start_offset: 0, length: 0) + Location.new(source, start_offset, length) end <%- nodes.each do |node| -%> - # Create a new <%= node.name %> node - def <%= node.name %>(<%= (node.fields.map(&:name) + ["source = nil, location = Location()"]).join(", ") %>) - <%= node.name %>.new(<%= ["source", *node.fields.map(&:name), "location"].join(", ") %>) + # Create a new <%= node.name %> node. + def <%= node.human %>(<%= ["source: default_source", "node_id: 0", "location: default_location", "flags: 0", *node.fields.map { |field| + case field + when Prism::Template::NodeField + kind = field.specific_kind || field.union_kind&.first + if kind.nil? + "#{field.name}: default_node(source, location)" + else + "#{field.name}: #{kind.gsub(/(?<=.)[A-Z]/, "_\\0").downcase}(source: source)" + end + when Prism::Template::ConstantField + "#{field.name}: :\"\"" + when Prism::Template::OptionalNodeField, Prism::Template::OptionalConstantField, Prism::Template::OptionalLocationField + "#{field.name}: nil" + when Prism::Template::NodeListField, Prism::Template::ConstantListField + "#{field.name}: []" + when Prism::Template::StringField + "#{field.name}: \"\"" + when Prism::Template::LocationField + "#{field.name}: location" + when Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::IntegerField + "#{field.name}: 0" + when Prism::Template::DoubleField + "#{field.name}: 0.0" + else + raise + end + }].join(", ") %>) + <%= node.name %>.new(<%= ["source", "node_id", "location", "flags", *node.fields.map(&:name)].join(", ") %>) end <%- end -%> + <%- flags.each do |flag| -%> + + # Retrieve the value of one of the <%= flag.name %> flags. + def <%= flag.human.chomp("s") %>(name) + case name + <%- flag.values.each do |value| -%> + when :<%= value.name.downcase %> then <%= flag.name %>::<%= value.name %> + <%- end -%> + else Kernel.raise ArgumentError, "invalid <%= flag.name %> flag: #{name.inspect}" + end + end + <%- end -%> + + private + + # The default source object that gets attached to nodes and locations if no + # source is specified. + def default_source + Source.for("") + end + + # The default location object that gets attached to nodes if no location is + # specified, which uses the given source. + def default_location + Location.new(default_source, 0, 0) + end + + # The default node that gets attached to nodes if no node is specified for a + # required node field. + def default_node(source, location) + MissingNode.new(source, -1, location, 0) + end end end diff --git a/templates/lib/prism/inspect_visitor.rb.erb b/templates/lib/prism/inspect_visitor.rb.erb index 8e7902f0f1f..3cfe615d850 100644 --- a/templates/lib/prism/inspect_visitor.rb.erb +++ b/templates/lib/prism/inspect_visitor.rb.erb @@ -69,10 +69,13 @@ module Prism # Inspect a <%= node.name %> node. def visit_<%= node.human %>(node) commands << [inspect_node(<%= node.name.inspect %>, node), indent] - <%- node.fields.each_with_index do |field, index| -%> - <%- pointer = index == node.fields.length - 1 ? "└── " : "├── " -%> - <%- preadd = index == node.fields.length - 1 ? " " : "│ " -%> + <%- (fields = [node.flags || Prism::Template::Flags.empty, *node.fields]).each_with_index do |field, index| -%> + <%- pointer = index == fields.length - 1 ? "└── " : "├── " -%> + <%- preadd = index == fields.length - 1 ? " " : "│ " -%> <%- case field -%> + <%- when Prism::Template::Flags -%> + flags = [("newline" if node.newline?), ("static_literal" if node.static_literal?), <%= field.values.map { |value| "(\"#{value.name.downcase}\" if node.#{value.name.downcase}?)" }.join(", ") %>].compact + commands << ["<%= pointer %>flags: #{flags.empty? ? "∅" : flags.join(", ")}\n", indent] <%- when Prism::Template::NodeListField -%> commands << ["<%= pointer %><%= field.name %>: (length: #{(<%= field.name %> = node.<%= field.name %>).length})\n", indent] if <%= field.name %>.any? @@ -101,10 +104,6 @@ module Prism else commands << ["<%= pointer %><%= field.name %>: #{<%= field.name %>.inspect}\n", indent] end - <%- when Prism::Template::FlagsField -%> - <%- flag = flags.find { |flag| flag.name == field.kind }.tap { |flag| raise unless flag } -%> - flags = [<%= flag.values.map { |value| "(\"#{value.name.downcase}\" if node.#{value.name.downcase}?)" }.join(", ") %>].compact - commands << ["<%= pointer %><%= field.name %>: #{flags.empty? ? "∅" : flags.join(", ")}\n", indent] <%- when Prism::Template::LocationField, Prism::Template::OptionalLocationField -%> commands << ["<%= pointer %><%= field.name %>: #{inspect_location(node.<%= field.name %>)}\n", indent] <%- end -%> @@ -116,13 +115,8 @@ module Prism # Compose a header for the given node. def inspect_node(name, node) - result = +"@ #{name} (" - location = node.location - result << "location: (#{location.start_line},#{location.start_column})-(#{location.end_line},#{location.end_column})" - result << ", newline: true" if node.newline? - - result << ")\n" + "@ #{name} (location: (#{location.start_line},#{location.start_column})-(#{location.end_line},#{location.end_column}))\n" end # Compose a string representing the given inner location field. diff --git a/templates/lib/prism/node.rb.erb b/templates/lib/prism/node.rb.erb index 50e622a8d12..f033cdea9b1 100644 --- a/templates/lib/prism/node.rb.erb +++ b/templates/lib/prism/node.rb.erb @@ -6,6 +6,12 @@ module Prism attr_reader :source private :source + # A unique identifier for this node. This is used in a very specific + # use case where you want to keep around a reference to a node without + # having to keep around the syntax tree in memory. This unique identifier + # will be consistent across multiple parses of the same source code. + attr_reader :node_id + # A Location instance that represents the location of this node in the # source. def location @@ -28,18 +34,6 @@ module Prism location.is_a?(Location) ? location.end_offset : ((location >> 32) + (location & 0xFFFFFFFF)) end - def newline? # :nodoc: - @newline ? true : false - end - - def set_newline_flag(newline_marked) # :nodoc: - line = location.start_line - unless newline_marked[line] - newline_marked[line] = true - @newline = true - end - end - # Returns all of the lines of the source code associated with this node. def source_lines location.source_lines @@ -61,6 +55,21 @@ module Prism location.slice_lines end + # An bitset of flags for this node. There are certain flags that are common + # for all nodes, and then some nodes have specific flags. + attr_reader :flags + protected :flags + + # Returns true if the node has the newline flag set. + def newline? + flags.anybits?(NodeFlags::NEWLINE) + end + + # Returns true if the node has the static literal flag set. + def static_literal? + flags.anybits?(NodeFlags::STATIC_LITERAL) + end + # Similar to inspect, but respects the current level of indentation given by # the pretty print object. def pretty_print(q) @@ -113,6 +122,23 @@ module Prism result end + # Returns the first node that matches the given block when visited in a + # depth-first search. This is useful for finding a node that matches a + # particular condition. + # + # node.breadth_first_search { |node| node.node_id == node_id } + # + def breadth_first_search(&block) + queue = [self] #: Array[Prism::node] + + while (node = queue.shift) + return node if yield node + queue.concat(node.compact_child_nodes) + end + + nil + end + # Returns a list of the fields that exist for this node class. Fields # describe the structure of the node. This kind of reflection is useful for # things like recursively visiting each node _and_ field in the tree. @@ -156,18 +182,31 @@ module Prism raise NoMethodError, "undefined method `comment_targets' for #{inspect}" end - # Returns a symbol symbolizing the type of node that this represents. This - # is particularly useful for case statements and array comparisons. - def type - raise NoMethodError, "undefined method `type' for #{inspect}" - end - # Returns a string representation of the node. def inspect raise NoMethodError, "undefined method `inspect' for #{inspect}" end - # Returns the type of the node as a symbol. + # Sometimes you want to check an instance of a node against a list of + # classes to see what kind of behavior to perform. Usually this is done by + # calling `[cls1, cls2].include?(node.class)` or putting the node into a + # case statement and doing `case node; when cls1; when cls2; end`. Both of + # these approaches are relatively slow because of the constant lookups, + # method calls, and/or array allocations. + # + # Instead, you can call #type, which will return to you a symbol that you + # can use for comparison. This is faster than the other approaches because + # it uses a single integer comparison, but also because if you're on CRuby + # you can take advantage of the fact that case statements with all symbol + # keys will use a jump table. + def type + raise NoMethodError, "undefined method `type' for #{inspect}" + end + + # Similar to #type, this method returns a symbol that you can use for + # splitting on the type of the node without having to do a long === chain. + # Note that like #type, it will still be slower than using == for a single + # class, but should be faster in a case statement or an array comparison. def self.type raise NoMethodError, "undefined method `type' for #{inspect}" end @@ -178,14 +217,15 @@ module Prism #<%= line %> <%- end -%> class <%= node.name -%> < Node - # def initialize: (<%= (node.fields.map { |field| "#{field.rbs_class} #{field.name}" } + ["Location location"]).join(", ") %>) -> void - def initialize(source, <%= (node.fields.map(&:name) + ["location"]).join(", ") %>) + # Initialize a new <%= node.name %> node. + def initialize(<%= ["source", "node_id", "location", "flags", *node.fields.map(&:name)].join(", ") %>) @source = source - @newline = false + @node_id = node_id @location = location + @flags = flags <%- node.fields.each do |field| -%> <%- if Prism::Template::CHECK_FIELD_KIND && field.respond_to?(:check_field_kind) -%> - raise <%= field.name %>.inspect unless <%= field.check_field_kind %> + raise "<%= node.name %>#<%= field.name %> was of unexpected type:\n#{<%= field.name %>.inspect}" unless <%= field.check_field_kind %> <%- end -%> @<%= field.name %> = <%= field.name %> <%- end -%> @@ -195,25 +235,6 @@ module Prism def accept(visitor) visitor.visit_<%= node.human %>(self) end - <%- if node.newline == false -%> - - def set_newline_flag(newline_marked) # :nodoc: - # Never mark <%= node.name %> with a newline flag, mark children instead - end - <%- elsif node.newline.is_a?(String) -%> - - def set_newline_flag(newline_marked) # :nodoc: - <%- field = node.fields.find { |f| f.name == node.newline } or raise node.newline -%> - <%- case field -%> - <%- when Prism::Template::NodeField -%> - <%= field.name %>.set_newline_flag(newline_marked) - <%- when Prism::Template::NodeListField -%> - first = <%= field.name %>.first - first.set_newline_flag(newline_marked) if first - <%- else raise field.class.name -%> - <%- end -%> - end - <%- end -%> # def child_nodes: () -> Array[nil | Node] def child_nodes @@ -260,22 +281,31 @@ module Prism }.compact.join(", ") %>] #: Array[Prism::node | Location] end - # def copy: (<%= (node.fields.map { |field| "?#{field.name}: #{field.rbs_class}" } + ["?location: Location"]).join(", ") %>) -> <%= node.name %> - def copy(<%= (node.fields.map(&:name) + ["location"]).map { |field| "#{field}: self.#{field}" }.join(", ") %>) - <%= node.name %>.new(<%= ["source", *node.fields.map(&:name), "location"].join(", ") %>) + # def copy: (<%= (["?node_id: Integer", "?location: Location", "?flags: Integer"] + node.fields.map { |field| "?#{field.name}: #{field.rbs_class}" }).join(", ") %>) -> <%= node.name %> + def copy(<%= (["node_id", "location", "flags"] + node.fields.map(&:name)).map { |field| "#{field}: self.#{field}" }.join(", ") %>) + <%= node.name %>.new(<%= ["source", "node_id", "location", "flags", *node.fields.map(&:name)].join(", ") %>) end # def deconstruct: () -> Array[nil | Node] alias deconstruct child_nodes - # def deconstruct_keys: (Array[Symbol] keys) -> { <%= (node.fields.map { |field| "#{field.name}: #{field.rbs_class}" } + ["location: Location"]).join(", ") %> } + # def deconstruct_keys: (Array[Symbol] keys) -> { <%= (["node_id: Integer", "location: Location"] + node.fields.map { |field| "#{field.name}: #{field.rbs_class}" }).join(", ") %> } def deconstruct_keys(keys) - { <%= (node.fields.map { |field| "#{field.name}: #{field.name}" } + ["location: location"]).join(", ") %> } + { <%= (["node_id: node_id", "location: location"] + node.fields.map { |field| "#{field.name}: #{field.name}" }).join(", ") %> } end + <%- if (node_flags = node.flags) -%> + <%- node_flags.values.each do |value| -%> + + # def <%= value.name.downcase %>?: () -> bool + def <%= value.name.downcase %>? + flags.anybits?(<%= node_flags.name %>::<%= value.name %>) + end + <%- end -%> + <%- end -%> <%- node.fields.each do |field| -%> <%- if field.comment.nil? -%> - # <%= "protected " if field.is_a?(Prism::Template::FlagsField) %>attr_reader <%= field.name %>: <%= field.rbs_class %> + # attr_reader <%= field.name %>: <%= field.rbs_class %> <%- else -%> <%- field.each_comment_line do |line| -%> #<%= line %> @@ -301,7 +331,7 @@ module Prism end end <%- else -%> - attr_reader :<%= field.name -%><%= "\n protected :#{field.name}" if field.is_a?(Prism::Template::FlagsField) %> + attr_reader :<%= field.name %> <%- end -%> <%- end -%> <%- node.fields.each do |field| -%> @@ -322,14 +352,6 @@ module Prism def <%= field.name.delete_suffix("_loc") %> <%= field.name %>&.slice end - <%- when Prism::Template::FlagsField -%> - <%- flags.find { |flag| flag.name == field.kind }.tap { |flag| raise "Expected to find #{field.kind}" unless flag }.values.each do |value| -%> - - # def <%= value.name.downcase %>?: () -> bool - def <%= value.name.downcase %>? - <%= field.name %>.anybits?(<%= field.kind %>::<%= value.name %>) - end - <%- end -%> <%- end -%> <%- end -%> @@ -338,30 +360,12 @@ module Prism InspectVisitor.compose(self) end - # Sometimes you want to check an instance of a node against a list of - # classes to see what kind of behavior to perform. Usually this is done by - # calling `[cls1, cls2].include?(node.class)` or putting the node into a - # case statement and doing `case node; when cls1; when cls2; end`. Both of - # these approaches are relatively slow because of the constant lookups, - # method calls, and/or array allocations. - # - # Instead, you can call #type, which will return to you a symbol that you - # can use for comparison. This is faster than the other approaches because - # it uses a single integer comparison, but also because if you're on CRuby - # you can take advantage of the fact that case statements with all symbol - # keys will use a jump table. - # - # def type: () -> Symbol + # Return a symbol representation of this node type. See `Node#type`. def type :<%= node.human %> end - # Similar to #type, this method returns a symbol that you can use for - # splitting on the type of the node without having to do a long === chain. - # Note that like #type, it will still be slower than using == for a single - # class, but should be faster in a case statement or an array comparison. - # - # def self.type: () -> Symbol + # Return a symbol representation of this node type. See `Node::type`. def self.type :<%= node.human %> end @@ -369,29 +373,42 @@ module Prism # Implements case-equality for the node. This is effectively == but without # comparing the value of locations. Locations are checked only for presence. def ===(other) - other.is_a?(<%= node.name %>)<%= " &&" if node.fields.any? %> - <%- node.fields.each_with_index do |field, index| -%> + other.is_a?(<%= node.name %>)<%= " &&" if (fields = [*node.flags, *node.fields]).any? %> + <%- fields.each_with_index do |field, index| -%> <%- if field.is_a?(Prism::Template::LocationField) || field.is_a?(Prism::Template::OptionalLocationField) -%> - (<%= field.name %>.nil? == other.<%= field.name %>.nil?)<%= " &&" if index != node.fields.length - 1 %> + (<%= field.name %>.nil? == other.<%= field.name %>.nil?)<%= " &&" if index != fields.length - 1 %> <%- elsif field.is_a?(Prism::Template::NodeListField) || field.is_a?(Prism::Template::ConstantListField) -%> (<%= field.name %>.length == other.<%= field.name %>.length) && - <%= field.name %>.zip(other.<%= field.name %>).all? { |left, right| left === right }<%= " &&" if index != node.fields.length - 1 %> + <%= field.name %>.zip(other.<%= field.name %>).all? { |left, right| left === right }<%= " &&" if index != fields.length - 1 %> + <%- elsif field.is_a?(Prism::Template::Flags) -%> + (flags === other.flags)<%= " &&" if index != fields.length - 1 %> <%- else -%> - (<%= field.name %> === other.<%= field.name %>)<%= " &&" if index != node.fields.length - 1 %> + (<%= field.name %> === other.<%= field.name %>)<%= " &&" if index != fields.length - 1 %> <%- end -%> <%- end -%> end end <%- end -%> - <%- flags.each_with_index do |flag, flag_index| -%> + <%- flags.each do |flag| -%> # <%= flag.comment %> module <%= flag.name %> <%- flag.values.each_with_index do |value, index| -%> # <%= value.comment %> - <%= value.name %> = 1 << <%= index %> + <%= value.name %> = 1 << <%= index + Prism::Template::COMMON_FLAGS_COUNT %> <%= "\n" if value != flag.values.last -%> <%- end -%> end <%- end -%> + + # The flags that are common to all nodes. + module NodeFlags + # A flag to indicate that the node is a candidate to emit a :line event + # through tracepoint when compiled. + NEWLINE = 1 + + # A flag to indicate that the value that the node represents is a value that + # can be determined at parse-time. + STATIC_LITERAL = 2 + end end diff --git a/templates/lib/prism/reflection.rb.erb b/templates/lib/prism/reflection.rb.erb index 3c1d61c6c1a..6c8b2f4d257 100644 --- a/templates/lib/prism/reflection.rb.erb +++ b/templates/lib/prism/reflection.rb.erb @@ -97,7 +97,7 @@ module Prism case node.type <%- nodes.each do |node| -%> when :<%= node.human %> - [<%= node.fields.map { |field| + [<%= [*node.flags, *node.fields].map { |field| case field when Prism::Template::NodeField "NodeField.new(:#{field.name})" @@ -121,9 +121,8 @@ module Prism "IntegerField.new(:#{field.name})" when Prism::Template::DoubleField "FloatField.new(:#{field.name})" - when Prism::Template::FlagsField - found = flags.find { |flag| flag.name == field.kind }.tap { |found| raise "Expected to find #{field.kind}" unless found } - "FlagsField.new(:#{field.name}, [#{found.values.map { |value| ":#{value.name.downcase}?" }.join(", ")}])" + when Prism::Template::Flags + "FlagsField.new(:flags, [#{field.values.map { |value| ":#{value.name.downcase}?" }.join(", ")}])" else raise field.class.name end diff --git a/templates/lib/prism/serialize.rb.erb b/templates/lib/prism/serialize.rb.erb index 370b6297997..3750fdaa7ba 100644 --- a/templates/lib/prism/serialize.rb.erb +++ b/templates/lib/prism/serialize.rb.erb @@ -6,11 +6,11 @@ module Prism module Serialize # The major version of prism that we are expecting to find in the serialized # strings. - MAJOR_VERSION = 0 + MAJOR_VERSION = 1 # The minor version of prism that we are expecting to find in the serialized # strings. - MINOR_VERSION = 28 + MINOR_VERSION = 2 # The patch version of prism that we are expecting to find in the serialized # strings. @@ -20,10 +20,21 @@ module Prism def self.load(input, serialized) input = input.dup source = Source.for(input) + loader = Loader.new(source, serialized) result = loader.load_result input.force_encoding(loader.encoding) + + # This is an extremely niche use-case where the file was marked as binary + # but it contained UTF-8-encoded characters. In that case we will actually + # put it back to UTF-8 to give the location APIs the best chance of being + # correct. + if !input.ascii_only? && input.encoding == Encoding::BINARY + input.force_encoding(Encoding::UTF_8) + input.force_encoding(Encoding::BINARY) unless input.valid_encoding? + end + result end @@ -131,8 +142,8 @@ module Prism comments = load_comments magic_comments = Array.new(load_varuint) { MagicComment.new(load_location_object, load_location_object) } data_loc = load_optional_location_object - errors = Array.new(load_varuint) { ParseError.new(DIAGNOSTIC_TYPES[load_varuint], load_embedded_string, load_location_object, load_error_level) } - warnings = Array.new(load_varuint) { ParseWarning.new(DIAGNOSTIC_TYPES[load_varuint], load_embedded_string, load_location_object, load_warning_level) } + errors = Array.new(load_varuint) { ParseError.new(DIAGNOSTIC_TYPES.fetch(load_varuint), load_embedded_string, load_location_object, load_error_level) } + warnings = Array.new(load_varuint) { ParseWarning.new(DIAGNOSTIC_TYPES.fetch(load_varuint), load_embedded_string, load_location_object, load_warning_level) } [comments, magic_comments, data_loc, errors, warnings] end @@ -319,9 +330,10 @@ module Prism end end - if RUBY_ENGINE == 'ruby' + if RUBY_ENGINE == "ruby" def load_node type = io.getbyte + node_id = load_varuint location = load_location case type @@ -330,8 +342,7 @@ module Prism <%- if node.needs_serialized_length? -%> load_uint32 <%- end -%> - <%= node.name %>.new( - source, <%= (node.fields.map { |field| + <%= node.name %>.new(<%= ["source", "node_id", "location", "load_varuint", *node.fields.map { |field| case field when Prism::Template::NodeField then "load_node" when Prism::Template::OptionalNodeField then "load_optional_node" @@ -343,12 +354,12 @@ module Prism when Prism::Template::LocationField then "load_location" when Prism::Template::OptionalLocationField then "load_optional_location" when Prism::Template::UInt8Field then "io.getbyte" - when Prism::Template::UInt32Field, Prism::Template::FlagsField then "load_varuint" + when Prism::Template::UInt32Field then "load_varuint" when Prism::Template::IntegerField then "load_integer" when Prism::Template::DoubleField then "load_double" else raise end - } + ["location"]).join(", ") -%>) + }].join(", ") -%>) <%- end -%> end end @@ -363,12 +374,12 @@ module Prism nil, <%- nodes.each do |node| -%> -> { + node_id = load_varuint location = load_location <%- if node.needs_serialized_length? -%> load_uint32 <%- end -%> - <%= node.name %>.new( - source, <%= (node.fields.map { |field| + <%= node.name %>.new(<%= ["source", "node_id", "location", "load_varuint", *node.fields.map { |field| case field when Prism::Template::NodeField then "load_node" when Prism::Template::OptionalNodeField then "load_optional_node" @@ -380,12 +391,12 @@ module Prism when Prism::Template::LocationField then "load_location" when Prism::Template::OptionalLocationField then "load_optional_location" when Prism::Template::UInt8Field then "io.getbyte" - when Prism::Template::UInt32Field, Prism::Template::FlagsField then "load_varuint" + when Prism::Template::UInt32Field then "load_varuint" when Prism::Template::IntegerField then "load_integer" when Prism::Template::DoubleField then "load_double" else raise end - } + ["location"]).join(", ") -%>) + }].join(", ") -%>) }, <%- end -%> ] diff --git a/templates/rbi/prism/dsl.rbi.erb b/templates/rbi/prism/dsl.rbi.erb new file mode 100644 index 00000000000..76a39c50512 --- /dev/null +++ b/templates/rbi/prism/dsl.rbi.erb @@ -0,0 +1,68 @@ +module Prism::DSL + sig { params(string: String).returns(Prism::Source) } + def source(string); end + + sig { params(source: Prism::Source, start_offset: Integer, length: Integer).returns(Prism::Location) } + def location(source: default_source, start_offset: 0, length: 0); end + <%- nodes.each do |node| -%> + <%- + params = [ + ["source", "default_source", "Prism::Source"], + ["node_id", "0", "Integer"], + ["location", "default_location", "Prism::Location"], + ["flags", "0", "Integer"] + ].concat(node.fields.map { |field| + case field + when Prism::Template::NodeField + kind = field.specific_kind || field.union_kind&.first + if kind.nil? + [field.name, "default_node(source, location)", field.rbi_class] + else + [field.name, %Q{#{kind.gsub(/(?<=.)[A-Z]/, "_\\0").downcase}(source: source)}, field.rbi_class] + end + when Prism::Template::OptionalNodeField + [field.name, "nil", field.rbi_class] + when Prism::Template::NodeListField + [field.name, "[]", field.rbi_class] + when Prism::Template::ConstantField + [field.name, ":\"\"", field.rbi_class] + when Prism::Template::OptionalConstantField + [field.name, "nil", field.rbi_class] + when Prism::Template::ConstantListField + [field.name, "[]", field.rbi_class] + when Prism::Template::StringField + [field.name, "\"\"", field.rbi_class] + when Prism::Template::LocationField + [field.name, "location", field.rbi_class] + when Prism::Template::OptionalLocationField + [field.name, "nil", field.rbi_class] + when Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::IntegerField + [field.name, "0", field.rbi_class] + when Prism::Template::DoubleField + [field.name, "0.0", field.rbi_class] + else + raise + end + }) + -%> + + sig { params(<%= params.map { |(name, _, type)| "#{name}: #{type}" }.join(", ") %>).returns(Prism::<%= node.name %>) } + def <%= node.human %>(<%= params.map { |(name, default, _)| "#{name}: #{default}" }.join(", ") %>); end + <%- end -%> + <%- flags.each do |flag| -%> + + sig { params(name: Symbol).returns(Integer) } + def <%= flag.human.chomp("s") %>(name); end + <%- end -%> + + private + + sig { returns(Prism::Source) } + def default_source; end + + sig { returns(Prism::Location) } + def default_location; end + + sig { params(source: Prism::Source, location: Prism::Location).returns(Prism::Node) } + def default_node(source, location); end +end diff --git a/templates/rbi/prism/node.rbi.erb b/templates/rbi/prism/node.rbi.erb index 923324ff20f..c0474bd2089 100644 --- a/templates/rbi/prism/node.rbi.erb +++ b/templates/rbi/prism/node.rbi.erb @@ -4,9 +4,21 @@ class Prism::Node sig { returns(Prism::Source) } def source; end + sig { returns(Integer) } + def node_id; end + sig { returns(Prism::Location) } def location; end + sig{ returns(Integer) } + def flags; end + + sig { returns(T::Boolean) } + def newline?; end + + sig { returns(T::Boolean) } + def static_literal?; end + sig { returns(Integer) } def start_offset; end @@ -34,6 +46,9 @@ class Prism::Node sig { params(line: Integer, column: Integer).returns(T::Array[Prism::Node]) } def tunnel(line, column); end + sig { params(block: T.proc.params(node: Prism::Node).returns(T::Boolean)).returns(T.nilable(Prism::Node)) } + def breadth_first_search(&block); end + sig { abstract.params(visitor: Prism::Visitor).returns(T.untyped) } def accept(visitor); end @@ -64,13 +79,20 @@ end #<%= line %> <%- end -%> class Prism::<%= node.name -%> < Prism::Node + <%- if (node_flags = node.flags) -%> + <%- node_flags.values.each do |value| -%> + sig { returns(T::Boolean) } + def <%= value.name.downcase %>?; end + + <%- end -%> + <%- end -%> <%- node.fields.each do |field| -%> sig { returns(<%= field.rbi_class %>) } def <%= field.name %>; end <%- end -%> - sig { params(<%= ["source: Prism::Source", *node.fields.map { |field| "#{field.name}: #{field.rbi_class}" }, "location: Prism::Location"].join(", ") %>).void } - def initialize(<%= ["source", *node.fields.map(&:name), "location"].join(", ") %>); end + sig { params(<%= ["source: Prism::Source", "node_id: Integer", "location: Prism::Location", "flags: Integer", *node.fields.map { |field| "#{field.name}: #{field.rbi_class}" }].join(", ") %>).void } + def initialize(<%= ["source", "node_id", "location", "flags", *node.fields.map(&:name)].join(", ") %>); end sig { override.params(visitor: Prism::Visitor).returns(T.untyped) } def accept(visitor); end @@ -87,8 +109,8 @@ class Prism::<%= node.name -%> < Prism::Node sig { override.returns(T::Array[T.any(Prism::Node, Prism::Location)]) } def comment_targets; end - sig { params(<%= (node.fields.map { |field| "#{field.name}: #{field.rbi_class}" } + ["location: Prism::Location"]).join(", ") %>).returns(Prism::<%= node.name %>) } - def copy(<%= (node.fields.map(&:name) + ["location"]).map { |field| "#{field}: self.#{field}" }.join(", ") %>); end + sig { params(<%= (["node_id: Integer", "location: Prism::Location", "flags: Integer"] + node.fields.map { |field| "#{field.name}: #{field.rbi_class}" }).join(", ") %>).returns(Prism::<%= node.name %>) } + def copy(<%= (["node_id", "location", "flags"] + node.fields.map(&:name)).map { |field| "#{field}: self.#{field}" }.join(", ") %>); end sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -106,12 +128,6 @@ class Prism::<%= node.name -%> < Prism::Node sig { returns(T.nilable(String)) } def <%= field.name.delete_suffix("_loc") %>; end - <%- when Prism::Template::FlagsField -%> - <%- flags.find { |flag| flag.name == field.kind }.tap { |flag| raise "Expected to find #{field.kind}" unless flag }.values.each do |value| -%> - - sig { returns(T::Boolean) } - def <%= value.name.downcase %>?; end - <%- end -%> <%- end -%> <%- end -%> @@ -131,7 +147,18 @@ end module Prism::<%= flag.name %> <%- flag.values.each_with_index do |value, index| -%> # <%= value.comment %> - <%= value.name %> = T.let(1 << <%= index %>, Integer) + <%= value.name %> = T.let(1 << <%= index + Prism::Template::COMMON_FLAGS_COUNT %>, Integer) <%- end -%> end <%- end -%> + +# The flags that are common to all nodes. +module Prism::NodeFlags + # A flag to indicate that the node is a candidate to emit a :line event + # through tracepoint when compiled. + NEWLINE = T.let(1, Integer) + + # A flag to indicate that the value that the node represents is a value that + # can be determined at parse-time. + STATIC_LITERAL = T.let(2, Integer) +end diff --git a/templates/sig/prism.rbs.erb b/templates/sig/prism.rbs.erb index fd4277bbf48..7c03218ab50 100644 --- a/templates/sig/prism.rbs.erb +++ b/templates/sig/prism.rbs.erb @@ -6,6 +6,7 @@ module Prism <%- { parse: "ParseResult", + profile: "nil", lex: "LexResult", lex_compat: "LexCompat::Result", parse_lex: "ParseLexResult", @@ -18,13 +19,14 @@ module Prism def self.<%= method %>: ( String source, + ?encoding: Encoding | false, ?filepath: String, + ?frozen_string_literal: bool, ?line: Integer, + ?main_script: bool, ?offset: Integer, - ?encoding: Encoding, - ?frozen_string_literal: bool, - ?verbose: bool, - ?scopes: Array[Array[Symbol]] + ?scopes: Array[Array[Symbol]], + ?verbose: bool ) -> <%= return_type %> <%- end -%> @@ -41,6 +43,7 @@ module Prism <%- { parse_file: "ParseResult", + profile_file: "nil", lex_file: "LexResult", parse_lex_file: "ParseLexResult", dump_file: "String", @@ -52,12 +55,13 @@ module Prism def self.<%= method %>: ( String filepath, + ?encoding: Encoding | false, + ?frozen_string_literal: bool, ?line: Integer, + ?main_script: bool, ?offset: Integer, - ?encoding: Encoding, - ?frozen_string_literal: bool, - ?verbose: bool, - ?scopes: Array[Array[Symbol]] + ?scopes: Array[Array[Symbol]], + ?verbose: bool ) -> <%= return_type %> <%- end -%> @@ -67,12 +71,13 @@ module Prism def self.parse_stream: ( _Stream stream, + ?encoding: Encoding | false, ?filepath: String, + ?frozen_string_literal: bool, ?line: Integer, + ?main_script: bool, ?offset: Integer, - ?encoding: Encoding, - ?frozen_string_literal: bool, - ?verbose: bool, - ?scopes: Array[Array[Symbol]] + ?scopes: Array[Array[Symbol]], + ?verbose: bool ) -> ParseResult end diff --git a/templates/sig/prism/_private/dot_visitor.rbs.erb b/templates/sig/prism/_private/dot_visitor.rbs.erb index 92b7b8f13d4..4b380ecc97c 100644 --- a/templates/sig/prism/_private/dot_visitor.rbs.erb +++ b/templates/sig/prism/_private/dot_visitor.rbs.erb @@ -39,7 +39,7 @@ module Prism def location_inspect: (Location location) -> String <%- flags.each do |flag| -%> - def <%= flag.human %>_inspect: (<%= nodes.map { |node| node.name if node.fields.any? { |field| field.is_a?(Prism::Template::FlagsField) && field.kind == flag.name } }.compact.join(" | ") %> node) -> String + def <%= flag.human %>_inspect: (<%= nodes.filter_map { |node| node.name if node.flags == flag }.join(" | ") %> node) -> String <%- end -%> end end diff --git a/templates/sig/prism/dsl.rbs.erb b/templates/sig/prism/dsl.rbs.erb index 793c452735a..401467c0d8f 100644 --- a/templates/sig/prism/dsl.rbs.erb +++ b/templates/sig/prism/dsl.rbs.erb @@ -1,13 +1,31 @@ module Prism module DSL - private + def source: (String string) -> Source - # Create a new Location object - def Location: (?Source source, ?Integer start_offset, ?Integer length) -> Location + def location: (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location <%- nodes.each do |node| -%> + <%- + params = [ + ["source", "Source"], + ["node_id", "Integer"], + ["location", "Location"], + ["flags", "Integer"] + ].concat(node.fields.map { |field| [field.name, field.rbs_class] }) + -%> + + def <%= node.human %>: (<%= params.map { |(name, type)| "?#{name}: #{type}" }.join(", ") %>) -> <%= node.name %> + <%- end -%> + <%- flags.each do |flag| -%> - # Create a new <%= node.name %> node - def <%= node.name %>: (<%= (node.fields.map { |field| "#{field.rbs_class} #{field.name}" } + ["?Source source", "?Location location"]).join(", ") %>) -> <%= node.name %> + def <%= flag.human.chomp("s") %>: (Symbol name) -> Integer <%- end -%> + + private + + def default_source: () -> Source + + def default_location: () -> Location + + def default_node: (Source source, Location location) -> node end end diff --git a/templates/sig/prism/node.rbs.erb b/templates/sig/prism/node.rbs.erb index 5354dc3cb07..c8f9b86cf12 100644 --- a/templates/sig/prism/node.rbs.erb +++ b/templates/sig/prism/node.rbs.erb @@ -7,8 +7,13 @@ module Prism class Node extend _NodeSingleton - attr_reader location: Location attr_reader source: Source + attr_reader node_id: Integer + attr_reader location: Location + attr_reader flags: Integer + + def newline?: () -> bool + def static_literal?: () -> bool def start_offset: () -> Integer def end_offset: () -> Integer @@ -19,6 +24,9 @@ module Prism def pretty_print: (untyped q) -> untyped def to_dot: () -> String def tunnel: (Integer line, Integer column) -> Array[Prism::node] + def breadth_first_search: () { (Prism::node) -> bool } -> Prism::node? + def deprecated: (*String) -> void + def newline!: (Array[untyped]) -> void end type node_singleton = singleton(Node) & _NodeSingleton @@ -44,14 +52,20 @@ module Prism <%- end -%> class <%= node.name -%> < Node include _Node + <%- if (node_flags = node.flags) -%> + + <%- node_flags.values.each do |value| -%> + def <%= value.name.downcase %>?: () -> bool + <%- end -%> + <%- end -%> <%- node.fields.each do |field| -%> attr_reader <%= field.name %>: <%= field.rbs_class %> <%- end -%> - def initialize: (<%= ["Source source", *node.fields.map { |field| "#{field.rbs_class} #{field.name}" }, "Location location"].join(", ") %>) -> void - def copy: (<%= (node.fields.map { |field| "?#{field.name}: #{field.rbs_class}" } + ["?location: Location"]).join(", ") %>) -> <%= node.name %> - def deconstruct_keys: (Array[Symbol] keys) -> { <%= (node.fields.map { |field| "#{field.name}: #{field.rbs_class}" } + ["location: Location"]).join(", ") %> } + def initialize: (<%= ["Source source", "Integer node_id", "Location location", "Integer flags", *node.fields.map { |field| "#{field.rbs_class} #{field.name}" }].join(", ") %>) -> void + def copy: (<%= (["?node_id: Integer", "?location: Location", "?flags: Integer"] + node.fields.map { |field| "?#{field.name}: #{field.rbs_class}" }).join(", ") %>) -> <%= node.name %> + def deconstruct_keys: (Array[Symbol] keys) -> { <%= (["node_id: Integer", "location: Location"] + node.fields.map { |field| "#{field.name}: #{field.rbs_class}" }).join(", ") %> } <%- node.fields.each do |field| -%> <%- case field -%> <%- when Prism::Template::LocationField -%> @@ -62,10 +76,6 @@ module Prism <%- raise unless field.name.end_with?("_loc") -%> <%- next if node.fields.any? { |other| other.name == field.name.delete_suffix("_loc") } -%> def <%= field.name.delete_suffix("_loc") %>: () -> String? - <%- when Prism::Template::FlagsField -%> - <%- flags.find { |flag| flag.name == field.kind }.tap { |flag| raise "Expected to find #{field.kind}" unless flag }.values.each do |value| -%> - def <%= value.name.downcase %>?: () -> bool - <%- end -%> <%- end -%> <%- end -%> def type: () -> :<%= node.human %> @@ -83,4 +93,10 @@ module Prism <%- end -%> end <%- end -%> + + # The flags that are common to all nodes. + module NodeFlags + NEWLINE: Integer + STATIC_LITERAL: Integer + end end diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index 86e7c3b6d1a..c0ec69652f3 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -91,27 +91,28 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_ARGUMENT_AFTER_BLOCK] = { "unexpected argument after a block argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES] = { "unexpected argument after `...`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_BARE_HASH] = { "unexpected bare hash argument", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_ARGUMENT_BLOCK_FORWARDING] = { "both a block argument and a forwarding argument; only one block is allowed", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_BLOCK_MULTI] = { "both block arg and actual block given; only one block is allowed", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ARGUMENT_CONFLICT_AMPERSAND] = { "unexpected `&`; anonymous block parameter is also used within block", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ARGUMENT_CONFLICT_STAR] = { "unexpected `*`; anonymous rest parameter is also used within block", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ARGUMENT_CONFLICT_STAR_STAR] = { "unexpected `**`; anonymous keyword rest parameter is also used within block", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_FORMAL_CLASS] = { "invalid formal argument; formal argument cannot be a class variable", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_FORMAL_CONSTANT] = { "invalid formal argument; formal argument cannot be a constant", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_FORMAL_GLOBAL] = { "invalid formal argument; formal argument cannot be a global variable", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_FORMAL_IVAR] = { "invalid formal argument; formal argument cannot be an instance variable", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_FORWARDING_UNBOUND] = { "unexpected `...` in an non-parenthesized call", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_ARGUMENT_IN] = { "unexpected `in` keyword in arguments", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_ARGUMENT_NO_FORWARDING_AMP] = { "unexpected `&`; no anonymous block parameter", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ARGUMENT_NO_FORWARDING_AMPERSAND] = { "unexpected `&`; no anonymous block parameter", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = { "unexpected ... when the parent method is not forwarding", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_NO_FORWARDING_STAR] = { "unexpected `*`; no anonymous rest parameter", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR] = { "unexpected `**`; no anonymous keyword rest parameter", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT] = { "unexpected `*` splat argument after a `**` keyword splat argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_SPLAT_AFTER_SPLAT] = { "unexpected `*` splat argument after a `*` splat argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_TERM_PAREN] = { "unexpected %s; expected a `)` to close the arguments", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_ARGUMENT_UNEXPECTED_BLOCK] = { "unexpected `{` after a method call without parenthesis", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ARGUMENT_UNEXPECTED_BLOCK] = { "unexpected '{' after a method call without parenthesis", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARRAY_ELEMENT] = { "expected an element for the array", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARRAY_EXPRESSION] = { "expected an expression for the array element", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARRAY_EXPRESSION_AFTER_STAR] = { "expected an expression after `*` in the array", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_ARRAY_SEPARATOR] = { "expected a `,` separator for the array elements", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_ARRAY_TERM] = { "expected a `]` to close the array", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ARRAY_SEPARATOR] = { "unexpected %s; expected a `,` separator for the array elements", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ARRAY_TERM] = { "unexpected %s; expected a `]` to close the array", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_BEGIN_LONELY_ELSE] = { "unexpected `else` in `begin` block; else without rescue is useless", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_BEGIN_TERM] = { "expected an `end` to close the `begin` statement", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_BEGIN_UPCASE_BRACE] = { "expected a `{` after `BEGIN`", PM_ERROR_LEVEL_SYNTAX }, @@ -146,7 +147,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_DEF_ENDLESS_SETTER] = { "invalid method name; a setter method cannot be defined in an endless method definition", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_NAME] = { "unexpected %s; expected a method name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_PARAMS_TERM] = { "expected a delimiter to close the parameters", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_DEF_PARAMS_TERM_PAREN] = { "expected a `)` to close the parameters", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_DEF_PARAMS_TERM_PAREN] = { "unexpected %s; expected a `)` to close the parameters", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_RECEIVER] = { "expected a receiver for the method definition", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_RECEIVER_TERM] = { "expected a `.` or `::` after the receiver in a method definition", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_TERM] = { "expected an `end` to close the `def` statement", PM_ERROR_LEVEL_SYNTAX }, @@ -156,17 +157,19 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_EMBVAR_INVALID] = { "invalid embedded variable", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_END_UPCASE_BRACE] = { "expected a `{` after `END`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_END_UPCASE_TERM] = { "expected a `}` to close the `END` statement", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_ESCAPE_INVALID_CONTROL] = { "invalid control escape sequence", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ESCAPE_INVALID_CONTROL] = { "Invalid escape character syntax", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT] = { "invalid control escape sequence; control cannot be repeated", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ESCAPE_INVALID_HEXADECIMAL] = { "invalid hex escape sequence", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_ESCAPE_INVALID_META] = { "invalid meta escape sequence", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ESCAPE_INVALID_META] = { "Invalid escape character syntax", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ESCAPE_INVALID_META_REPEAT] = { "invalid meta escape sequence; meta cannot be repeated", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ESCAPE_INVALID_UNICODE] = { "invalid Unicode escape sequence", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ESCAPE_INVALID_UNICODE_CM_FLAGS] = { "invalid Unicode escape sequence; Unicode cannot be combined with control or meta flags", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ESCAPE_INVALID_UNICODE_LIST] = { "invalid Unicode list: %.*s", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ESCAPE_INVALID_UNICODE_LITERAL] = { "invalid Unicode escape sequence; Multiple codepoints at single character literal are disallowed", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ESCAPE_INVALID_UNICODE_LONG] = { "invalid Unicode escape sequence; maximum length is 6 digits", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_ESCAPE_INVALID_UNICODE_TERM] = { "invalid Unicode escape sequence; needs closing `}`", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_EXPECT_ARGUMENT] = { "expected an argument", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ESCAPE_INVALID_UNICODE_SHORT] = { "too short escape sequence: %.*s", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ESCAPE_INVALID_UNICODE_TERM] = { "unterminated Unicode escape", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPECT_ARGUMENT] = { "unexpected %s; expected an argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EOL_AFTER_STATEMENT] = { "unexpected %s, expecting end-of-input", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ] = { "expected an expression after `&&=`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ] = { "expected an expression after `||=`", PM_ERROR_LEVEL_SYNTAX }, @@ -174,17 +177,20 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL] = { "expected an expression after `=`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS] = { "expected an expression after `<<`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EXPRESSION_AFTER_LPAREN] = { "expected an expression after `(`", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR] = { "expected an expression after the operator", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR] = { "unexpected %s; expected an expression after the operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT] = { "expected an expression after `*` splat in an argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH] = { "expected an expression after `**` in a hash", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EXPRESSION_AFTER_STAR] = { "expected an expression after `*`", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPECT_FOR_DELIMITER] = { "unexpected %s; expected a 'do', newline, or ';' after the 'for' loop collection", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_IDENT_REQ_PARAMETER] = { "expected an identifier for the required parameter", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPECT_IN_DELIMITER] = { "expected a delimiter after the patterns of an `in` clause", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_LPAREN_REQ_PARAMETER] = { "expected a `(` to start a required parameter", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_MESSAGE] = { "unexpected %s; expecting a message to send to the receiver", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_RBRACKET] = { "expected a matching `]`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_RPAREN] = { "expected a matching `)`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_RPAREN_AFTER_MULTI] = { "expected a `)` after multiple assignment", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_RPAREN_REQ_PARAMETER] = { "expected a `)` to end a required parameter", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPECT_SINGLETON_CLASS_DELIMITER] = { "unexpected %s; expected a newline or a ';' after the singleton class", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_STRING_CONTENT] = { "expected string content after opening string delimiter", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_WHEN_DELIMITER] = { "expected a delimiter after the predicates of a `when` clause", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPRESSION_BARE_HASH] = { "unexpected bare hash in expression", PM_ERROR_LEVEL_SYNTAX }, @@ -194,6 +200,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_EXPRESSION_NOT_WRITABLE_FILE] = { "Can't assign to __FILE__", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPRESSION_NOT_WRITABLE_LINE] = { "Can't assign to __LINE__", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPRESSION_NOT_WRITABLE_NIL] = { "Can't assign to nil", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPRESSION_NOT_WRITABLE_NUMBERED] = { "Can't assign to numbered parameter %.2s", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPRESSION_NOT_WRITABLE_SELF] = { "Can't change the value of self", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPRESSION_NOT_WRITABLE_TRUE] = { "Can't assign to true", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_FLOAT_PARSE] = { "could not parse the float '%.*s'", PM_ERROR_LEVEL_SYNTAX }, @@ -206,9 +213,9 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_HASH_KEY] = { "unexpected %s, expecting '}' or a key in the hash literal", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_HASH_ROCKET] = { "expected a `=>` between the hash key and value", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_HASH_TERM] = { "expected a `}` to close the hash literal", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_HASH_VALUE] = { "expected a value in the hash literal", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_HASH_VALUE] = { "unexpected %s; expected a value in the hash literal", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_HEREDOC_IDENTIFIER] = { "unterminated here document identifier", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_HEREDOC_TERM] = { "unterminated heredoc; can't find string \"%.*s\"", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_HEREDOC_TERM] = { "unterminated heredoc; can't find string \"%.*s\" anywhere before EOF", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INCOMPLETE_QUESTION_MARK] = { "incomplete expression at `?`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INCOMPLETE_VARIABLE_CLASS_3_3] = { "`%.*s' is not allowed as a class variable name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INCOMPLETE_VARIABLE_CLASS] = { "'%.*s' is not allowed as a class variable name", PM_ERROR_LEVEL_SYNTAX }, @@ -216,21 +223,25 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_INCOMPLETE_VARIABLE_INSTANCE] = { "'%.*s' is not allowed as an instance variable name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INSTANCE_VARIABLE_BARE] = { "'@' without identifiers is not allowed as an instance variable name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_BLOCK_EXIT] = { "Invalid %s", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_INVALID_COMMA] = { "invalid comma", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_INVALID_ESCAPE_CHARACTER] = { "Invalid escape character syntax", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_FLOAT_EXPONENT] = { "invalid exponent", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_LOCAL_VARIABLE_READ] = { "identifier %.*s is not valid to get", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_LOCAL_VARIABLE_WRITE] = { "identifier %.*s is not valid to set", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_NUMBER_BINARY] = { "invalid binary number; numeric literal without digits", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_NUMBER_DECIMAL] = { "invalid decimal number; numeric literal without digits", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_INVALID_NUMBER_FRACTION] = { "unexpected fraction part after numeric literal", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_NUMBER_HEXADECIMAL] = { "invalid hexadecimal number; numeric literal without digits", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_NUMBER_OCTAL] = { "invalid octal number; numeric literal without digits", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_NUMBER_UNDERSCORE_INNER] = { "invalid underscore placement in number", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_NUMBER_UNDERSCORE_TRAILING] = { "trailing '_' in number", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_INVALID_CHARACTER] = { "invalid character 0x%X", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_INVALID_CHARACTER] = { "Invalid char '\\x%02X' in expression", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_MULTIBYTE_CHAR] = { "invalid multibyte char (%s)", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_MULTIBYTE_CHARACTER] = { "invalid multibyte character 0x%X", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_MULTIBYTE_ESCAPE] = { "invalid multibyte escape: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_PRINTABLE_CHARACTER] = { "invalid character `%c`", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_INVALID_PERCENT] = { "invalid `%` token", PM_ERROR_LEVEL_SYNTAX }, // TODO WHAT? + [PM_ERR_INVALID_PERCENT] = { "unknown type of %string", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_INVALID_PERCENT_EOF] = { "unterminated quoted string meets end of file", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_RETRY_AFTER_ELSE] = { "Invalid retry after else", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_RETRY_AFTER_ENSURE] = { "Invalid retry after ensure", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_RETRY_WITHOUT_RESCUE] = { "Invalid retry without rescue", PM_ERROR_LEVEL_SYNTAX }, @@ -238,7 +249,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_INVALID_VARIABLE_GLOBAL_3_3] = { "`%.*s' is not allowed as a global variable name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_VARIABLE_GLOBAL] = { "'%.*s' is not allowed as a global variable name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_YIELD] = { "Invalid yield", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_IT_NOT_ALLOWED_NUMBERED] = { "`it` is not allowed when an numbered parameter is defined", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_IT_NOT_ALLOWED_NUMBERED] = { "`it` is not allowed when a numbered parameter is already used", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_IT_NOT_ALLOWED_ORDINARY] = { "`it` is not allowed when an ordinary parameter is defined", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_LAMBDA_OPEN] = { "expected a `do` keyword or a `{` to open the lambda block", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_LAMBDA_TERM_BRACE] = { "expected a lambda block beginning with `{` to end with `}`", PM_ERROR_LEVEL_SYNTAX }, @@ -258,18 +269,22 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_MODULE_TERM] = { "expected an `end` to close the `module` statement", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_MULTI_ASSIGN_MULTI_SPLATS] = { "multiple splats in multiple assignment", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_MULTI_ASSIGN_UNEXPECTED_REST] = { "unexpected '%.*s' resulting in multiple splats in multiple assignment", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_NOT_EXPRESSION] = { "expected an expression after `not`", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_NESTING_TOO_DEEP] = { "nesting too deep", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_NO_LOCAL_VARIABLE] = { "%.*s: no such local variable", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_NON_ASSOCIATIVE_OPERATOR] = { "unexpected %s; %s is a non-associative operator", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_NOT_EXPRESSION] = { "expected an expression after `not`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_NUMBER_LITERAL_UNDERSCORE] = { "number literal ending with a `_`", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_NUMBERED_PARAMETER_IT] = { "numbered parameters are not allowed when an 'it' parameter is defined", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_NUMBERED_PARAMETER_INNER_BLOCK] = { "numbered parameter is already used in inner block", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_NUMBERED_PARAMETER_IT] = { "numbered parameters are not allowed when 'it' is already used", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_NUMBERED_PARAMETER_ORDINARY] = { "numbered parameters are not allowed when an ordinary parameter is defined", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_NUMBERED_PARAMETER_OUTER_SCOPE] = { "numbered parameter is already used in outer scope", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_NUMBERED_PARAMETER_OUTER_BLOCK] = { "numbered parameter is already used in outer block", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_OPERATOR_MULTI_ASSIGN] = { "unexpected operator for a multiple assignment", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_OPERATOR_WRITE_ARGUMENTS] = { "unexpected operator after a call with arguments", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_OPERATOR_WRITE_BLOCK] = { "unexpected operator after a call with a block", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_ASSOC_SPLAT_MULTI] = { "unexpected multiple `**` splat parameters", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_BLOCK_MULTI] = { "multiple block parameters; only one block is allowed", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_CIRCULAR] = { "circular argument reference - %.*s", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_PARAMETER_FORWARDING_AFTER_REST] = { "... after rest argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_METHOD_NAME] = { "unexpected name for a parameter", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_NAME_DUPLICATED] = { "duplicated argument name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_NO_DEFAULT] = { "expected a default value for the parameter", PM_ERROR_LEVEL_SYNTAX }, @@ -281,6 +296,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_PARAMETER_UNEXPECTED_FWD] = { "unexpected `...` in parameters", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_WILD_LOOSE_COMMA] = { "unexpected `,` in parameters", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_UNEXPECTED_NO_KW] = { "unexpected **nil; no keywords marker disallowed after keywords", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_PATTERN_ARRAY_MULTIPLE_RESTS] = { "unexpected multiple '*' rest patterns in an array pattern", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_CAPTURE_DUPLICATE] = { "duplicated variable name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET] = { "expected a pattern expression after the `[` operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA] = { "expected a pattern expression after `,`", PM_ERROR_LEVEL_SYNTAX }, @@ -292,9 +308,12 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE] = { "expected a pattern expression after the `|` operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE] = { "expected a pattern expression after the range operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_EXPRESSION_AFTER_REST] = { "unexpected pattern expression after the `**` expression", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_PATTERN_HASH_KEY] = { "expected a key in the hash pattern", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_PATTERN_FIND_MISSING_INNER] = { "find patterns need at least one required inner pattern", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_PATTERN_HASH_IMPLICIT] = { "unexpected implicit hash in pattern; use '{' to delineate", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_PATTERN_HASH_KEY] = { "unexpected %s; expected a key in the hash pattern", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_HASH_KEY_DUPLICATE] = { "duplicated key name", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_PATTERN_HASH_KEY_LABEL] = { "expected a label as the key in the hash pattern", PM_ERROR_LEVEL_SYNTAX }, // TODO // THIS // AND // ABOVE // IS WEIRD + [PM_ERR_PATTERN_HASH_KEY_INTERPOLATED] = { "symbol literal with interpolation is not allowed", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_PATTERN_HASH_KEY_LABEL] = { "expected a label as the key in the hash pattern", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_HASH_KEY_LOCALS] = { "key must be valid as local variables", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_IDENT_AFTER_HROCKET] = { "expected an identifier after the `=>` operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_LABEL_AFTER_COMMA] = { "expected a label after the `,` in the hash pattern", PM_ERROR_LEVEL_SYNTAX }, @@ -307,7 +326,8 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_REGEXP_INCOMPAT_CHAR_ENCODING] = { "incompatible character encoding: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_REGEXP_NON_ESCAPED_MBC] = { "/.../n has a non escaped non ASCII character in non ASCII-8BIT script: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_REGEXP_INVALID_UNICODE_RANGE] = { "invalid Unicode range: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_REGEXP_UNKNOWN_OPTIONS] = { "unknown regexp %s: %.*s", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_REGEXP_PARSE_ERROR] = { "%s", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_REGEXP_UNKNOWN_OPTIONS] = { "unknown regexp %s - %.*s", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_REGEXP_TERM] = { "unterminated regexp meets end of file; expected a closing delimiter", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_REGEXP_UTF8_CHAR_NON_UTF8_REGEXP] = { "UTF-8 character in non UTF-8 regexp: /%s/", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_RESCUE_EXPRESSION] = { "expected a rescued expression", PM_ERROR_LEVEL_SYNTAX }, @@ -321,20 +341,24 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_STATEMENT_PREEXE_BEGIN] = { "unexpected a `BEGIN` at a non-statement position", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_STATEMENT_UNDEF] = { "unexpected an `undef` at a non-statement position", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_STRING_CONCATENATION] = { "expected a string for concatenation", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_STRING_INTERPOLATED_TERM] = { "expected a closing delimiter for the interpolated string", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_STRING_INTERPOLATED_TERM] = { "unterminated string; expected a closing delimiter for the interpolated string", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_STRING_LITERAL_EOF] = { "unterminated string meets end of file", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_STRING_LITERAL_TERM] = { "unexpected %s, expected a string literal terminator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_SYMBOL_INVALID] = { "invalid symbol", PM_ERROR_LEVEL_SYNTAX }, // TODO expected symbol? prism.c ~9719 [PM_ERR_SYMBOL_TERM_DYNAMIC] = { "unterminated quoted string; expected a closing delimiter for the dynamic symbol", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_SYMBOL_TERM_INTERPOLATED] = { "expected a closing delimiter for the interpolated symbol", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_SYMBOL_TERM_INTERPOLATED] = { "unterminated symbol; expected a closing delimiter for the interpolated symbol", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_TERNARY_COLON] = { "expected a `:` after the true expression of a ternary operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_TERNARY_EXPRESSION_FALSE] = { "expected an expression after `:` in the ternary operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_TERNARY_EXPRESSION_TRUE] = { "expected an expression after `?` in the ternary operator", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_UNDEF_ARGUMENT] = { "invalid argument being passed to `undef`; expected a bare word, constant, or symbol argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_UNARY_RECEIVER] = { "unexpected %s, expected a receiver for unary `%c`", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_UNARY_DISALLOWED] = { "unexpected %s; unary calls are not allowed in this context", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_UNDEF_ARGUMENT] = { "invalid argument being passed to `undef`; expected a bare word, constant, or symbol argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_UNEXPECTED_BLOCK_ARGUMENT] = { "block argument should not be given", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_UNEXPECTED_INDEX_BLOCK] = { "unexpected block arg given in index; blocks are not allowed in index expressions", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_UNEXPECTED_INDEX_KEYWORDS] = { "unexpected keyword arg given in index; keywords are not allowed in index expressions", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_UNEXPECTED_INDEX_BLOCK] = { "unexpected block arg given in index assignment; blocks are not allowed in index assignment expressions", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_UNEXPECTED_INDEX_KEYWORDS] = { "unexpected keyword arg given in index assignment; keywords are not allowed in index assignment expressions", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_UNEXPECTED_LABEL] = { "unexpected label", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_UNEXPECTED_MULTI_WRITE] = { "unexpected multiple assignment; multiple assignment is not allowed in this context", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_UNEXPECTED_RANGE_OPERATOR] = { "unexpected range operator; .. and ... are non-associative and cannot be chained", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_UNEXPECTED_SAFE_NAVIGATION] = { "&. inside multiple assignment destination", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT] = { "unexpected %s, assuming it is closing the parent %s", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_UNEXPECTED_TOKEN_IGNORE] = { "unexpected %s, ignoring it", PM_ERROR_LEVEL_SYNTAX }, @@ -347,6 +371,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_XSTRING_TERM] = { "expected a closing delimiter for the `%x` or backtick string", PM_ERROR_LEVEL_SYNTAX }, // Warnings + [PM_WARN_AMBIGUOUS_BINARY_OPERATOR] = { "'%s' after local variable or literal is interpreted as binary operator even though it seems like %s", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_MINUS] = { "ambiguous first argument; put parentheses or a space even after `-` operator", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_PLUS] = { "ambiguous first argument; put parentheses or a space even after `+` operator", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_AMBIGUOUS_PREFIX_AMPERSAND] = { "ambiguous `&` has been interpreted as an argument prefix", PM_WARNING_LEVEL_VERBOSE }, @@ -356,19 +381,21 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_WARN_COMPARISON_AFTER_COMPARISON] = { "comparison '%.*s' after comparison", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_DOT_DOT_DOT_EOL] = { "... at EOL, should be parenthesized?", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_DUPLICATED_HASH_KEY] = { "key %.*s is duplicated and overwritten on line %" PRIi32, PM_WARNING_LEVEL_DEFAULT }, - [PM_WARN_DUPLICATED_WHEN_CLAUSE] = { "duplicated 'when' clause with line %" PRIi32 " is ignored", PM_WARNING_LEVEL_VERBOSE }, + [PM_WARN_DUPLICATED_WHEN_CLAUSE] = { "'when' clause on line %" PRIi32 " duplicates 'when' clause on line %" PRIi32 " and is ignored", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_EQUAL_IN_CONDITIONAL_3_3] = { "found `= literal' in conditional, should be ==", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_EQUAL_IN_CONDITIONAL] = { "found '= literal' in conditional, should be ==", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_END_IN_METHOD] = { "END in method; use at_exit", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_FLOAT_OUT_OF_RANGE] = { "Float %.*s%s out of range", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_IGNORED_FROZEN_STRING_LITERAL] = { "'frozen_string_literal' is ignored after any tokens", PM_WARNING_LEVEL_VERBOSE }, + [PM_WARN_INDENTATION_MISMATCH] = { "mismatched indentations at '%.*s' with '%.*s' at %" PRIi32, PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_INTEGER_IN_FLIP_FLOP] = { "integer literal in flip-flop", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_INVALID_CHARACTER] = { "invalid character syntax; use %s%s%s", PM_WARNING_LEVEL_DEFAULT }, - [PM_WARN_INVALID_SHAREABLE_CONSTANT_VALUE] = { "invalid value for shareable_constant_value: %.*s", PM_WARNING_LEVEL_VERBOSE }, + [PM_WARN_INVALID_MAGIC_COMMENT_VALUE] = { "invalid value for %.*s: %.*s", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_INVALID_NUMBERED_REFERENCE] = { "'%.*s' is too big for a number variable, always nil", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_KEYWORD_EOL] = { "`%.*s` at the end of line without an expression", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_LITERAL_IN_CONDITION_DEFAULT] = { "%sliteral in %s", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_LITERAL_IN_CONDITION_VERBOSE] = { "%sliteral in %s", PM_WARNING_LEVEL_VERBOSE }, + [PM_WARN_SHAREABLE_CONSTANT_VALUE_LINE] = { "'shareable_constant_value' is ignored unless in comment-only line", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_SHEBANG_CARRIAGE_RETURN] = { "shebang line ending with \\r may cause problems", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_UNEXPECTED_CARRIAGE_RETURN] = { "encountered \\r in middle of line, treated as a mere space", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_UNREACHABLE_STATEMENT] = { "statement not reached", PM_WARNING_LEVEL_VERBOSE }, diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index e1c35f5a456..2357e552000 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -1,19 +1,6 @@ -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" #include "prism/node.h" -static void -pm_node_memsize_node(pm_node_t *node, pm_memsize_t *memsize); - -/** - * Calculate the size of the node list in bytes. - */ -static size_t -pm_node_list_memsize(pm_node_list_t *node_list, pm_memsize_t *memsize) { - pm_node_t *node; - PM_NODE_LIST_FOREACH(node_list, index, node) pm_node_memsize_node(node, memsize); - return sizeof(pm_node_list_t) + (node_list->capacity * sizeof(pm_node_t *)); -} - /** * Attempts to grow the node list to the next size. If there is already * capacity in the list, this function does nothing. Otherwise it reallocates @@ -119,14 +106,14 @@ PRISM_EXPORTED_FUNCTION void pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { switch (PM_NODE_TYPE(node)) { <%- nodes.each do |node| -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" case <%= node.type %>: { - <%- if node.fields.any? { |field| ![Prism::Template::LocationField, Prism::Template::OptionalLocationField, Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::FlagsField, Prism::Template::ConstantField, Prism::Template::OptionalConstantField, Prism::Template::DoubleField].include?(field.class) } -%> + <%- if node.fields.any? { |field| ![Prism::Template::LocationField, Prism::Template::OptionalLocationField, Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::ConstantField, Prism::Template::OptionalConstantField, Prism::Template::DoubleField].include?(field.class) } -%> pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node; <%- end -%> <%- node.fields.each do |field| -%> <%- case field -%> - <%- when Prism::Template::LocationField, Prism::Template::OptionalLocationField, Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::FlagsField, Prism::Template::ConstantField, Prism::Template::OptionalConstantField, Prism::Template::DoubleField -%> + <%- when Prism::Template::LocationField, Prism::Template::OptionalLocationField, Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::ConstantField, Prism::Template::OptionalConstantField, Prism::Template::DoubleField -%> <%- when Prism::Template::NodeField -%> pm_node_destroy(parser, (pm_node_t *)cast-><%= field.name %>); <%- when Prism::Template::OptionalNodeField -%> @@ -148,7 +135,7 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { break; } <%- end -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" default: assert(false && "unreachable"); break; @@ -156,57 +143,6 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { xfree(node); } -static void -pm_node_memsize_node(pm_node_t *node, pm_memsize_t *memsize) { - memsize->node_count++; - - switch (PM_NODE_TYPE(node)) { - // We do not calculate memsize of a ScopeNode - // as it should never be generated - case PM_SCOPE_NODE: - return; - <%- nodes.each do |node| -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" - case <%= node.type %>: { - pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node; - memsize->memsize += sizeof(*cast); - <%- node.fields.each do |field| -%> - <%- case field -%> - <%- when Prism::Template::ConstantField, Prism::Template::OptionalConstantField, Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::FlagsField, Prism::Template::LocationField, Prism::Template::OptionalLocationField, Prism::Template::DoubleField -%> - <%- when Prism::Template::NodeField -%> - pm_node_memsize_node((pm_node_t *)cast-><%= field.name %>, memsize); - <%- when Prism::Template::OptionalNodeField -%> - if (cast-><%= field.name %> != NULL) { - pm_node_memsize_node((pm_node_t *)cast-><%= field.name %>, memsize); - } - <%- when Prism::Template::StringField -%> - memsize->memsize += (pm_string_memsize(&cast-><%= field.name %>) - sizeof(pm_string_t)); - <%- when Prism::Template::NodeListField -%> - memsize->memsize += (pm_node_list_memsize(&cast-><%= field.name %>, memsize) - sizeof(pm_node_list_t)); - <%- when Prism::Template::ConstantListField -%> - memsize->memsize += (pm_constant_id_list_memsize(&cast-><%= field.name %>) - sizeof(pm_constant_id_list_t)); - <%- when Prism::Template::IntegerField -%> - memsize->memsize += (pm_integer_memsize(&cast-><%= field.name %>) - sizeof(pm_integer_t)); - <%- else -%> - <%- raise -%> - <%- end -%> - <%- end -%> - break; - } - <%- end -%> -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" - } -} - -/** - * Calculates the memory footprint of a given node. - */ -PRISM_EXPORTED_FUNCTION void -pm_node_memsize(pm_node_t *node, pm_memsize_t *memsize) { - *memsize = (pm_memsize_t) { .memsize = 0, .node_count = 0 }; - pm_node_memsize_node(node, memsize); -} - /** * Returns a string representation of the given node type. */ @@ -308,7 +244,7 @@ pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *no const pm_<%= node.human %>_t *cast = (const pm_<%= node.human %>_t *) node; pm_dump_json_location(buffer, parser, &cast->base.location); - <%- node.fields.each_with_index do |field, index| -%> + <%- [*node.flags, *node.fields].each_with_index do |field, index| -%> // Dump the <%= field.name %> field pm_buffer_append_byte(buffer, ','); @@ -365,12 +301,11 @@ pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *no pm_buffer_append_format(buffer, "%" PRIu8, cast-><%= field.name %>); <%- when Prism::Template::UInt32Field -%> pm_buffer_append_format(buffer, "%" PRIu32, cast-><%= field.name %>); - <%- when Prism::Template::FlagsField -%> + <%- when Prism::Template::Flags -%> size_t flags = 0; pm_buffer_append_byte(buffer, '['); - <%- found = flags.find { |flag| flag.name == field.kind }.tap { |found| raise "Expected to find #{field.kind}" unless found } -%> - <%- found.values.each_with_index do |value, index| -%> - if (PM_NODE_FLAG_P(cast, PM_<%= found.human.upcase %>_<%= value.name %>)) { + <%- node.flags.values.each_with_index do |value, index| -%> + if (PM_NODE_FLAG_P(cast, PM_<%= node.flags.human.upcase %>_<%= value.name %>)) { if (flags != 0) pm_buffer_append_byte(buffer, ','); pm_buffer_append_string(buffer, "\"<%= value.name %>\"", <%= value.name.bytesize + 2 %>); flags++; diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index 27f44cd996f..639c2fecf33 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -31,14 +31,14 @@ prettyprint_node(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm return; <%- nodes.each do |node| -%> case <%= node.type %>: { - <%- if node.fields.any? -%> + <%- if !node.flags.nil? || node.fields.any? -%> pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node; <%- end -%> pm_buffer_append_string(output_buffer, "@ <%= node.name %> (location: ", <%= node.name.length + 14 %>); prettyprint_location(output_buffer, parser, &node->location); pm_buffer_append_string(output_buffer, ")\n", 2); - <%- node.fields.each_with_index do |field, index| -%> - <%- preadd = index == node.fields.length - 1 ? " " : "| " -%> + <%- (fields = [*node.flags, *node.fields]).each_with_index do |field, index| -%> + <%- preadd = index == fields.length - 1 ? " " : "| " -%> // <%= field.name %> { @@ -123,11 +123,10 @@ prettyprint_node(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm pm_buffer_append_format(output_buffer, " %" PRIu8 "\n", cast-><%= field.name %>); <%- when Prism::Template::UInt32Field -%> pm_buffer_append_format(output_buffer, " %" PRIu32 "\n", cast-><%= field.name %>); - <%- when Prism::Template::FlagsField -%> + <%- when Prism::Template::Flags -%> bool found = false; - <%- found = flags.find { |flag| flag.name == field.kind }.tap { |found| raise "Expected to find #{field.kind}" unless found } -%> - <%- found.values.each do |value| -%> - if (cast->base.<%= field.name %> & PM_<%= found.human.upcase %>_<%= value.name %>) { + <%- field.values.each do |value| -%> + if (cast->base.flags & PM_<%= field.human.upcase %>_<%= value.name %>) { if (found) pm_buffer_append_byte(output_buffer, ','); pm_buffer_append_string(output_buffer, " <%= value.name.downcase %>", <%= value.name.bytesize + 1 %>); found = true; diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 97101e36d52..9f8f0cbd077 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -74,6 +74,9 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { size_t offset = buffer->length; + <%- unless Prism::Template::SERIALIZE_ONLY_SEMANTICS_FIELDS -%> + pm_buffer_append_varuint(buffer, node->node_id); + <%- end -%> pm_serialize_location(parser, &node->location, buffer); switch (PM_NODE_TYPE(node)) { @@ -89,6 +92,9 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { size_t length_offset = buffer->length; pm_buffer_append_string(buffer, "\0\0\0\0", 4); /* consume 4 bytes, updated below */ <%- end -%> + <%- unless Prism::Template::SERIALIZE_ONLY_SEMANTICS_FIELDS && !node.flags -%> + pm_buffer_append_varuint(buffer, (uint32_t) node->flags); + <%- end -%> <%- node.fields.each do |field| -%> <%- case field -%> <%- when Prism::Template::NodeField -%> @@ -132,8 +138,6 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { pm_buffer_append_byte(buffer, ((pm_<%= node.human %>_t *)node)-><%= field.name %>); <%- when Prism::Template::UInt32Field -%> pm_buffer_append_varuint(buffer, ((pm_<%= node.human %>_t *)node)-><%= field.name %>); - <%- when Prism::Template::FlagsField -%> - pm_buffer_append_varuint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); <%- when Prism::Template::IntegerField -%> pm_serialize_integer(&((pm_<%= node.human %>_t *)node)-><%= field.name %>, buffer); <%- when Prism::Template::DoubleField -%> @@ -267,7 +271,7 @@ pm_serialize_metadata(pm_parser_t *parser, pm_buffer_t *buffer) { pm_serialize_diagnostic_list(parser, &parser->warning_list, buffer); } -#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" +#line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" /** * Serialize the metadata, nodes, and constant pool. */ diff --git a/templates/src/token_type.c.erb b/templates/src/token_type.c.erb index 0587fc6cdf0..f196393ee12 100644 --- a/templates/src/token_type.c.erb +++ b/templates/src/token_type.c.erb @@ -30,7 +30,7 @@ const char * pm_token_type_human(pm_token_type_t token_type) { switch (token_type) { case PM_TOKEN_EOF: - return "end of file"; + return "end-of-input"; case PM_TOKEN_MISSING: return "missing token"; case PM_TOKEN_NOT_PROVIDED: @@ -90,9 +90,9 @@ pm_token_type_human(pm_token_type_t token_type) { case PM_TOKEN_DOT: return "'.'"; case PM_TOKEN_DOT_DOT: - return "'..'"; + return ".."; case PM_TOKEN_DOT_DOT_DOT: - return "'...'"; + return "..."; case PM_TOKEN_EMBDOC_BEGIN: return "'=begin'"; case PM_TOKEN_EMBDOC_END: @@ -352,7 +352,7 @@ pm_token_type_human(pm_token_type_t token_type) { case PM_TOKEN_USTAR: return "*"; case PM_TOKEN_USTAR_STAR: - return "'**'"; + return "**"; case PM_TOKEN_WORDS_SEP: return "string separator"; case PM_TOKEN___END__: diff --git a/templates/template.rb b/templates/template.rb index 6f79a853712..7068c098d31 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# typed: false +# typed: ignore require "erb" require "fileutils" @@ -8,11 +8,14 @@ module Prism module Template SERIALIZE_ONLY_SEMANTICS_FIELDS = ENV.fetch("PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS", false) + REMOVE_ON_ERROR_TYPES = SERIALIZE_ONLY_SEMANTICS_FIELDS CHECK_FIELD_KIND = ENV.fetch("CHECK_FIELD_KIND", false) JAVA_BACKEND = ENV["PRISM_JAVA_BACKEND"] || "truffleruby" JAVA_STRING_TYPE = JAVA_BACKEND == "jruby" ? "org.jruby.RubySymbol" : "String" + COMMON_FLAGS_COUNT = 2 + class Error attr_reader :name @@ -93,6 +96,11 @@ def should_be_serialized? # Some node fields can be specialized if they point to a specific kind of # node and not just a generic node. class NodeKindField < Field + def initialize(kind:, **options) + @kind = kind + super(**options) + end + def c_type if specific_kind "pm_#{specific_kind.gsub(/(?<=.)[A-Z]/, "_\\0").downcase}" @@ -111,18 +119,18 @@ def java_type def java_cast if specific_kind - "(Nodes.#{options[:kind]}) " + "(Nodes.#{@kind}) " else "" end end def specific_kind - options[:kind] unless options[:kind].is_a?(Array) + @kind unless @kind.is_a?(Array) end def union_kind - options[:kind] if options[:kind].is_a?(Array) + @kind if @kind.is_a?(Array) end end @@ -357,27 +365,6 @@ def java_type end end - # This represents a set of flags. It is very similar to the UInt32Field, but - # can be directly embedded into the flags field on the struct and provides - # convenient methods for checking if a flag is set. - class FlagsField < Field - def rbs_class - "Integer" - end - - def rbi_class - "Integer" - end - - def java_type - "short" - end - - def kind - options.fetch(:kind) - end - end - # This represents an arbitrarily-sized integer. When it gets to Ruby it will # be an Integer. class IntegerField < Field @@ -414,9 +401,9 @@ def java_type # in YAML format. It contains information about the name of the node and the # various child nodes it contains. class NodeType - attr_reader :name, :type, :human, :fields, :newline, :comment + attr_reader :name, :type, :human, :flags, :fields, :newline, :comment - def initialize(config) + def initialize(config, flags) @name = config.fetch("name") type = @name.gsub(/(?<=.)[A-Z]/, "_\\0") @@ -430,13 +417,42 @@ def initialize(config) options = field.transform_keys(&:to_sym) options.delete(:type) - # If/when we have documentation on every field, this should be changed - # to use fetch instead of delete. + # If/when we have documentation on every field, this should be + # changed to use fetch instead of delete. comment = options.delete(:comment) + if kinds = options[:kind] + kinds = [kinds] unless kinds.is_a?(Array) + kinds = kinds.map do |kind| + case kind + when "non-void expression" + # the actual list of types would be way too long + "Node" + when "pattern expression" + # the list of all possible types is too long with 37+ different classes + "Node" + when Hash + kind = kind.fetch("on error") + REMOVE_ON_ERROR_TYPES ? nil : kind + else + kind + end + end.compact + if kinds.size == 1 + kinds = kinds.first + kinds = nil if kinds == "Node" + end + options[:kind] = kinds + else + if type < NodeKindField + raise "Missing kind in config.yml for field #{@name}##{options.fetch(:name)}" + end + end + type.new(comment: comment, **options) end + @flags = config.key?("flags") ? flags.fetch(config.fetch("flags")) : nil @newline = config.fetch("newline", true) @comment = config.fetch("comment") end @@ -474,7 +490,6 @@ def field_type_for(name) when "location?" then OptionalLocationField when "uint8" then UInt8Field when "uint32" then UInt32Field - when "flags" then FlagsField when "integer" then IntegerField when "double" then DoubleField else raise("Unknown field type: #{name.inspect}") @@ -514,6 +529,10 @@ def initialize(config) @values = config.fetch("values").map { |flag| Flag.new(flag) } @comment = config.fetch("comment") end + + def self.empty + new("name" => "", "values" => [], "comment" => "") + end end class << self @@ -559,13 +578,13 @@ def render(name, write_to: nil) HEADING else <<~HEADING - /******************************************************************************/ + /*----------------------------------------------------------------------------*/ /* This file is generated by the templates/template.rb script and should not */ /* be modified manually. See */ /* #{filepath + " " * (74 - filepath.size) } */ /* if you are looking to modify the */ /* template */ - /******************************************************************************/ + /*----------------------------------------------------------------------------*/ HEADING end @@ -603,13 +622,14 @@ def locals @locals ||= begin config = YAML.load_file(File.expand_path("../config.yml", __dir__)) + flags = config.fetch("flags").to_h { |flags| [flags["name"], Flags.new(flags)] } { errors: config.fetch("errors").map { |name| Error.new(name) }, warnings: config.fetch("warnings").map { |name| Warning.new(name) }, - nodes: config.fetch("nodes").map { |node| NodeType.new(node) }.sort_by(&:name), + nodes: config.fetch("nodes").map { |node| NodeType.new(node, flags) }.sort_by(&:name), tokens: config.fetch("tokens").map { |token| Token.new(token) }, - flags: config.fetch("flags").map { |flags| Flags.new(flags) } + flags: flags.values } end end @@ -640,6 +660,7 @@ def locals "src/prettyprint.c", "src/serialize.c", "src/token_type.c", + "rbi/prism/dsl.rbi", "rbi/prism/node.rbi", "rbi/prism/visitor.rbi", "sig/prism.rbs", diff --git a/test/prism/command_line_test.rb b/test/prism/api/command_line_test.rb similarity index 87% rename from test/prism/command_line_test.rb rename to test/prism/api/command_line_test.rb index 4b04c36f3aa..e53d18703a4 100644 --- a/test/prism/command_line_test.rb +++ b/test/prism/api/command_line_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "test_helper" +require_relative "../test_helper" module Prism class CommandLineTest < TestCase @@ -52,6 +52,9 @@ def test_command_line_l assert_kind_of CallNode, predicate assert_equal :gets, predicate.name + arguments = predicate.arguments + assert arguments.contains_keywords? + arguments = predicate.arguments.arguments assert_equal 2, arguments.length assert_equal :$/, arguments.first.name @@ -67,7 +70,7 @@ def test_command_line_e end def test_command_line_x_implicit - result = Prism.parse(<<~RUBY) + result = Prism.parse_statement(<<~RUBY, main_script: true) #!/bin/bash exit 1 @@ -75,22 +78,22 @@ def test_command_line_x_implicit 1 RUBY - assert_kind_of IntegerNode, result.value.statements.body.first + assert_kind_of IntegerNode, result end def test_command_line_x_explicit - result = Prism.parse(<<~RUBY, command_line: "x") + result = Prism.parse_statement(<<~RUBY, command_line: "x") exit 1 #!/usr/bin/env ruby 1 RUBY - assert_kind_of IntegerNode, result.value.statements.body.first + assert_kind_of IntegerNode, result end def test_command_line_x_implicit_fail - result = Prism.parse(<<~RUBY) + result = Prism.parse(<<~RUBY, main_script: true) #!/bin/bash exit 1 RUBY diff --git a/test/prism/api/dump_test.rb b/test/prism/api/dump_test.rb new file mode 100644 index 00000000000..941088e1592 --- /dev/null +++ b/test/prism/api/dump_test.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +return if ENV["PRISM_BUILD_MINIMAL"] + +require_relative "../test_helper" + +module Prism + class DumpTest < TestCase + Fixture.each do |fixture| + define_method(fixture.test_name) { assert_dump(fixture) } + end + + def test_dump + filepath = __FILE__ + source = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8) + + assert_equal Prism.lex(source, filepath: filepath).value, Prism.lex_file(filepath).value + assert_equal Prism.dump(source, filepath: filepath), Prism.dump_file(filepath) + + serialized = Prism.dump(source, filepath: filepath) + ast1 = Prism.load(source, serialized).value + ast2 = Prism.parse(source, filepath: filepath).value + ast3 = Prism.parse_file(filepath).value + + assert_equal_nodes ast1, ast2 + assert_equal_nodes ast2, ast3 + end + + def test_dump_file + assert_nothing_raised do + Prism.dump_file(__FILE__) + end + + error = assert_raise Errno::ENOENT do + Prism.dump_file("idontexist.rb") + end + + assert_equal "No such file or directory - idontexist.rb", error.message + + assert_raise TypeError do + Prism.dump_file(nil) + end + end + + private + + def assert_dump(fixture) + source = fixture.read + + result = Prism.parse(source, filepath: fixture.path) + dumped = Prism.dump(source, filepath: fixture.path) + + assert_equal_nodes(result.value, Prism.load(source, dumped).value) + end + end +end diff --git a/test/prism/api/lex_test.rb b/test/prism/api/lex_test.rb new file mode 100644 index 00000000000..0b675b215f3 --- /dev/null +++ b/test/prism/api/lex_test.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class LexTest < TestCase + def test_lex_result + result = Prism.lex("") + assert_kind_of LexResult, result + + result = Prism.lex_file(__FILE__) + assert_kind_of LexResult, result + end + + def test_parse_lex_result + result = Prism.parse_lex("") + assert_kind_of ParseLexResult, result + + result = Prism.parse_lex_file(__FILE__) + assert_kind_of ParseLexResult, result + end + end +end diff --git a/test/prism/parse_comments_test.rb b/test/prism/api/parse_comments_test.rb similarity index 54% rename from test/prism/parse_comments_test.rb rename to test/prism/api/parse_comments_test.rb index 30086e31552..4dbcca1827f 100644 --- a/test/prism/parse_comments_test.rb +++ b/test/prism/api/parse_comments_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "test_helper" +require_relative "../test_helper" module Prism class ParseCommentsTest < TestCase @@ -17,5 +17,17 @@ def test_parse_file_comments assert_kind_of Array, comments assert_equal 1, comments.length end + + def test_parse_file_comments_error + error = assert_raise Errno::ENOENT do + Prism.parse_file_comments("idontexist.rb") + end + + assert_equal "No such file or directory - idontexist.rb", error.message + + assert_raise TypeError do + Prism.parse_file_comments(nil) + end + end end end diff --git a/test/prism/parse_stream_test.rb b/test/prism/api/parse_stream_test.rb similarity index 78% rename from test/prism/parse_stream_test.rb rename to test/prism/api/parse_stream_test.rb index 9e6347b92b0..1c068c617c4 100644 --- a/test/prism/parse_stream_test.rb +++ b/test/prism/api/parse_stream_test.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true -require_relative "test_helper" -require "stringio" +require_relative "../test_helper" module Prism class ParseStreamTest < TestCase @@ -10,7 +9,7 @@ def test_single_line result = Prism.parse_stream(io) assert result.success? - assert_kind_of Prism::CallNode, result.value.statements.body.first + assert_kind_of Prism::CallNode, result.statement end def test_multi_line @@ -18,8 +17,8 @@ def test_multi_line result = Prism.parse_stream(io) assert result.success? - assert_kind_of Prism::CallNode, result.value.statements.body.first - assert_kind_of Prism::CallNode, result.value.statements.body.last + assert_kind_of Prism::CallNode, result.statement + assert_kind_of Prism::CallNode, result.statement end def test_multi_read @@ -27,7 +26,7 @@ def test_multi_read result = Prism.parse_stream(io) assert result.success? - assert_kind_of Prism::CallNode, result.value.statements.body.first + assert_kind_of Prism::CallNode, result.statement end def test___END__ @@ -70,5 +69,13 @@ def test_false___END___in_heredoc assert result.success? assert_equal 4, result.value.statements.body.length end + + def test_nul_bytes + io = StringIO.new("1 # \0\0\0 \n2 # \0\0\0\n3") + result = Prism.parse_stream(io) + + assert result.success? + assert_equal 3, result.value.statements.body.length + end end end diff --git a/test/prism/api/parse_success_test.rb b/test/prism/api/parse_success_test.rb new file mode 100644 index 00000000000..2caaa5136e2 --- /dev/null +++ b/test/prism/api/parse_success_test.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class ParseSuccessTest < TestCase + def test_parse_success? + assert Prism.parse_success?("1") + refute Prism.parse_success?("<>") + end + + def test_parse_file_success? + assert Prism.parse_file_success?(__FILE__) + end + end +end diff --git a/test/prism/api/parse_test.rb b/test/prism/api/parse_test.rb new file mode 100644 index 00000000000..ee8061c98c5 --- /dev/null +++ b/test/prism/api/parse_test.rb @@ -0,0 +1,150 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class ParseTest < TestCase + def test_parse_result + result = Prism.parse("") + assert_kind_of ParseResult, result + + result = Prism.parse_file(__FILE__) + assert_kind_of ParseResult, result + end + + def test_parse_empty_string + result = Prism.parse("") + assert_equal [], result.value.statements.body + end + + def test_parse_takes_file_path + filepath = "filepath.rb" + result = Prism.parse("def foo; __FILE__; end", filepath: filepath) + + assert_equal filepath, find_source_file_node(result.value).filepath + end + + def test_parse_takes_line + line = 4 + result = Prism.parse("def foo\n __FILE__\nend", line: line) + + assert_equal line, result.value.location.start_line + assert_equal line + 1, find_source_file_node(result.value).location.start_line + + result = Prism.parse_lex("def foo\n __FILE__\nend", line: line) + assert_equal line, result.value.first.location.start_line + end + + def test_parse_takes_negative_lines + line = -2 + result = Prism.parse("def foo\n __FILE__\nend", line: line) + + assert_equal line, result.value.location.start_line + assert_equal line + 1, find_source_file_node(result.value).location.start_line + + result = Prism.parse_lex("def foo\n __FILE__\nend", line: line) + assert_equal line, result.value.first.location.start_line + end + + def test_parse_file + node = Prism.parse_file(__FILE__).value + assert_kind_of ProgramNode, node + + error = assert_raise Errno::ENOENT do + Prism.parse_file("idontexist.rb") + end + + assert_equal "No such file or directory - idontexist.rb", error.message + + assert_raise TypeError do + Prism.parse_file(nil) + end + end + + def test_parse_tempfile + Tempfile.create(["test_parse_tempfile", ".rb"]) do |t| + t.puts ["begin\n", " end\n"] + t.flush + Prism.parse_file(t.path) + end + end + + if RUBY_ENGINE != "truffleruby" + def test_parse_nonascii + Dir.mktmpdir do |dir| + path = File.join(dir, "\u{3042 3044 3046 3048 304a}.rb".encode(Encoding::Windows_31J)) + File.write(path, "ok") + Prism.parse_file(path) + end + end + end + + def test_parse_directory + error = nil + + begin + Prism.parse_file(__dir__) + rescue SystemCallError => error + end + + assert_kind_of Errno::EISDIR, error + end + + def test_partial_script + assert Prism.parse_failure?("break") + assert Prism.parse_success?("break", partial_script: true) + + assert Prism.parse_failure?("next") + assert Prism.parse_success?("next", partial_script: true) + + assert Prism.parse_failure?("redo") + assert Prism.parse_success?("redo", partial_script: true) + + assert Prism.parse_failure?("yield") + assert Prism.parse_success?("yield", partial_script: true) + end + + def test_version + assert Prism.parse_success?("1 + 1", version: "3.3") + assert Prism.parse_success?("1 + 1", version: "3.3.0") + assert Prism.parse_success?("1 + 1", version: "3.3.1") + assert Prism.parse_success?("1 + 1", version: "3.3.9") + assert Prism.parse_success?("1 + 1", version: "3.3.10") + + assert Prism.parse_success?("1 + 1", version: "3.4") + assert Prism.parse_success?("1 + 1", version: "3.4.0") + assert Prism.parse_success?("1 + 1", version: "3.4.9") + assert Prism.parse_success?("1 + 1", version: "3.4.10") + + assert Prism.parse_success?("1 + 1", version: "latest") + + # Test edge case + error = assert_raise(ArgumentError) { Prism.parse("1 + 1", version: "latest2") } + assert_equal "invalid version: latest2", error.message + + assert_raise ArgumentError do + Prism.parse("1 + 1", version: "3.3.a") + end + + # Not supported version (too old) + assert_raise ArgumentError do + Prism.parse("1 + 1", version: "3.2.0") + end + + # Not supported version (too new) + assert_raise ArgumentError do + Prism.parse("1 + 1", version: "3.5.0") + end + end + + private + + def find_source_file_node(program) + queue = [program] + while (node = queue.shift) + return node if node.is_a?(SourceFileNode) + queue.concat(node.compact_child_nodes) + end + end + end +end diff --git a/test/prism/bom_test.rb b/test/prism/bom_test.rb index 1525caf458d..890bc4b36c3 100644 --- a/test/prism/bom_test.rb +++ b/test/prism/bom_test.rb @@ -2,7 +2,7 @@ # Don't bother checking this on these engines, this is such a specific Ripper # test. -return if RUBY_ENGINE == "jruby" || RUBY_ENGINE == "truffleruby" +return if RUBY_ENGINE != "ruby" require_relative "test_helper" diff --git a/test/prism/encoding/encodings_test.rb b/test/prism/encoding/encodings_test.rb new file mode 100644 index 00000000000..4ad2b465cc1 --- /dev/null +++ b/test/prism/encoding/encodings_test.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +return if RUBY_ENGINE != "ruby" + +require_relative "../test_helper" + +module Prism + class EncodingsTest < TestCase + class ConstantContext < BasicObject + def self.const_missing(const) + const + end + end + + class IdentifierContext < BasicObject + def method_missing(name, *) + name + end + end + + # These test that we're correctly parsing codepoints for each alias of each + # encoding that prism supports. + each_encoding do |encoding, range| + (encoding.names - %w[external internal filesystem locale]).each do |name| + define_method(:"test_encoding_#{name}") do + assert_encoding(encoding, name, range) + end + end + end + + private + + def assert_encoding_constant(name, character) + source = "# encoding: #{name}\n#{character}" + expected = ConstantContext.new.instance_eval(source) + + result = Prism.parse(source) + assert result.success? + + actual = result.value.statements.body.last + assert_kind_of ConstantReadNode, actual + assert_equal expected, actual.name + end + + def assert_encoding_identifier(name, character) + source = "# encoding: #{name}\n#{character}" + expected = IdentifierContext.new.instance_eval(source) + + result = Prism.parse(source) + assert result.success? + + actual = result.value.statements.body.last + assert_kind_of CallNode, actual + assert_equal expected, actual.name + end + + # Check that we can properly parse every codepoint in the given encoding. + def assert_encoding(encoding, name, range) + # I'm not entirely sure, but I believe these codepoints are incorrect in + # their parsing in CRuby. They all report as matching `[[:lower:]]` but + # then they are parsed as constants. This is because CRuby determines if + # an identifier is a constant or not by case folding it down to lowercase + # and checking if there is a difference. And even though they report + # themselves as lowercase, their case fold is different. I have reported + # this bug upstream. + case encoding + when Encoding::UTF_8, Encoding::UTF_8_MAC, Encoding::UTF8_DoCoMo, Encoding::UTF8_KDDI, Encoding::UTF8_SoftBank, Encoding::CESU_8 + range = range.to_a - [ + 0x01c5, 0x01c8, 0x01cb, 0x01f2, 0x1f88, 0x1f89, 0x1f8a, 0x1f8b, + 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, 0x1f98, 0x1f99, 0x1f9a, 0x1f9b, + 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, 0x1fa8, 0x1fa9, 0x1faa, 0x1fab, + 0x1fac, 0x1fad, 0x1fae, 0x1faf, 0x1fbc, 0x1fcc, 0x1ffc, + ] + when Encoding::Windows_1253 + range = range.to_a - [0xb5] + end + + range.each do |codepoint| + character = codepoint.chr(encoding) + + if character.match?(/[[:alpha:]]/) + if character.match?(/[[:upper:]]/) + assert_encoding_constant(name, character) + else + assert_encoding_identifier(name, character) + end + elsif character.match?(/[[:alnum:]]/) + assert_encoding_identifier(name, "_#{character}") + else + next if ["/", "{"].include?(character) + + source = "# encoding: #{name}\n/(?##{character})/\n" + assert Prism.parse_success?(source), "Expected #{source.inspect} to parse successfully." + end + rescue RangeError + source = "# encoding: #{name}\n\\x#{codepoint.to_s(16)}" + assert Prism.parse_failure?(source) + end + end + end +end diff --git a/test/prism/encoding/regular_expression_encoding_test.rb b/test/prism/encoding/regular_expression_encoding_test.rb new file mode 100644 index 00000000000..5d062fe59a2 --- /dev/null +++ b/test/prism/encoding/regular_expression_encoding_test.rb @@ -0,0 +1,131 @@ +# frozen_string_literal: true + +return unless defined?(RubyVM::InstructionSequence) +return if RubyVM::InstructionSequence.compile("").to_a[4][:parser] == :prism + +require_relative "../test_helper" + +module Prism + class RegularExpressionEncodingTest < TestCase + each_encoding do |encoding, _| + define_method(:"test_regular_expression_encoding_flags_#{encoding.name}") do + assert_regular_expression_encoding_flags(encoding, ["/a/", "/ą/", "//"]) + end + + escapes = ["\\x00", "\\x7F", "\\x80", "\\xFF", "\\u{00}", "\\u{7F}", "\\u{80}", "\\M-\\C-?"] + escapes = escapes.concat(escapes.product(escapes).map(&:join)) + + define_method(:"test_regular_expression_escape_encoding_flags_#{encoding.name}") do + assert_regular_expression_encoding_flags(encoding, escapes.map { |e| "/#{e}/" }) + end + + ["n", "u", "e", "s"].each do |modifier| + define_method(:"test_regular_expression_encoding_modifiers_/#{modifier}_#{encoding.name}") do + regexp_sources = ["abc", "garçon", "\\x80", "gar\\xC3\\xA7on", "gar\\u{E7}on", "abc\\u{FFFFFF}", "\\x80\\u{80}" ] + + assert_regular_expression_encoding_flags( + encoding, + regexp_sources.product(["n", "u", "e", "s"]).map { |r, modifier| "/#{r}/#{modifier}" } + ) + end + end + end + + private + + def assert_regular_expression_encoding_flags(encoding, regexps) + regexps.each do |regexp| + regexp_modifier_used = regexp.end_with?("/u") || regexp.end_with?("/e") || regexp.end_with?("/s") || regexp.end_with?("/n") + source = "# encoding: #{encoding.name}\n#{regexp}" + + encoding_errors = ["invalid multibyte char", "escaped non ASCII character in UTF-8 regexp", "differs from source encoding"] + skipped_errors = ["invalid multibyte escape", "incompatible character encoding", "UTF-8 character in non UTF-8 regexp", "invalid Unicode range", "invalid Unicode list"] + + # TODO (nirvdrum 21-Feb-2024): Prism currently does not handle Regexp validation unless modifiers are used. So, skip processing those errors for now: https://github.com/ruby/prism/issues/2104 + unless regexp_modifier_used + skipped_errors += encoding_errors + encoding_errors.clear + end + + expected = + begin + eval(source).encoding + rescue SyntaxError => error + if encoding_errors.find { |e| error.message.include?(e) } + error.message.split("\n").map { |m| m[/: (.+?)$/, 1] } + elsif skipped_errors.find { |e| error.message.include?(e) } + next + else + raise + end + end + + actual = + Prism.parse(source).then do |result| + if result.success? + regexp = result.statement + + actual_encoding = if regexp.forced_utf8_encoding? + Encoding::UTF_8 + elsif regexp.forced_binary_encoding? + Encoding::ASCII_8BIT + elsif regexp.forced_us_ascii_encoding? + Encoding::US_ASCII + elsif regexp.ascii_8bit? + Encoding::ASCII_8BIT + elsif regexp.utf_8? + Encoding::UTF_8 + elsif regexp.euc_jp? + Encoding::EUC_JP + elsif regexp.windows_31j? + Encoding::Windows_31J + else + encoding + end + + if regexp.utf_8? && actual_encoding != Encoding::UTF_8 + raise "expected regexp encoding to be UTF-8 due to '/u' modifier, but got #{actual_encoding.name}" + elsif regexp.ascii_8bit? && (actual_encoding != Encoding::ASCII_8BIT && actual_encoding != Encoding::US_ASCII) + raise "expected regexp encoding to be ASCII-8BIT or US-ASCII due to '/n' modifier, but got #{actual_encoding.name}" + elsif regexp.euc_jp? && actual_encoding != Encoding::EUC_JP + raise "expected regexp encoding to be EUC-JP due to '/e' modifier, but got #{actual_encoding.name}" + elsif regexp.windows_31j? && actual_encoding != Encoding::Windows_31J + raise "expected regexp encoding to be Windows-31J due to '/s' modifier, but got #{actual_encoding.name}" + end + + if regexp.utf_8? && regexp.forced_utf8_encoding? + raise "the forced_utf8 flag should not be set when the UTF-8 modifier (/u) is used" + elsif regexp.ascii_8bit? && regexp.forced_binary_encoding? + raise "the forced_ascii_8bit flag should not be set when the UTF-8 modifier (/u) is used" + end + + actual_encoding + else + errors = result.errors.map(&:message) + + if errors.last&.include?("UTF-8 mixed within") + nil + else + errors + end + end + end + + # TODO (nirvdrum 22-Feb-2024): Remove this workaround once Prism better maps CRuby's error messages. + # This class of error message is tricky. The part not being compared is a representation of the regexp. + # Depending on the source encoding and any encoding modifiers being used, CRuby alters how the regexp is represented. + # Sometimes it's an MBC string. Other times it uses hexadecimal character escapes. And in other cases it uses + # the long-form Unicode escape sequences. This short-circuit checks that the error message is mostly correct. + if expected.is_a?(Array) && actual.is_a?(Array) + if expected.last.start_with?("/.../n has a non escaped non ASCII character in non ASCII-8BIT script:") && + actual.last.start_with?("/.../n has a non escaped non ASCII character in non ASCII-8BIT script:") + expected.last.clear + actual.last.clear + end + end + + assert_equal expected, actual + end + end + end +end diff --git a/test/prism/encoding/string_encoding_test.rb b/test/prism/encoding/string_encoding_test.rb new file mode 100644 index 00000000000..6f9d86df3be --- /dev/null +++ b/test/prism/encoding/string_encoding_test.rb @@ -0,0 +1,136 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class StringEncodingTest < TestCase + each_encoding do |encoding, _| + define_method(:"test_#{encoding.name}") do + assert_encoding(encoding) + end + end + + def test_coding + actual = Prism.parse_statement("# coding: utf-8\n'string'").unescaped.encoding + assert_equal Encoding::UTF_8, actual + end + + def test_coding_with_whitespace + actual = Prism.parse_statement("# coding \t \r \v : \t \v \r ascii-8bit \n'string'").unescaped.encoding + assert_equal Encoding::ASCII_8BIT, actual + end + + def test_emacs_style + actual = Prism.parse_statement("# -*- coding: utf-8 -*-\n'string'").unescaped.encoding + assert_equal Encoding::UTF_8, actual + end + + def test_utf_8_unix + actual = Prism.parse_statement("# coding: utf-8-unix\n'string'").unescaped.encoding + assert_equal Encoding::UTF_8, actual + end + + def test_utf_8_dos + actual = Prism.parse_statement("# coding: utf-8-dos\n'string'").unescaped.encoding + assert_equal Encoding::UTF_8, actual + end + + def test_utf_8_mac + actual = Prism.parse_statement("# coding: utf-8-mac\n'string'").unescaped.encoding + assert_equal Encoding::UTF_8, actual + end + + def test_utf_8_star + actual = Prism.parse_statement("# coding: utf-8-*\n'string'").unescaped.encoding + assert_equal Encoding::UTF_8, actual + end + + def test_first_lexed_token + encoding = Prism.lex("# encoding: ascii-8bit").value[0][0].value.encoding + assert_equal Encoding::ASCII_8BIT, encoding + end + + if !ENV["PRISM_BUILD_MINIMAL"] + # This test may be a little confusing. Basically when we use our strpbrk, + # it takes into account the encoding of the file. + def test_strpbrk_multibyte + result = Prism.parse(<<~RUBY) + # encoding: Shift_JIS + %w[\x81\x5c] + RUBY + + assert(result.errors.empty?) + assert_equal( + (+"\x81\x5c").force_encoding(Encoding::Shift_JIS), + result.statement.elements.first.unescaped + ) + end + + def test_slice_encoding + slice = Prism.parse("# encoding: Shift_JIS\nア").value.slice + assert_equal (+"ア").force_encoding(Encoding::SHIFT_JIS), slice + assert_equal Encoding::SHIFT_JIS, slice.encoding + end + + def test_multibyte_escapes + [ + ["'", "'"], + ["\"", "\""], + ["`", "`"], + ["/", "/"], + ["<<'HERE'\n", "\nHERE"], + ["<<-HERE\n", "\nHERE"] + ].each do |opening, closing| + assert Prism.parse_success?("# encoding: shift_jis\n'\\\x82\xA0'\n") + end + end + end + + private + + def assert_encoding(encoding) + escapes = ["\\x00", "\\x7F", "\\x80", "\\xFF", "\\u{00}", "\\u{7F}", "\\u{80}", "\\M-\\C-?"] + escapes = escapes.concat(escapes.product(escapes).map(&:join)) + + escapes.each do |escaped| + source = "# encoding: #{encoding.name}\n\"#{escaped}\"" + + expected = + begin + eval(source).encoding + rescue SyntaxError => error + if error.message.include?("UTF-8 mixed within") + error.message[/UTF-8 mixed within .+? source/] + else + raise + end + end + + actual = + Prism.parse(source).then do |result| + if result.success? + string = result.statement + + if string.forced_utf8_encoding? + Encoding::UTF_8 + elsif string.forced_binary_encoding? + Encoding::ASCII_8BIT + else + encoding + end + else + error = result.errors.first + + if error.message.include?("mixed") + error.message + else + raise error.message + end + end + end + + assert_equal expected, actual + end + end + end +end diff --git a/test/prism/encoding/symbol_encoding_test.rb b/test/prism/encoding/symbol_encoding_test.rb new file mode 100644 index 00000000000..20c998a58bb --- /dev/null +++ b/test/prism/encoding/symbol_encoding_test.rb @@ -0,0 +1,108 @@ +# frozen_string_literal: true + +return if RUBY_ENGINE != "ruby" + +require_relative "../test_helper" + +module Prism + class SymbolEncodingTest < TestCase + each_encoding do |encoding, _| + define_method(:"test_symbols_#{encoding.name}") do + assert_symbols(encoding) + end + + define_method(:"test_escapes_#{encoding.name}") do + assert_escapes(encoding) + end + end + + private + + def expected_encoding(source) + eval(source).encoding + end + + def actual_encoding(source, encoding) + result = Prism.parse(source) + + if result.success? + symbol = result.statement + + if symbol.forced_utf8_encoding? + Encoding::UTF_8 + elsif symbol.forced_binary_encoding? + Encoding::ASCII_8BIT + elsif symbol.forced_us_ascii_encoding? + Encoding::US_ASCII + else + encoding + end + else + raise SyntaxError.new(result.errors.map(&:message).join("\n")) + end + end + + def assert_symbols(encoding) + [:a, :ą, :+].each do |symbol| + source = "# encoding: #{encoding.name}\n#{symbol.inspect}" + + expected = + begin + expected_encoding(source) + rescue SyntaxError => error + if error.message.include?("invalid multibyte") + "invalid multibyte" + else + raise + end + end + + actual = + begin + actual_encoding(source, encoding) + rescue SyntaxError => error + if error.message.include?("invalid multibyte") + "invalid multibyte" + else + raise + end + end + + assert_equal expected, actual + end + end + + def assert_escapes(encoding) + escapes = ["\\x00", "\\x7F", "\\x80", "\\xFF", "\\u{00}", "\\u{7F}", "\\u{80}", "\\M-\\C-?"] + escapes = escapes.concat(escapes.product(escapes).map(&:join)) + + escapes.each do |escaped| + source = "# encoding: #{encoding.name}\n:\"#{escaped}\"" + + expected = + begin + expected_encoding(source) + rescue SyntaxError => error + if error.message.include?("UTF-8 mixed within") + error.message[/UTF-8 mixed within .+? source/] + else + raise + end + end + + actual = + begin + actual_encoding(source, encoding) + rescue SyntaxError => error + if error.message.include?("mixed") + error.message.split("\n", 2).first + else + raise + end + end + + assert_equal expected, actual + end + end + end +end diff --git a/test/prism/encoding_test.rb b/test/prism/encoding_test.rb deleted file mode 100644 index 2aee473ddf9..00000000000 --- a/test/prism/encoding_test.rb +++ /dev/null @@ -1,577 +0,0 @@ -# frozen_string_literal: true - -return if RUBY_ENGINE != "ruby" - -require_relative "test_helper" - -module Prism - class EncodingTest < TestCase - codepoints_1byte = 0...0x100 - encodings = { - Encoding::ASCII_8BIT => codepoints_1byte, - Encoding::US_ASCII => codepoints_1byte - } - - if !ENV["PRISM_BUILD_MINIMAL"] - encodings[Encoding::Windows_1253] = codepoints_1byte - end - - # By default we don't test every codepoint in these encodings because it - # takes a very long time. - if ENV["PRISM_TEST_ALL_ENCODINGS"] - codepoints_2bytes = 0...0x10000 - codepoints_unicode = (0...0x110000) - - codepoints_eucjp = [ - *(0...0x10000), - *(0...0x10000).map { |bytes| bytes | 0x8F0000 } - ] - - codepoints_emacs_mule = [ - *(0...0x80), - *((0x81...0x90).flat_map { |byte1| (0x90...0x100).map { |byte2| byte1 << 8 | byte2 } }), - *((0x90...0x9C).flat_map { |byte1| (0xA0...0x100).flat_map { |byte2| (0xA0...0x100).flat_map { |byte3| byte1 << 16 | byte2 << 8 | byte3 } } }), - *((0xF0...0xF5).flat_map { |byte2| (0xA0...0x100).flat_map { |byte3| (0xA0...0x100).flat_map { |byte4| 0x9C << 24 | byte3 << 16 | byte3 << 8 | byte4 } } }), - ] - - codepoints_gb18030 = [ - *(0...0x80), - *((0x81..0xFE).flat_map { |byte1| (0x40...0x100).map { |byte2| byte1 << 8 | byte2 } }), - *((0x81..0xFE).flat_map { |byte1| (0x30...0x40).flat_map { |byte2| (0x81..0xFE).flat_map { |byte3| (0x2F...0x41).map { |byte4| byte1 << 24 | byte2 << 16 | byte3 << 8 | byte4 } } } }), - ] - - codepoints_euc_tw = [ - *(0..0x7F), - *(0xA1..0xFF).flat_map { |byte1| (0xA1..0xFF).map { |byte2| (byte1 << 8) | byte2 } }, - *(0xA1..0xB0).flat_map { |byte2| (0xA1..0xFF).flat_map { |byte3| (0xA1..0xFF).flat_map { |byte4| 0x8E << 24 | byte2 << 16 | byte3 << 8 | byte4 } } } - ] - - encodings.merge!( - Encoding::CP850 => codepoints_1byte, - Encoding::CP852 => codepoints_1byte, - Encoding::CP855 => codepoints_1byte, - Encoding::GB1988 => codepoints_1byte, - Encoding::IBM437 => codepoints_1byte, - Encoding::IBM720 => codepoints_1byte, - Encoding::IBM737 => codepoints_1byte, - Encoding::IBM775 => codepoints_1byte, - Encoding::IBM852 => codepoints_1byte, - Encoding::IBM855 => codepoints_1byte, - Encoding::IBM857 => codepoints_1byte, - Encoding::IBM860 => codepoints_1byte, - Encoding::IBM861 => codepoints_1byte, - Encoding::IBM862 => codepoints_1byte, - Encoding::IBM863 => codepoints_1byte, - Encoding::IBM864 => codepoints_1byte, - Encoding::IBM865 => codepoints_1byte, - Encoding::IBM866 => codepoints_1byte, - Encoding::IBM869 => codepoints_1byte, - Encoding::ISO_8859_1 => codepoints_1byte, - Encoding::ISO_8859_2 => codepoints_1byte, - Encoding::ISO_8859_3 => codepoints_1byte, - Encoding::ISO_8859_4 => codepoints_1byte, - Encoding::ISO_8859_5 => codepoints_1byte, - Encoding::ISO_8859_6 => codepoints_1byte, - Encoding::ISO_8859_7 => codepoints_1byte, - Encoding::ISO_8859_8 => codepoints_1byte, - Encoding::ISO_8859_9 => codepoints_1byte, - Encoding::ISO_8859_10 => codepoints_1byte, - Encoding::ISO_8859_11 => codepoints_1byte, - Encoding::ISO_8859_13 => codepoints_1byte, - Encoding::ISO_8859_14 => codepoints_1byte, - Encoding::ISO_8859_15 => codepoints_1byte, - Encoding::ISO_8859_16 => codepoints_1byte, - Encoding::KOI8_R => codepoints_1byte, - Encoding::KOI8_U => codepoints_1byte, - Encoding::MACCENTEURO => codepoints_1byte, - Encoding::MACCROATIAN => codepoints_1byte, - Encoding::MACCYRILLIC => codepoints_1byte, - Encoding::MACGREEK => codepoints_1byte, - Encoding::MACICELAND => codepoints_1byte, - Encoding::MACROMAN => codepoints_1byte, - Encoding::MACROMANIA => codepoints_1byte, - Encoding::MACTHAI => codepoints_1byte, - Encoding::MACTURKISH => codepoints_1byte, - Encoding::MACUKRAINE => codepoints_1byte, - Encoding::TIS_620 => codepoints_1byte, - Encoding::Windows_1250 => codepoints_1byte, - Encoding::Windows_1251 => codepoints_1byte, - Encoding::Windows_1252 => codepoints_1byte, - Encoding::Windows_1254 => codepoints_1byte, - Encoding::Windows_1255 => codepoints_1byte, - Encoding::Windows_1256 => codepoints_1byte, - Encoding::Windows_1257 => codepoints_1byte, - Encoding::Windows_1258 => codepoints_1byte, - Encoding::Windows_874 => codepoints_1byte, - Encoding::Big5 => codepoints_2bytes, - Encoding::Big5_HKSCS => codepoints_2bytes, - Encoding::Big5_UAO => codepoints_2bytes, - Encoding::CP949 => codepoints_2bytes, - Encoding::CP950 => codepoints_2bytes, - Encoding::CP951 => codepoints_2bytes, - Encoding::EUC_KR => codepoints_2bytes, - Encoding::GBK => codepoints_2bytes, - Encoding::GB12345 => codepoints_2bytes, - Encoding::GB2312 => codepoints_2bytes, - Encoding::MACJAPANESE => codepoints_2bytes, - Encoding::Shift_JIS => codepoints_2bytes, - Encoding::SJIS_DoCoMo => codepoints_2bytes, - Encoding::SJIS_KDDI => codepoints_2bytes, - Encoding::SJIS_SoftBank => codepoints_2bytes, - Encoding::Windows_31J => codepoints_2bytes, - Encoding::UTF_8 => codepoints_unicode, - Encoding::UTF8_MAC => codepoints_unicode, - Encoding::UTF8_DoCoMo => codepoints_unicode, - Encoding::UTF8_KDDI => codepoints_unicode, - Encoding::UTF8_SoftBank => codepoints_unicode, - Encoding::CESU_8 => codepoints_unicode, - Encoding::CP51932 => codepoints_eucjp, - Encoding::EUC_JP => codepoints_eucjp, - Encoding::EUCJP_MS => codepoints_eucjp, - Encoding::EUC_JIS_2004 => codepoints_eucjp, - Encoding::EMACS_MULE => codepoints_emacs_mule, - Encoding::STATELESS_ISO_2022_JP => codepoints_emacs_mule, - Encoding::STATELESS_ISO_2022_JP_KDDI => codepoints_emacs_mule, - Encoding::GB18030 => codepoints_gb18030, - Encoding::EUC_TW => codepoints_euc_tw - ) - end - - # These test that we're correctly parsing codepoints for each alias of each - # encoding that prism supports. - encodings.each do |encoding, range| - (encoding.names - %w[external internal filesystem locale]).each do |name| - define_method(:"test_encoding_#{name}") do - assert_encoding(encoding, name, range) - end - end - end - - # These test that we're correctly setting the flags on strings for each - # encoding that prism supports. - escapes = ["\\x00", "\\x7F", "\\x80", "\\xFF", "\\u{00}", "\\u{7F}", "\\u{80}", "\\M-\\C-?"] - escapes = escapes.concat(escapes.product(escapes).map(&:join)) - symbols = [:a, :ą, :+] - regexps = [/a/, /ą/, //] - - encodings.each_key do |encoding| - define_method(:"test_encoding_flags_#{encoding.name}") do - assert_encoding_flags(encoding, escapes) - end - - define_method(:"test_symbol_encoding_flags_#{encoding.name}") do - assert_symbol_encoding_flags(encoding, symbols) - end - - define_method(:"test_symbol_character_escape_encoding_flags_#{encoding.name}") do - assert_symbol_character_escape_encoding_flags(encoding, escapes) - end - - define_method(:"test_regular_expression_encoding_flags_#{encoding.name}") do - assert_regular_expression_encoding_flags(encoding, regexps.map(&:inspect)) - end - - define_method(:"test_regular_expression_escape_encoding_flags_#{encoding.name}") do - assert_regular_expression_encoding_flags(encoding, escapes.map { |e| "/#{e}/" }) - end - end - - encoding_modifiers = { ascii_8bit: "n", utf_8: "u", euc_jp: "e", windows_31j: "s" } - regexp_sources = ["abc", "garçon", "\\x80", "gar\\xC3\\xA7on", "gar\\u{E7}on", "abc\\u{FFFFFF}", "\\x80\\u{80}" ] - - encoding_modifiers.each_value do |modifier| - encodings.each_key do |encoding| - define_method(:"test_regular_expression_encoding_modifiers_/#{modifier}_#{encoding.name}") do - assert_regular_expression_encoding_flags( - encoding, - regexp_sources.product(encoding_modifiers.values).map { |r, modifier| "/#{r}/#{modifier}" } - ) - end - end - end - - def test_coding - result = Prism.parse("# coding: utf-8\n'string'") - actual = result.value.statements.body.first.unescaped.encoding - assert_equal Encoding.find("utf-8"), actual - end - - def test_coding_with_whitespace - result = Prism.parse("# coding \t \r \v : \t \v \r ascii-8bit \n'string'") - actual = result.value.statements.body.first.unescaped.encoding - assert_equal Encoding.find("ascii-8bit"), actual - end - - def test_emacs_style - result = Prism.parse("# -*- coding: utf-8 -*-\n'string'") - actual = result.value.statements.body.first.unescaped.encoding - assert_equal Encoding.find("utf-8"), actual - end - - def test_utf_8_variations - %w[ - utf-8-unix - utf-8-dos - utf-8-mac - utf-8-* - ].each do |encoding| - result = Prism.parse("# coding: #{encoding}\n'string'") - actual = result.value.statements.body.first.unescaped.encoding - assert_equal Encoding.find("utf-8"), actual - end - end - - def test_first_lexed_token - encoding = Prism.lex("# encoding: ascii-8bit").value[0][0].value.encoding - assert_equal Encoding.find("ascii-8bit"), encoding - end - - if !ENV["PRISM_BUILD_MINIMAL"] - # This test may be a little confusing. Basically when we use our strpbrk, - # it takes into account the encoding of the file. - def test_strpbrk_multibyte - result = Prism.parse(<<~RUBY) - # encoding: Shift_JIS - %w[\x81\x5c] - RUBY - - assert(result.errors.empty?) - assert_equal( - (+"\x81\x5c").force_encoding(Encoding::Shift_JIS), - result.value.statements.body.first.elements.first.unescaped - ) - end - - def test_slice_encoding - slice = Prism.parse("# encoding: Shift_JIS\nア").value.slice - assert_equal (+"ア").force_encoding(Encoding::SHIFT_JIS), slice - assert_equal Encoding::SHIFT_JIS, slice.encoding - end - - def test_multibyte_escapes - [ - ["'", "'"], - ["\"", "\""], - ["`", "`"], - ["/", "/"], - ["<<'HERE'\n", "\nHERE"], - ["<<-HERE\n", "\nHERE"] - ].each do |opening, closing| - assert Prism.parse_success?("# encoding: shift_jis\n'\\\x82\xA0'\n") - end - end - end - - private - - class ConstantContext < BasicObject - def self.const_missing(const) - const - end - end - - def constant_context - ConstantContext.new - end - - class IdentifierContext < BasicObject - def method_missing(name, *) - name - end - end - - def identifier_context - IdentifierContext.new - end - - def assert_encoding_constant(name, character) - source = "# encoding: #{name}\n#{character}" - expected = constant_context.instance_eval(source) - - result = Prism.parse(source) - assert result.success? - - actual = result.value.statements.body.last - assert_kind_of ConstantReadNode, actual - assert_equal expected, actual.name - end - - def assert_encoding_identifier(name, character) - source = "# encoding: #{name}\n#{character}" - expected = identifier_context.instance_eval(source) - - result = Prism.parse(source) - assert result.success? - - actual = result.value.statements.body.last - assert_kind_of CallNode, actual - assert_equal expected, actual.name - end - - # Check that we can properly parse every codepoint in the given encoding. - def assert_encoding(encoding, name, range) - # I'm not entirely sure, but I believe these codepoints are incorrect in - # their parsing in CRuby. They all report as matching `[[:lower:]]` but - # then they are parsed as constants. This is because CRuby determines if - # an identifier is a constant or not by case folding it down to lowercase - # and checking if there is a difference. And even though they report - # themselves as lowercase, their case fold is different. I have reported - # this bug upstream. - case encoding - when Encoding::UTF_8, Encoding::UTF_8_MAC, Encoding::UTF8_DoCoMo, Encoding::UTF8_KDDI, Encoding::UTF8_SoftBank, Encoding::CESU_8 - range = range.to_a - [ - 0x01c5, 0x01c8, 0x01cb, 0x01f2, 0x1f88, 0x1f89, 0x1f8a, 0x1f8b, - 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, 0x1f98, 0x1f99, 0x1f9a, 0x1f9b, - 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, 0x1fa8, 0x1fa9, 0x1faa, 0x1fab, - 0x1fac, 0x1fad, 0x1fae, 0x1faf, 0x1fbc, 0x1fcc, 0x1ffc, - ] - when Encoding::Windows_1253 - range = range.to_a - [0xb5] - end - - range.each do |codepoint| - character = codepoint.chr(encoding) - - if character.match?(/[[:alpha:]]/) - if character.match?(/[[:upper:]]/) - assert_encoding_constant(name, character) - else - assert_encoding_identifier(name, character) - end - elsif character.match?(/[[:alnum:]]/) - assert_encoding_identifier(name, "_#{character}") - else - next if ["/", "{"].include?(character) - - source = "# encoding: #{name}\n/(?##{character})/\n" - assert Prism.parse(source).success?, "Expected #{source.inspect} to parse successfully." - end - rescue RangeError - source = "# encoding: #{name}\n\\x#{codepoint.to_s(16)}" - refute Prism.parse(source).success? - end - end - - def assert_encoding_flags(encoding, escapes) - escapes.each do |escaped| - source = "# encoding: #{encoding.name}\n\"#{escaped}\"" - - expected = - begin - eval(source).encoding - rescue SyntaxError => error - if error.message.include?("UTF-8 mixed within") - error.message[/: (.+?)\n/, 1] - else - raise - end - end - - actual = - Prism.parse(source).then do |result| - if result.success? - string = result.value.statements.body.first - - if string.forced_utf8_encoding? - Encoding::UTF_8 - elsif string.forced_binary_encoding? - Encoding::ASCII_8BIT - else - encoding - end - else - error = result.errors.first - - if error.message.include?("mixed") - error.message - else - raise error.message - end - end - end - - assert_equal expected, actual - end - end - - # Test Symbol literals without any interpolation or escape sequences. - def assert_symbol_encoding_flags(encoding, symbols) - symbols.each do |symbol| - source = "# encoding: #{encoding.name}\n#{symbol.inspect}" - - expected = - begin - eval(source).encoding - rescue SyntaxError => error - unless error.message.include?("invalid multibyte char") - raise - end - end - - actual = - Prism.parse(source).then do |result| - if result.success? - symbol = result.value.statements.body.first - - if symbol.forced_utf8_encoding? - Encoding::UTF_8 - elsif symbol.forced_binary_encoding? - Encoding::ASCII_8BIT - elsif symbol.forced_us_ascii_encoding? - Encoding::US_ASCII - else - encoding - end - else - error = result.errors.last - - unless error.message.include?("invalid symbol") - raise error.message - end - end - end - - assert_equal expected, actual - end - end - - def assert_symbol_character_escape_encoding_flags(encoding, escapes) - escapes.each do |escaped| - source = "# encoding: #{encoding.name}\n:\"#{escaped}\"" - - expected = - begin - eval(source).encoding - rescue SyntaxError => error - if error.message.include?("UTF-8 mixed within") - error.message[/: (.+?)\n/, 1] - else - raise - end - end - - actual = - Prism.parse(source).then do |result| - if result.success? - symbol = result.value.statements.body.first - - if symbol.forced_utf8_encoding? - Encoding::UTF_8 - elsif symbol.forced_binary_encoding? - Encoding::ASCII_8BIT - elsif symbol.forced_us_ascii_encoding? - Encoding::US_ASCII - else - encoding - end - else - error = result.errors.first - - if error.message.include?("mixed") - error.message - else - raise error.message - end - end - end - - assert_equal expected, actual - end - end - - def assert_regular_expression_encoding_flags(encoding, regexps) - regexps.each do |regexp| - regexp_modifier_used = regexp.end_with?("/u") || regexp.end_with?("/e") || regexp.end_with?("/s") || regexp.end_with?("/n") - source = "# encoding: #{encoding.name}\n#{regexp}" - - encoding_errors = ["invalid multibyte char", "escaped non ASCII character in UTF-8 regexp", "differs from source encoding"] - skipped_errors = ["invalid multibyte escape", "incompatible character encoding", "UTF-8 character in non UTF-8 regexp", "invalid Unicode range", "invalid Unicode list"] - - # TODO (nirvdrum 21-Feb-2024): Prism currently does not handle Regexp validation unless modifiers are used. So, skip processing those errors for now: https://github.com/ruby/prism/issues/2104 - unless regexp_modifier_used - skipped_errors += encoding_errors - encoding_errors.clear - end - - expected = - begin - eval(source).encoding - rescue SyntaxError => error - if encoding_errors.find { |e| error.message.include?(e) } - error.message.split("\n").map { |m| m[/: (.+?)$/, 1] } - elsif skipped_errors.find { |e| error.message.include?(e) } - next - else - raise - end - end - - actual = - Prism.parse(source).then do |result| - if result.success? - regexp = result.value.statements.body.first - - actual_encoding = if regexp.forced_utf8_encoding? - Encoding::UTF_8 - elsif regexp.forced_binary_encoding? - Encoding::ASCII_8BIT - elsif regexp.forced_us_ascii_encoding? - Encoding::US_ASCII - elsif regexp.ascii_8bit? - Encoding::ASCII_8BIT - elsif regexp.utf_8? - Encoding::UTF_8 - elsif regexp.euc_jp? - Encoding::EUC_JP - elsif regexp.windows_31j? - Encoding::Windows_31J - else - encoding - end - - if regexp.utf_8? && actual_encoding != Encoding::UTF_8 - raise "expected regexp encoding to be UTF-8 due to '/u' modifier, but got #{actual_encoding.name}" - elsif regexp.ascii_8bit? && (actual_encoding != Encoding::ASCII_8BIT && actual_encoding != Encoding::US_ASCII) - raise "expected regexp encoding to be ASCII-8BIT or US-ASCII due to '/n' modifier, but got #{actual_encoding.name}" - elsif regexp.euc_jp? && actual_encoding != Encoding::EUC_JP - raise "expected regexp encoding to be EUC-JP due to '/e' modifier, but got #{actual_encoding.name}" - elsif regexp.windows_31j? && actual_encoding != Encoding::Windows_31J - raise "expected regexp encoding to be Windows-31J due to '/s' modifier, but got #{actual_encoding.name}" - end - - if regexp.utf_8? && regexp.forced_utf8_encoding? - raise "the forced_utf8 flag should not be set when the UTF-8 modifier (/u) is used" - elsif regexp.ascii_8bit? && regexp.forced_binary_encoding? - raise "the forced_ascii_8bit flag should not be set when the UTF-8 modifier (/u) is used" - end - - actual_encoding - else - errors = result.errors.map(&:message) - - if errors.last&.include?("UTF-8 mixed within") - nil - else - errors - end - end - end - - # TODO (nirvdrum 22-Feb-2024): Remove this workaround once Prism better maps CRuby's error messages. - # This class of error message is tricky. The part not being compared is a representation of the regexp. - # Depending on the source encoding and any encoding modifiers being used, CRuby alters how the regexp is represented. - # Sometimes it's an MBC string. Other times it uses hexadecimal character escapes. And in other cases it uses - # the long-form Unicode escape sequences. This short-circuit checks that the error message is mostly correct. - if expected.is_a?(Array) && actual.is_a?(Array) - if expected.last.start_with?("/.../n has a non escaped non ASCII character in non ASCII-8BIT script:") && - actual.last.start_with?("/.../n has a non escaped non ASCII character in non ASCII-8BIT script:") - expected.last.clear - actual.last.clear - end - end - - assert_equal expected, actual - end - end - end -end diff --git a/test/prism/errors/1_2_3.txt b/test/prism/errors/1_2_3.txt new file mode 100644 index 00000000000..345452911f3 --- /dev/null +++ b/test/prism/errors/1_2_3.txt @@ -0,0 +1,11 @@ +(1, 2, 3) + ^ unexpected ',', expecting end-of-input + ^ unexpected ',', ignoring it + ^ expected a matching `)` + ^ unexpected ',', expecting end-of-input + ^ unexpected ',', ignoring it + ^ unexpected ',', expecting end-of-input + ^ unexpected ',', ignoring it + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/aliasing_global_variable_with_global_number_variable.txt b/test/prism/errors/aliasing_global_variable_with_global_number_variable.txt new file mode 100644 index 00000000000..2f40a6a3288 --- /dev/null +++ b/test/prism/errors/aliasing_global_variable_with_global_number_variable.txt @@ -0,0 +1,3 @@ +alias $a $1 + ^~ invalid argument being passed to `alias`; can't make alias for the number variables + diff --git a/test/prism/errors/aliasing_global_variable_with_non_global_variable.txt b/test/prism/errors/aliasing_global_variable_with_non_global_variable.txt new file mode 100644 index 00000000000..b6f013bab52 --- /dev/null +++ b/test/prism/errors/aliasing_global_variable_with_non_global_variable.txt @@ -0,0 +1,3 @@ +alias $a b + ^ invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable + diff --git a/test/prism/errors/aliasing_non_global_variable_with_global_variable.txt b/test/prism/errors/aliasing_non_global_variable_with_global_variable.txt new file mode 100644 index 00000000000..8863f342f0f --- /dev/null +++ b/test/prism/errors/aliasing_non_global_variable_with_global_variable.txt @@ -0,0 +1,3 @@ +alias a $b + ^~ invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable + diff --git a/test/prism/errors/alnum_delimiters.txt b/test/prism/errors/alnum_delimiters.txt new file mode 100644 index 00000000000..c9ed06ae51d --- /dev/null +++ b/test/prism/errors/alnum_delimiters.txt @@ -0,0 +1,3 @@ +%qXfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_2.txt b/test/prism/errors/alnum_delimiters_2.txt new file mode 100644 index 00000000000..3f78b434d6c --- /dev/null +++ b/test/prism/errors/alnum_delimiters_2.txt @@ -0,0 +1,3 @@ +%QXfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_3.txt b/test/prism/errors/alnum_delimiters_3.txt new file mode 100644 index 00000000000..55ef8d29a54 --- /dev/null +++ b/test/prism/errors/alnum_delimiters_3.txt @@ -0,0 +1,3 @@ +%wXfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_4.txt b/test/prism/errors/alnum_delimiters_4.txt new file mode 100644 index 00000000000..603b54debdc --- /dev/null +++ b/test/prism/errors/alnum_delimiters_4.txt @@ -0,0 +1,3 @@ +%WxfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_5.txt b/test/prism/errors/alnum_delimiters_5.txt new file mode 100644 index 00000000000..31c344ea902 --- /dev/null +++ b/test/prism/errors/alnum_delimiters_5.txt @@ -0,0 +1,3 @@ +%iXfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_6.txt b/test/prism/errors/alnum_delimiters_6.txt new file mode 100644 index 00000000000..79ffbbb1b84 --- /dev/null +++ b/test/prism/errors/alnum_delimiters_6.txt @@ -0,0 +1,3 @@ +%IXfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_7.txt b/test/prism/errors/alnum_delimiters_7.txt new file mode 100644 index 00000000000..809192e031f --- /dev/null +++ b/test/prism/errors/alnum_delimiters_7.txt @@ -0,0 +1,3 @@ +%xXfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_8.txt b/test/prism/errors/alnum_delimiters_8.txt new file mode 100644 index 00000000000..abfcf119c00 --- /dev/null +++ b/test/prism/errors/alnum_delimiters_8.txt @@ -0,0 +1,3 @@ +%rXfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_9.txt b/test/prism/errors/alnum_delimiters_9.txt new file mode 100644 index 00000000000..ae56d7be4fb --- /dev/null +++ b/test/prism/errors/alnum_delimiters_9.txt @@ -0,0 +1,3 @@ +%sXfooX +^ unknown type of %string + diff --git a/test/prism/errors/amperand_dot_after_endless_range.txt b/test/prism/errors/amperand_dot_after_endless_range.txt new file mode 100644 index 00000000000..ab8c8ccc4d4 --- /dev/null +++ b/test/prism/errors/amperand_dot_after_endless_range.txt @@ -0,0 +1,3 @@ +0 if true...&.abs + ^~ unexpected '&.'; ... is a non-associative operator + diff --git a/test/prism/errors/argument_after_ellipsis.txt b/test/prism/errors/argument_after_ellipsis.txt new file mode 100644 index 00000000000..3d708648a40 --- /dev/null +++ b/test/prism/errors/argument_after_ellipsis.txt @@ -0,0 +1,3 @@ +def foo(...); foo(..., 1); end + ^ unexpected argument after `...` + diff --git a/test/prism/errors/argument_forwarding_only_effects_its_own_internals.txt b/test/prism/errors/argument_forwarding_only_effects_its_own_internals.txt new file mode 100644 index 00000000000..9c3f0ae3f76 --- /dev/null +++ b/test/prism/errors/argument_forwarding_only_effects_its_own_internals.txt @@ -0,0 +1,3 @@ +def a(...); b(...); end; def c(x, y, z); b(...); end + ^~~ unexpected ... when the parent method is not forwarding + diff --git a/test/prism/errors/argument_forwarding_when_parent_is_not_forwarding.txt b/test/prism/errors/argument_forwarding_when_parent_is_not_forwarding.txt new file mode 100644 index 00000000000..017ba7eec9e --- /dev/null +++ b/test/prism/errors/argument_forwarding_when_parent_is_not_forwarding.txt @@ -0,0 +1,3 @@ +def a(x, y, z); b(...); end + ^~~ unexpected ... when the parent method is not forwarding + diff --git a/test/prism/errors/arguments_after_block.txt b/test/prism/errors/arguments_after_block.txt new file mode 100644 index 00000000000..c33039146fd --- /dev/null +++ b/test/prism/errors/arguments_after_block.txt @@ -0,0 +1,17 @@ +a(&block, foo) + ^ unexpected argument after a block argument +a(&block,) + ^ unexpected argument after a block argument +a.(&block,) + ^ unexpected argument after a block argument +a[&block,] + ^ unexpected argument after a block argument +def a(&block) + p(&block,) + ^ unexpected argument after a block argument + a.(&block,) + ^ unexpected argument after a block argument + a[&block,] + ^ unexpected argument after a block argument +end + diff --git a/test/prism/errors/arguments_binding_power_for_and.txt b/test/prism/errors/arguments_binding_power_for_and.txt new file mode 100644 index 00000000000..0585a091f4d --- /dev/null +++ b/test/prism/errors/arguments_binding_power_for_and.txt @@ -0,0 +1,5 @@ +foo(*bar and baz) + ^~~ unexpected 'and'; expected a `)` to close the arguments + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/arguments_invalid_comma.txt b/test/prism/errors/arguments_invalid_comma.txt new file mode 100644 index 00000000000..4e1360580c4 --- /dev/null +++ b/test/prism/errors/arguments_invalid_comma.txt @@ -0,0 +1,4 @@ +p(a,b +,) +^ invalid comma + diff --git a/test/prism/errors/array_invalid_comma.txt b/test/prism/errors/array_invalid_comma.txt new file mode 100644 index 00000000000..2f52a253e0f --- /dev/null +++ b/test/prism/errors/array_invalid_comma.txt @@ -0,0 +1,4 @@ +[a +,] +^ invalid comma + diff --git a/test/prism/errors/assign_to_numbered_parameter.txt b/test/prism/errors/assign_to_numbered_parameter.txt new file mode 100644 index 00000000000..74cc0c40324 --- /dev/null +++ b/test/prism/errors/assign_to_numbered_parameter.txt @@ -0,0 +1,11 @@ +a in _1 + ^~ _1 is reserved for numbered parameters +a => _1 + ^~ _1 is reserved for numbered parameters +1 => a, _1 + ^~ _1 is reserved for numbered parameters +1 in a, _1 + ^~ _1 is reserved for numbered parameters +/(?<_1>)/ =~ a + ^~ _1 is reserved for numbered parameters + diff --git a/test/prism/errors/bad_arguments.txt b/test/prism/errors/bad_arguments.txt new file mode 100644 index 00000000000..ea19efd3c8f --- /dev/null +++ b/test/prism/errors/bad_arguments.txt @@ -0,0 +1,6 @@ +def foo(A, @a, $A, @@a);end + ^ invalid formal argument; formal argument cannot be a constant + ^~ invalid formal argument; formal argument cannot be an instance variable + ^~ invalid formal argument; formal argument cannot be a global variable + ^~~ invalid formal argument; formal argument cannot be a class variable + diff --git a/test/prism/errors/begin_at_toplevel.txt b/test/prism/errors/begin_at_toplevel.txt new file mode 100644 index 00000000000..ce3d3b8d002 --- /dev/null +++ b/test/prism/errors/begin_at_toplevel.txt @@ -0,0 +1,3 @@ +def foo; BEGIN {}; end + ^~~~~ BEGIN is permitted only at toplevel + diff --git a/test/prism/errors/binary_range_with_left_unary_range.txt b/test/prism/errors/binary_range_with_left_unary_range.txt new file mode 100644 index 00000000000..85cf55fb806 --- /dev/null +++ b/test/prism/errors/binary_range_with_left_unary_range.txt @@ -0,0 +1,8 @@ +..1.. + ^~ unexpected range operator; .. and ... are non-associative and cannot be chained +...1.. + ^~ unexpected range operator; .. and ... are non-associative and cannot be chained + ^~ unexpected ..; .. is a non-associative operator + ^~ unexpected .., expecting end-of-input + ^~ unexpected .., ignoring it + diff --git a/test/prism/errors/block_arg_and_block.txt b/test/prism/errors/block_arg_and_block.txt new file mode 100644 index 00000000000..c355c404758 --- /dev/null +++ b/test/prism/errors/block_arg_and_block.txt @@ -0,0 +1,3 @@ +foo(&1) { } + ^~~ both block arg and actual block given; only one block is allowed + diff --git a/test/prism/errors/block_beginning_with_brace_and_ending_with_end.txt b/test/prism/errors/block_beginning_with_brace_and_ending_with_end.txt new file mode 100644 index 00000000000..f0fa964c8a7 --- /dev/null +++ b/test/prism/errors/block_beginning_with_brace_and_ending_with_end.txt @@ -0,0 +1,6 @@ +x.each { x end + ^~~ unexpected 'end', expecting end-of-input + ^~~ unexpected 'end', ignoring it + ^ unexpected end-of-input, assuming it is closing the parent top level context + ^ expected a block beginning with `{` to end with `}` + diff --git a/test/prism/errors/break_1.txt b/test/prism/errors/break_1.txt new file mode 100644 index 00000000000..5d74e7bde0f --- /dev/null +++ b/test/prism/errors/break_1.txt @@ -0,0 +1,4 @@ +break 1,; + ^ unexpected ';'; expected an argument +^~~~~~~~ Invalid break + diff --git a/test/prism/errors/break_1_2_3.txt b/test/prism/errors/break_1_2_3.txt new file mode 100644 index 00000000000..817207cbfe3 --- /dev/null +++ b/test/prism/errors/break_1_2_3.txt @@ -0,0 +1,8 @@ +break(1, 2, 3) + ^ unexpected ',', expecting end-of-input + ^ unexpected ',', ignoring it + ^ expected a matching `)` + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it +^~~~~~~~~~~~~ Invalid break + diff --git a/test/prism/errors/call_with_block_and_write.txt b/test/prism/errors/call_with_block_and_write.txt new file mode 100644 index 00000000000..f63d94770eb --- /dev/null +++ b/test/prism/errors/call_with_block_and_write.txt @@ -0,0 +1,4 @@ +foo {} &&= 1 +^~~~~~ unexpected write target + ^~~ unexpected operator after a call with a block + diff --git a/test/prism/errors/call_with_block_operator_write.txt b/test/prism/errors/call_with_block_operator_write.txt new file mode 100644 index 00000000000..3c36050b34f --- /dev/null +++ b/test/prism/errors/call_with_block_operator_write.txt @@ -0,0 +1,4 @@ +foo {} += 1 +^~~~~~ unexpected write target + ^~ unexpected operator after a call with a block + diff --git a/test/prism/errors/call_with_block_or_write.txt b/test/prism/errors/call_with_block_or_write.txt new file mode 100644 index 00000000000..2cced0db75d --- /dev/null +++ b/test/prism/errors/call_with_block_or_write.txt @@ -0,0 +1,4 @@ +foo {} ||= 1 +^~~~~~ unexpected write target + ^~~ unexpected operator after a call with a block + diff --git a/test/prism/errors/cannot_assign_to_a_reserved_numbered_parameter.txt b/test/prism/errors/cannot_assign_to_a_reserved_numbered_parameter.txt new file mode 100644 index 00000000000..750915fb1fb --- /dev/null +++ b/test/prism/errors/cannot_assign_to_a_reserved_numbered_parameter.txt @@ -0,0 +1,14 @@ +begin + _1=:a;_2=:a;_3=:a;_4=:a;_5=:a + ^~ _1 is reserved for numbered parameters + ^~ _2 is reserved for numbered parameters + ^~ _3 is reserved for numbered parameters + ^~ _4 is reserved for numbered parameters + ^~ _5 is reserved for numbered parameters + _6=:a;_7=:a;_8=:a;_9=:a;_10=:a + ^~ _6 is reserved for numbered parameters + ^~ _7 is reserved for numbered parameters + ^~ _8 is reserved for numbered parameters + ^~ _9 is reserved for numbered parameters +end + diff --git a/test/prism/errors/case_without_clauses.txt b/test/prism/errors/case_without_clauses.txt new file mode 100644 index 00000000000..3bbbfdd97fa --- /dev/null +++ b/test/prism/errors/case_without_clauses.txt @@ -0,0 +1,4 @@ +case :a +^~~~ expected a `when` or `in` clause after `case` +end + diff --git a/test/prism/errors/case_without_when_clauses_errors_on_else_clause.txt b/test/prism/errors/case_without_when_clauses_errors_on_else_clause.txt new file mode 100644 index 00000000000..c5a1179fb9d --- /dev/null +++ b/test/prism/errors/case_without_when_clauses_errors_on_else_clause.txt @@ -0,0 +1,5 @@ +case :a +^~~~ expected a `when` or `in` clause after `case` +else +end + diff --git a/test/prism/errors/check_value_expression.txt b/test/prism/errors/check_value_expression.txt new file mode 100644 index 00000000000..33a472d94c1 --- /dev/null +++ b/test/prism/errors/check_value_expression.txt @@ -0,0 +1,20 @@ +1 => ^(return) + ^~~~~~ unexpected void value expression +while true + 1 => ^(break) + ^~~~~ unexpected void value expression + 1 => ^(next) + ^~~~ unexpected void value expression + 1 => ^(redo) + ^~~~ unexpected void value expression + 1 => ^(retry) + ^~~~~ Invalid retry without rescue + ^~~~~ unexpected void value expression + 1 => ^(2 => a) + ^~~~~~ unexpected void value expression +end +1 => ^(if 1; (return) else (return) end) + ^~~~~~ unexpected void value expression +1 => ^(unless 1; (return) else (return) end) + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/class_definition_in_method_body.txt b/test/prism/errors/class_definition_in_method_body.txt new file mode 100644 index 00000000000..fcdc5746eec --- /dev/null +++ b/test/prism/errors/class_definition_in_method_body.txt @@ -0,0 +1,3 @@ +def foo;class A;end;end + ^~~~~ unexpected class definition in method body + diff --git a/test/prism/errors/class_definition_in_method_defs.txt b/test/prism/errors/class_definition_in_method_defs.txt new file mode 100644 index 00000000000..23bee0b6fb3 --- /dev/null +++ b/test/prism/errors/class_definition_in_method_defs.txt @@ -0,0 +1,7 @@ +def foo(bar = class A;end);end + ^~~~~ unexpected class definition in method body +def foo;rescue;class A;end;end + ^~~~~ unexpected class definition in method body +def foo;ensure;class A;end;end + ^~~~~ unexpected class definition in method body + diff --git a/test/prism/errors/class_name.txt b/test/prism/errors/class_name.txt new file mode 100644 index 00000000000..8b75896ddba --- /dev/null +++ b/test/prism/errors/class_name.txt @@ -0,0 +1,3 @@ +class 0.X end + ^~~ unexpected constant path after `class`; class/module name must be CONSTANT + diff --git a/test/prism/errors/command_call_in.txt b/test/prism/errors/command_call_in.txt new file mode 100644 index 00000000000..2fdcf097389 --- /dev/null +++ b/test/prism/errors/command_call_in.txt @@ -0,0 +1,5 @@ +foo 1 in a + ^~ unexpected 'in', expecting end-of-input + ^~ unexpected 'in', ignoring it +a = foo 2 in b + diff --git a/test/prism/errors/command_calls.txt b/test/prism/errors/command_calls.txt new file mode 100644 index 00000000000..19812a1d0a6 --- /dev/null +++ b/test/prism/errors/command_calls.txt @@ -0,0 +1,3 @@ +[a b] + ^ unexpected local variable or method; expected a `,` separator for the array elements + diff --git a/test/prism/errors/command_calls_10.txt b/test/prism/errors/command_calls_10.txt new file mode 100644 index 00000000000..f4d9f0fabcf --- /dev/null +++ b/test/prism/errors/command_calls_10.txt @@ -0,0 +1,3 @@ ++a b + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_11.txt b/test/prism/errors/command_calls_11.txt new file mode 100644 index 00000000000..868476c0c31 --- /dev/null +++ b/test/prism/errors/command_calls_11.txt @@ -0,0 +1,3 @@ +a + b c + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_12.txt b/test/prism/errors/command_calls_12.txt new file mode 100644 index 00000000000..50c9ae88e3a --- /dev/null +++ b/test/prism/errors/command_calls_12.txt @@ -0,0 +1,3 @@ +a && b c + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_13.txt b/test/prism/errors/command_calls_13.txt new file mode 100644 index 00000000000..50dc4a84a02 --- /dev/null +++ b/test/prism/errors/command_calls_13.txt @@ -0,0 +1,3 @@ +a =~ b c + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_14.txt b/test/prism/errors/command_calls_14.txt new file mode 100644 index 00000000000..1b16fd32453 --- /dev/null +++ b/test/prism/errors/command_calls_14.txt @@ -0,0 +1,3 @@ +a = b, c d + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_15.txt b/test/prism/errors/command_calls_15.txt new file mode 100644 index 00000000000..d2409fd0023 --- /dev/null +++ b/test/prism/errors/command_calls_15.txt @@ -0,0 +1,3 @@ +a = *b c + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_16.txt b/test/prism/errors/command_calls_16.txt new file mode 100644 index 00000000000..ceb07dfe30a --- /dev/null +++ b/test/prism/errors/command_calls_16.txt @@ -0,0 +1,3 @@ +a, b = c = d f + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_17.txt b/test/prism/errors/command_calls_17.txt new file mode 100644 index 00000000000..a78ac0985d1 --- /dev/null +++ b/test/prism/errors/command_calls_17.txt @@ -0,0 +1,5 @@ +a ? b c : d e + ^ expected a `:` after the true expression of a ternary operator + ^ unexpected ':', expecting end-of-input + ^ unexpected ':', ignoring it + diff --git a/test/prism/errors/command_calls_18.txt b/test/prism/errors/command_calls_18.txt new file mode 100644 index 00000000000..393e7e0ae63 --- /dev/null +++ b/test/prism/errors/command_calls_18.txt @@ -0,0 +1,3 @@ +defined? a b + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_19.txt b/test/prism/errors/command_calls_19.txt new file mode 100644 index 00000000000..e045187f1e4 --- /dev/null +++ b/test/prism/errors/command_calls_19.txt @@ -0,0 +1,3 @@ +! ! a b + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_2.txt b/test/prism/errors/command_calls_2.txt new file mode 100644 index 00000000000..b0983c015bb --- /dev/null +++ b/test/prism/errors/command_calls_2.txt @@ -0,0 +1,6 @@ +{a: b c} + ^ expected a `}` to close the hash literal + ^ unexpected local variable or method, expecting end-of-input + ^ unexpected '}', expecting end-of-input + ^ unexpected '}', ignoring it + diff --git a/test/prism/errors/command_calls_20.txt b/test/prism/errors/command_calls_20.txt new file mode 100644 index 00000000000..3058ebce963 --- /dev/null +++ b/test/prism/errors/command_calls_20.txt @@ -0,0 +1,3 @@ +def f a = b c; end + ^ expected a delimiter to close the parameters + diff --git a/test/prism/errors/command_calls_21.txt b/test/prism/errors/command_calls_21.txt new file mode 100644 index 00000000000..73d8f83539a --- /dev/null +++ b/test/prism/errors/command_calls_21.txt @@ -0,0 +1,5 @@ +def f(a = b c); end + ^ unexpected local variable or method; expected a `)` to close the parameters + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/command_calls_22.txt b/test/prism/errors/command_calls_22.txt new file mode 100644 index 00000000000..5a234e04e8b --- /dev/null +++ b/test/prism/errors/command_calls_22.txt @@ -0,0 +1,3 @@ +a = b rescue c d + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_23.txt b/test/prism/errors/command_calls_23.txt new file mode 100644 index 00000000000..db85589ffde --- /dev/null +++ b/test/prism/errors/command_calls_23.txt @@ -0,0 +1,3 @@ +def a = b rescue c d + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_24.txt b/test/prism/errors/command_calls_24.txt new file mode 100644 index 00000000000..3046b36dc12 --- /dev/null +++ b/test/prism/errors/command_calls_24.txt @@ -0,0 +1,5 @@ +->a=b c{} + ^ expected a `do` keyword or a `{` to open the lambda block + ^ unexpected end-of-input, assuming it is closing the parent top level context + ^ expected a lambda block beginning with `do` to end with `end` + diff --git a/test/prism/errors/command_calls_25.txt b/test/prism/errors/command_calls_25.txt new file mode 100644 index 00000000000..5fddd90fdd0 --- /dev/null +++ b/test/prism/errors/command_calls_25.txt @@ -0,0 +1,8 @@ +->(a=b c){} + ^ expected a matching `)` + ^ expected a `do` keyword or a `{` to open the lambda block + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + ^ unexpected end-of-input, assuming it is closing the parent top level context + ^ expected a lambda block beginning with `do` to end with `end` + diff --git a/test/prism/errors/command_calls_26.txt b/test/prism/errors/command_calls_26.txt new file mode 100644 index 00000000000..29ed4cb903b --- /dev/null +++ b/test/prism/errors/command_calls_26.txt @@ -0,0 +1,3 @@ +case; when a b; end + ^ expected a delimiter after the predicates of a `when` clause + diff --git a/test/prism/errors/command_calls_27.txt b/test/prism/errors/command_calls_27.txt new file mode 100644 index 00000000000..8d1c3ee0779 --- /dev/null +++ b/test/prism/errors/command_calls_27.txt @@ -0,0 +1,3 @@ +case; in a if a b; end +^~~~ expected a predicate for a case matching statement + diff --git a/test/prism/errors/command_calls_28.txt b/test/prism/errors/command_calls_28.txt new file mode 100644 index 00000000000..4bfe88d67ba --- /dev/null +++ b/test/prism/errors/command_calls_28.txt @@ -0,0 +1,3 @@ +case; in a unless a b; end +^~~~ expected a predicate for a case matching statement + diff --git a/test/prism/errors/command_calls_29.txt b/test/prism/errors/command_calls_29.txt new file mode 100644 index 00000000000..eae012ab44c --- /dev/null +++ b/test/prism/errors/command_calls_29.txt @@ -0,0 +1,3 @@ +begin; rescue a b; end + ^ expected a closing delimiter for the `rescue` clause + diff --git a/test/prism/errors/command_calls_3.txt b/test/prism/errors/command_calls_3.txt new file mode 100644 index 00000000000..77af72b9048 --- /dev/null +++ b/test/prism/errors/command_calls_3.txt @@ -0,0 +1,3 @@ +...a b + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_30.txt b/test/prism/errors/command_calls_30.txt new file mode 100644 index 00000000000..48e35685cba --- /dev/null +++ b/test/prism/errors/command_calls_30.txt @@ -0,0 +1,3 @@ +begin; rescue a b => c; end + ^ expected a closing delimiter for the `rescue` clause + diff --git a/test/prism/errors/command_calls_4.txt b/test/prism/errors/command_calls_4.txt new file mode 100644 index 00000000000..4be14e57e47 --- /dev/null +++ b/test/prism/errors/command_calls_4.txt @@ -0,0 +1,3 @@ +if ...a b; end + ^ expected `then` or `;` or '\n' + diff --git a/test/prism/errors/command_calls_5.txt b/test/prism/errors/command_calls_5.txt new file mode 100644 index 00000000000..799a6c1136b --- /dev/null +++ b/test/prism/errors/command_calls_5.txt @@ -0,0 +1,3 @@ +a b, c d + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_6.txt b/test/prism/errors/command_calls_6.txt new file mode 100644 index 00000000000..6f09d36e942 --- /dev/null +++ b/test/prism/errors/command_calls_6.txt @@ -0,0 +1,6 @@ +a(b, c d) + ^ unexpected local variable or method; expected a `)` to close the arguments + ^ unexpected local variable or method, expecting end-of-input + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/command_calls_7.txt b/test/prism/errors/command_calls_7.txt new file mode 100644 index 00000000000..b5d74209fa6 --- /dev/null +++ b/test/prism/errors/command_calls_7.txt @@ -0,0 +1,6 @@ +a(*b c) + ^ unexpected local variable or method; expected a `)` to close the arguments + ^ unexpected local variable or method, expecting end-of-input + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/command_calls_8.txt b/test/prism/errors/command_calls_8.txt new file mode 100644 index 00000000000..e574063e72a --- /dev/null +++ b/test/prism/errors/command_calls_8.txt @@ -0,0 +1,6 @@ +a(**b c) + ^ unexpected local variable or method; expected a `)` to close the arguments + ^ unexpected local variable or method, expecting end-of-input + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/command_calls_9.txt b/test/prism/errors/command_calls_9.txt new file mode 100644 index 00000000000..69515d959c0 --- /dev/null +++ b/test/prism/errors/command_calls_9.txt @@ -0,0 +1,6 @@ +a(&b c) + ^ unexpected local variable or method; expected a `)` to close the arguments + ^ unexpected local variable or method, expecting end-of-input + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/conditional_predicate_closed.txt b/test/prism/errors/conditional_predicate_closed.txt new file mode 100644 index 00000000000..6655fd2b1ce --- /dev/null +++ b/test/prism/errors/conditional_predicate_closed.txt @@ -0,0 +1,6 @@ +if 0 0; elsif 0 0; end + ^ expected `then` or `;` or '\n' + ^ expected `then` or `;` or '\n' +unless 0 0; end + ^ expected `then` or `;` or '\n' + diff --git a/test/prism/errors/constant_assignment_in_method.txt b/test/prism/errors/constant_assignment_in_method.txt new file mode 100644 index 00000000000..1ee49bffe6f --- /dev/null +++ b/test/prism/errors/constant_assignment_in_method.txt @@ -0,0 +1,3 @@ +def foo();A=1;end + ^~~ dynamic constant assignment + diff --git a/test/prism/errors/constant_path_with_invalid_token_after.txt b/test/prism/errors/constant_path_with_invalid_token_after.txt new file mode 100644 index 00000000000..acb6dba30a3 --- /dev/null +++ b/test/prism/errors/constant_path_with_invalid_token_after.txt @@ -0,0 +1,4 @@ +A::$b + ^ expected a constant after the `::` operator + ^~ unexpected global variable, expecting end-of-input + diff --git a/test/prism/errors/content_after_unterminated_heredoc.txt b/test/prism/errors/content_after_unterminated_heredoc.txt new file mode 100644 index 00000000000..c0446a8c39f --- /dev/null +++ b/test/prism/errors/content_after_unterminated_heredoc.txt @@ -0,0 +1,4 @@ +<<~FOO.foo + ^~~ unterminated heredoc; can't find string "FOO" anywhere before EOF + ^~~ unterminated heredoc; can't find string "FOO" anywhere before EOF + diff --git a/test/prism/errors/cr_without_lf_in_percent_expression.txt b/test/prism/errors/cr_without_lf_in_percent_expression.txt new file mode 100644 index 00000000000..903f8b4b4af --- /dev/null +++ b/test/prism/errors/cr_without_lf_in_percent_expression.txt @@ -0,0 +1,3 @@ +% + ^ unterminated string meets end of file + diff --git a/test/prism/errors/def_with_empty_expression_receiver.txt b/test/prism/errors/def_with_empty_expression_receiver.txt new file mode 100644 index 00000000000..153fe8a1c6f --- /dev/null +++ b/test/prism/errors/def_with_empty_expression_receiver.txt @@ -0,0 +1,3 @@ +def ().a; end + ^ expected a receiver for the method definition + diff --git a/test/prism/errors/def_with_expression_receiver_and_no_identifier.txt b/test/prism/errors/def_with_expression_receiver_and_no_identifier.txt new file mode 100644 index 00000000000..1aefc07f1a2 --- /dev/null +++ b/test/prism/errors/def_with_expression_receiver_and_no_identifier.txt @@ -0,0 +1,4 @@ +def (a); end + ^ expected a `.` or `::` after the receiver in a method definition + ^ unexpected ';'; expected a method name + diff --git a/test/prism/errors/def_with_multiple_statements_receiver.txt b/test/prism/errors/def_with_multiple_statements_receiver.txt new file mode 100644 index 00000000000..80c9d4c1901 --- /dev/null +++ b/test/prism/errors/def_with_multiple_statements_receiver.txt @@ -0,0 +1,10 @@ +def ( +a +b +^ expected a matching `)` +^ expected a `.` or `::` after the receiver in a method definition + ^ expected a delimiter to close the parameters +).c; end +^ unexpected ')', ignoring it + ^ unexpected '.', ignoring it + diff --git a/test/prism/errors/defining_numbered_parameter.txt b/test/prism/errors/defining_numbered_parameter.txt new file mode 100644 index 00000000000..2bf05d95631 --- /dev/null +++ b/test/prism/errors/defining_numbered_parameter.txt @@ -0,0 +1,3 @@ +def _1; end + ^~ _1 is reserved for numbered parameters + diff --git a/test/prism/errors/defining_numbered_parameter_2.txt b/test/prism/errors/defining_numbered_parameter_2.txt new file mode 100644 index 00000000000..dc4739b126a --- /dev/null +++ b/test/prism/errors/defining_numbered_parameter_2.txt @@ -0,0 +1,3 @@ +def self._1; end + ^~ _1 is reserved for numbered parameters + diff --git a/test/prism/errors/do_not_allow_characters_other_than_0_9_a_f_and_A_F_in_u_Unicode_character_notation.txt b/test/prism/errors/do_not_allow_characters_other_than_0_9_a_f_and_A_F_in_u_Unicode_character_notation.txt new file mode 100644 index 00000000000..953b9589d1f --- /dev/null +++ b/test/prism/errors/do_not_allow_characters_other_than_0_9_a_f_and_A_F_in_u_Unicode_character_notation.txt @@ -0,0 +1,4 @@ +"\u{000z}" + ^ invalid Unicode escape sequence + ^ unterminated Unicode escape + diff --git a/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt b/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt new file mode 100644 index 00000000000..df495576177 --- /dev/null +++ b/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt @@ -0,0 +1,3 @@ +a {|...|} + ^~~ unexpected ... when the parent method is not forwarding + diff --git a/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt b/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt new file mode 100644 index 00000000000..c2405a5c66f --- /dev/null +++ b/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt @@ -0,0 +1,3 @@ +->(...) {} + ^~~ unexpected ... when the parent method is not forwarding + diff --git a/test/prism/errors/do_not_allow_more_than_6_hexadecimal_digits_in_u_Unicode_character_notation.txt b/test/prism/errors/do_not_allow_more_than_6_hexadecimal_digits_in_u_Unicode_character_notation.txt new file mode 100644 index 00000000000..50795c93533 --- /dev/null +++ b/test/prism/errors/do_not_allow_more_than_6_hexadecimal_digits_in_u_Unicode_character_notation.txt @@ -0,0 +1,3 @@ +"\u{0000001}" + ^~~~~~~ invalid Unicode escape sequence; maximum length is 6 digits + diff --git a/test/prism/errors/do_not_allow_multiple_codepoints_in_a_single_character_literal.txt b/test/prism/errors/do_not_allow_multiple_codepoints_in_a_single_character_literal.txt new file mode 100644 index 00000000000..1a93dc6c694 --- /dev/null +++ b/test/prism/errors/do_not_allow_multiple_codepoints_in_a_single_character_literal.txt @@ -0,0 +1,3 @@ +?\u{0001 0002} + ^~~ invalid Unicode escape sequence; Multiple codepoints at single character literal are disallowed + diff --git a/test/prism/errors/do_not_allow_trailing_commas_in_lambda_parameters.txt b/test/prism/errors/do_not_allow_trailing_commas_in_lambda_parameters.txt new file mode 100644 index 00000000000..11f23f03457 --- /dev/null +++ b/test/prism/errors/do_not_allow_trailing_commas_in_lambda_parameters.txt @@ -0,0 +1,3 @@ +-> (a, b, ) {} + ^ unexpected `,` in parameters + diff --git a/test/prism/errors/do_not_allow_trailing_commas_in_method_parameters.txt b/test/prism/errors/do_not_allow_trailing_commas_in_method_parameters.txt new file mode 100644 index 00000000000..c0fec0c7048 --- /dev/null +++ b/test/prism/errors/do_not_allow_trailing_commas_in_method_parameters.txt @@ -0,0 +1,3 @@ +def foo(a,b,c,);end + ^ unexpected `,` in parameters + diff --git a/test/prism/errors/dont_allow_return_inside_class_body.txt b/test/prism/errors/dont_allow_return_inside_class_body.txt new file mode 100644 index 00000000000..286eba21033 --- /dev/null +++ b/test/prism/errors/dont_allow_return_inside_class_body.txt @@ -0,0 +1,3 @@ +class A; return; end + ^~~~~~ Invalid return in class/module body + diff --git a/test/prism/errors/dont_allow_return_inside_module_body.txt b/test/prism/errors/dont_allow_return_inside_module_body.txt new file mode 100644 index 00000000000..85dd619a932 --- /dev/null +++ b/test/prism/errors/dont_allow_return_inside_module_body.txt @@ -0,0 +1,3 @@ +module A; return; end + ^~~~~~ Invalid return in class/module body + diff --git a/test/prism/errors/dont_allow_return_inside_sclass_body.txt b/test/prism/errors/dont_allow_return_inside_sclass_body.txt new file mode 100644 index 00000000000..c29fe017282 --- /dev/null +++ b/test/prism/errors/dont_allow_return_inside_sclass_body.txt @@ -0,0 +1,3 @@ +class << A; return; end + ^~~~~~ Invalid return in class/module body + diff --git a/test/prism/errors/dont_allow_setting_to_back_and_nth_reference.txt b/test/prism/errors/dont_allow_setting_to_back_and_nth_reference.txt new file mode 100644 index 00000000000..71b5b94589c --- /dev/null +++ b/test/prism/errors/dont_allow_setting_to_back_and_nth_reference.txt @@ -0,0 +1,7 @@ +begin +$+ = nil +^~ Can't set variable $+ +$1466 = nil +^~~~~ Can't set variable $1466 +end + diff --git a/test/prism/errors/double_arguments_forwarding.txt b/test/prism/errors/double_arguments_forwarding.txt new file mode 100644 index 00000000000..29c78f8c802 --- /dev/null +++ b/test/prism/errors/double_arguments_forwarding.txt @@ -0,0 +1,4 @@ +def foo(..., ...) + ^~~ unexpected parameter order +end + diff --git a/test/prism/errors/double_scope_numbered_parameters.txt b/test/prism/errors/double_scope_numbered_parameters.txt new file mode 100644 index 00000000000..0bb9df4ede0 --- /dev/null +++ b/test/prism/errors/double_scope_numbered_parameters.txt @@ -0,0 +1,3 @@ +-> { _1 + -> { _2 } } + ^~ numbered parameter is already used in outer block + diff --git a/test/prism/errors/double_splat_followed_by_splat_argument.txt b/test/prism/errors/double_splat_followed_by_splat_argument.txt new file mode 100644 index 00000000000..b2aec1167e8 --- /dev/null +++ b/test/prism/errors/double_splat_followed_by_splat_argument.txt @@ -0,0 +1,3 @@ +a(**kwargs, *args) + ^~~~~ unexpected `*` splat argument after a `**` keyword splat argument + diff --git a/test/prism/errors/duplicate_pattern_capture.txt b/test/prism/errors/duplicate_pattern_capture.txt new file mode 100644 index 00000000000..4b48fd31188 --- /dev/null +++ b/test/prism/errors/duplicate_pattern_capture.txt @@ -0,0 +1,17 @@ +case (); in [a, a]; end + ^ duplicated variable name +case (); in [a, *a]; end + ^ duplicated variable name +case (); in {a: a, b: a}; end + ^ duplicated variable name +case (); in {a: a, **a}; end + ^ duplicated variable name +case (); in [a, {a:}]; end + ^ duplicated variable name +case (); in [a, {a: {a: {a: [a]}}}]; end + ^ duplicated variable name +case (); in a => a; end + ^ duplicated variable name +case (); in [A => a, {a: b => a}]; end + ^ duplicated variable name + diff --git a/test/prism/errors/duplicate_pattern_hash_key.txt b/test/prism/errors/duplicate_pattern_hash_key.txt new file mode 100644 index 00000000000..201b51234fa --- /dev/null +++ b/test/prism/errors/duplicate_pattern_hash_key.txt @@ -0,0 +1,4 @@ +case (); in {a:, a:}; end + ^~ duplicated key name + ^ duplicated variable name + diff --git a/test/prism/errors/duplicate_pattern_hash_key_2.txt b/test/prism/errors/duplicate_pattern_hash_key_2.txt new file mode 100644 index 00000000000..66756c454a5 --- /dev/null +++ b/test/prism/errors/duplicate_pattern_hash_key_2.txt @@ -0,0 +1,3 @@ +case (); in {a:1, a:2}; end + ^~ duplicated key name + diff --git a/test/prism/errors/duplicated_parameter_names.txt b/test/prism/errors/duplicated_parameter_names.txt new file mode 100644 index 00000000000..7b82685ca36 --- /dev/null +++ b/test/prism/errors/duplicated_parameter_names.txt @@ -0,0 +1,3 @@ +def foo(a,b,a);end + ^ duplicated argument name + diff --git a/test/prism/errors/duplicated_parameter_names_2.txt b/test/prism/errors/duplicated_parameter_names_2.txt new file mode 100644 index 00000000000..8396993d569 --- /dev/null +++ b/test/prism/errors/duplicated_parameter_names_2.txt @@ -0,0 +1,3 @@ +def foo(a,b,*a);end + ^ duplicated argument name + diff --git a/test/prism/errors/duplicated_parameter_names_3.txt b/test/prism/errors/duplicated_parameter_names_3.txt new file mode 100644 index 00000000000..437a6623c3e --- /dev/null +++ b/test/prism/errors/duplicated_parameter_names_3.txt @@ -0,0 +1,3 @@ +def foo(a,b,**a);end + ^ duplicated argument name + diff --git a/test/prism/errors/duplicated_parameter_names_4.txt b/test/prism/errors/duplicated_parameter_names_4.txt new file mode 100644 index 00000000000..a420dd8a695 --- /dev/null +++ b/test/prism/errors/duplicated_parameter_names_4.txt @@ -0,0 +1,3 @@ +def foo(a,b,&a);end + ^ duplicated argument name + diff --git a/test/prism/errors/duplicated_parameter_names_5.txt b/test/prism/errors/duplicated_parameter_names_5.txt new file mode 100644 index 00000000000..694d3a668c0 --- /dev/null +++ b/test/prism/errors/duplicated_parameter_names_5.txt @@ -0,0 +1,3 @@ +def foo(a = 1,b,*c);end + ^ unexpected parameter `*` + diff --git a/test/prism/errors/dynamic_label_pattern.txt b/test/prism/errors/dynamic_label_pattern.txt new file mode 100644 index 00000000000..b8d1012e45b --- /dev/null +++ b/test/prism/errors/dynamic_label_pattern.txt @@ -0,0 +1,3 @@ +:a => 'a': | 1 + ^ expected a pattern expression after the key + diff --git a/test/prism/errors/ellipsis_in_no_paren_call.txt b/test/prism/errors/ellipsis_in_no_paren_call.txt new file mode 100644 index 00000000000..87a847d1927 --- /dev/null +++ b/test/prism/errors/ellipsis_in_no_paren_call.txt @@ -0,0 +1,3 @@ +def foo(...); foo 1, ...; end + ^~~ unexpected `...` in an non-parenthesized call + diff --git a/test/prism/errors/for_loop_delimiter.txt b/test/prism/errors/for_loop_delimiter.txt new file mode 100644 index 00000000000..07002d9d064 --- /dev/null +++ b/test/prism/errors/for_loop_delimiter.txt @@ -0,0 +1,3 @@ +for a in b end + ^~~ unexpected 'end'; expected a 'do', newline, or ';' after the 'for' loop collection + diff --git a/test/prism/errors/for_loops_index_missing.txt b/test/prism/errors/for_loops_index_missing.txt new file mode 100644 index 00000000000..a57c22b0449 --- /dev/null +++ b/test/prism/errors/for_loops_index_missing.txt @@ -0,0 +1,5 @@ +for in 1..10 +^~~ expected an index after `for` +i +end + diff --git a/test/prism/errors/for_loops_only_end.txt b/test/prism/errors/for_loops_only_end.txt new file mode 100644 index 00000000000..a8eaf0b8ab3 --- /dev/null +++ b/test/prism/errors/for_loops_only_end.txt @@ -0,0 +1,6 @@ +for end +^~~ expected an index after `for` + ^ expected an `in` after the index in a `for` statement + ^ expected a collection after the `in` in a `for` statement + ^~~ unexpected 'end'; expected a 'do', newline, or ';' after the 'for' loop collection + diff --git a/test/prism/errors/forwarding_arg_after_keyword_rest.txt b/test/prism/errors/forwarding_arg_after_keyword_rest.txt new file mode 100644 index 00000000000..86fe4aad93f --- /dev/null +++ b/test/prism/errors/forwarding_arg_after_keyword_rest.txt @@ -0,0 +1,3 @@ +def f(**,...);end + ^~~ unexpected parameter order + diff --git a/test/prism/errors/forwarding_arg_and_block.txt b/test/prism/errors/forwarding_arg_and_block.txt new file mode 100644 index 00000000000..65c75a5d7cf --- /dev/null +++ b/test/prism/errors/forwarding_arg_and_block.txt @@ -0,0 +1,3 @@ +def foo(...) = foo(...) { } + ^~~ both block arg and actual block given; only one block is allowed + diff --git a/test/prism/errors/heredoc_unterminated.txt b/test/prism/errors/heredoc_unterminated.txt new file mode 100644 index 00000000000..3c6aeaeb81f --- /dev/null +++ b/test/prism/errors/heredoc_unterminated.txt @@ -0,0 +1,9 @@ +a=>{< 1 } + ^ unexpected '.'; expected a value in the hash literal + ^ expected a `}` to close the hash literal + ^ unexpected '}', expecting end-of-input + ^ unexpected '}', ignoring it + diff --git a/test/prism/errors/interpolated_regular_expression_with_unknown_regexp_options.txt b/test/prism/errors/interpolated_regular_expression_with_unknown_regexp_options.txt new file mode 100644 index 00000000000..8e78753b1cc --- /dev/null +++ b/test/prism/errors/interpolated_regular_expression_with_unknown_regexp_options.txt @@ -0,0 +1,3 @@ +/#{foo}/AZaz + ^~~~~ unknown regexp options - AZaz + diff --git a/test/prism/errors/invalid_global_variable_write.txt b/test/prism/errors/invalid_global_variable_write.txt new file mode 100644 index 00000000000..9d9018bcf14 --- /dev/null +++ b/test/prism/errors/invalid_global_variable_write.txt @@ -0,0 +1,4 @@ +$', +^~ Can't set variable $' +^~ unexpected write target + diff --git a/test/prism/errors/invalid_hex_escape.txt b/test/prism/errors/invalid_hex_escape.txt new file mode 100644 index 00000000000..4fb847f6d24 --- /dev/null +++ b/test/prism/errors/invalid_hex_escape.txt @@ -0,0 +1,3 @@ +"\xx" + ^~ invalid hex escape sequence + diff --git a/test/prism/errors/invalid_multi_target.txt b/test/prism/errors/invalid_multi_target.txt new file mode 100644 index 00000000000..9756278b0cf --- /dev/null +++ b/test/prism/errors/invalid_multi_target.txt @@ -0,0 +1,3 @@ +foo, +^~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_10.txt b/test/prism/errors/invalid_multi_target_10.txt new file mode 100644 index 00000000000..0e87b67d36d --- /dev/null +++ b/test/prism/errors/invalid_multi_target_10.txt @@ -0,0 +1,3 @@ +Foo, +^~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_11.txt b/test/prism/errors/invalid_multi_target_11.txt new file mode 100644 index 00000000000..8185cde79e9 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_11.txt @@ -0,0 +1,3 @@ +::Foo, +^~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_12.txt b/test/prism/errors/invalid_multi_target_12.txt new file mode 100644 index 00000000000..f511a8a76f1 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_12.txt @@ -0,0 +1,3 @@ +Foo::Foo, +^~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_13.txt b/test/prism/errors/invalid_multi_target_13.txt new file mode 100644 index 00000000000..7c9a3fb4e1e --- /dev/null +++ b/test/prism/errors/invalid_multi_target_13.txt @@ -0,0 +1,3 @@ +Foo::foo, +^~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_14.txt b/test/prism/errors/invalid_multi_target_14.txt new file mode 100644 index 00000000000..88dc08de922 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_14.txt @@ -0,0 +1,3 @@ +foo[foo], +^~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_15.txt b/test/prism/errors/invalid_multi_target_15.txt new file mode 100644 index 00000000000..c140833467c --- /dev/null +++ b/test/prism/errors/invalid_multi_target_15.txt @@ -0,0 +1,3 @@ +(foo, bar) +^~~~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_16.txt b/test/prism/errors/invalid_multi_target_16.txt new file mode 100644 index 00000000000..20ea56331f5 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_16.txt @@ -0,0 +1,3 @@ +foo((foo, bar)) + ^~~~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_17.txt b/test/prism/errors/invalid_multi_target_17.txt new file mode 100644 index 00000000000..da1ced0c595 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_17.txt @@ -0,0 +1,3 @@ +foo((*)) + ^~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_18.txt b/test/prism/errors/invalid_multi_target_18.txt new file mode 100644 index 00000000000..2beed193b44 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_18.txt @@ -0,0 +1,3 @@ +foo(((foo, bar), *)) + ^~~~~~~~~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_19.txt b/test/prism/errors/invalid_multi_target_19.txt new file mode 100644 index 00000000000..b5e3e6999ad --- /dev/null +++ b/test/prism/errors/invalid_multi_target_19.txt @@ -0,0 +1,3 @@ +(foo, bar) + 1 +^~~~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_2.txt b/test/prism/errors/invalid_multi_target_2.txt new file mode 100644 index 00000000000..68a7bbc305b --- /dev/null +++ b/test/prism/errors/invalid_multi_target_2.txt @@ -0,0 +1,3 @@ +foo = 1; foo, + ^~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_20.txt b/test/prism/errors/invalid_multi_target_20.txt new file mode 100644 index 00000000000..e800bcf2044 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_20.txt @@ -0,0 +1,3 @@ +(foo, bar) in baz +^~~~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_3.txt b/test/prism/errors/invalid_multi_target_3.txt new file mode 100644 index 00000000000..51e62076038 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_3.txt @@ -0,0 +1,3 @@ +foo.bar, +^~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_4.txt b/test/prism/errors/invalid_multi_target_4.txt new file mode 100644 index 00000000000..f4c3599ffea --- /dev/null +++ b/test/prism/errors/invalid_multi_target_4.txt @@ -0,0 +1,3 @@ +*foo, +^~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_5.txt b/test/prism/errors/invalid_multi_target_5.txt new file mode 100644 index 00000000000..5d143a3f5dc --- /dev/null +++ b/test/prism/errors/invalid_multi_target_5.txt @@ -0,0 +1,3 @@ +@foo, +^~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_6.txt b/test/prism/errors/invalid_multi_target_6.txt new file mode 100644 index 00000000000..6d15893f57d --- /dev/null +++ b/test/prism/errors/invalid_multi_target_6.txt @@ -0,0 +1,3 @@ +@@foo, +^~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_7.txt b/test/prism/errors/invalid_multi_target_7.txt new file mode 100644 index 00000000000..451f9f0a00e --- /dev/null +++ b/test/prism/errors/invalid_multi_target_7.txt @@ -0,0 +1,3 @@ +$foo, +^~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_8.txt b/test/prism/errors/invalid_multi_target_8.txt new file mode 100644 index 00000000000..fdbe272f9a0 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_8.txt @@ -0,0 +1,4 @@ +$1, +^~ Can't set variable $1 +^~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_9.txt b/test/prism/errors/invalid_multi_target_9.txt new file mode 100644 index 00000000000..038f355c5da --- /dev/null +++ b/test/prism/errors/invalid_multi_target_9.txt @@ -0,0 +1,4 @@ +$+, +^~ Can't set variable $+ +^~ unexpected write target + diff --git a/test/prism/errors/invalid_number_underscores.txt b/test/prism/errors/invalid_number_underscores.txt new file mode 100644 index 00000000000..8fc79ed7a27 --- /dev/null +++ b/test/prism/errors/invalid_number_underscores.txt @@ -0,0 +1,3 @@ +1__1 + ^ invalid underscore placement in number + diff --git a/test/prism/errors/invalid_number_underscores_10.txt b/test/prism/errors/invalid_number_underscores_10.txt new file mode 100644 index 00000000000..53b0cc07196 --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_10.txt @@ -0,0 +1,3 @@ +01_1_ + ^ trailing '_' in number + diff --git a/test/prism/errors/invalid_number_underscores_11.txt b/test/prism/errors/invalid_number_underscores_11.txt new file mode 100644 index 00000000000..469110f86fe --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_11.txt @@ -0,0 +1,3 @@ +0d1_1_ + ^ trailing '_' in number + diff --git a/test/prism/errors/invalid_number_underscores_12.txt b/test/prism/errors/invalid_number_underscores_12.txt new file mode 100644 index 00000000000..a9b63a4b6c2 --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_12.txt @@ -0,0 +1,3 @@ +0x1_1_ + ^ trailing '_' in number + diff --git a/test/prism/errors/invalid_number_underscores_2.txt b/test/prism/errors/invalid_number_underscores_2.txt new file mode 100644 index 00000000000..2762e087907 --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_2.txt @@ -0,0 +1,3 @@ +0b1__1 + ^ invalid underscore placement in number + diff --git a/test/prism/errors/invalid_number_underscores_3.txt b/test/prism/errors/invalid_number_underscores_3.txt new file mode 100644 index 00000000000..23f1e0b10be --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_3.txt @@ -0,0 +1,3 @@ +0o1__1 + ^ invalid underscore placement in number + diff --git a/test/prism/errors/invalid_number_underscores_4.txt b/test/prism/errors/invalid_number_underscores_4.txt new file mode 100644 index 00000000000..ced149752fa --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_4.txt @@ -0,0 +1,3 @@ +01__1 + ^ invalid underscore placement in number + diff --git a/test/prism/errors/invalid_number_underscores_5.txt b/test/prism/errors/invalid_number_underscores_5.txt new file mode 100644 index 00000000000..5e3f2bf6824 --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_5.txt @@ -0,0 +1,3 @@ +0d1__1 + ^ invalid underscore placement in number + diff --git a/test/prism/errors/invalid_number_underscores_6.txt b/test/prism/errors/invalid_number_underscores_6.txt new file mode 100644 index 00000000000..225b654248f --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_6.txt @@ -0,0 +1,3 @@ +0x1__1 + ^ invalid underscore placement in number + diff --git a/test/prism/errors/invalid_number_underscores_7.txt b/test/prism/errors/invalid_number_underscores_7.txt new file mode 100644 index 00000000000..d953b4cbc4e --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_7.txt @@ -0,0 +1,3 @@ +1_1_ + ^ trailing '_' in number + diff --git a/test/prism/errors/invalid_number_underscores_8.txt b/test/prism/errors/invalid_number_underscores_8.txt new file mode 100644 index 00000000000..cbdcd95d8f4 --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_8.txt @@ -0,0 +1,3 @@ +0b1_1_ + ^ trailing '_' in number + diff --git a/test/prism/errors/invalid_number_underscores_9.txt b/test/prism/errors/invalid_number_underscores_9.txt new file mode 100644 index 00000000000..173282ffb2e --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_9.txt @@ -0,0 +1,3 @@ +0o1_1_ + ^ trailing '_' in number + diff --git a/test/prism/errors/invalid_operator_write_dot.txt b/test/prism/errors/invalid_operator_write_dot.txt new file mode 100644 index 00000000000..666817e60f0 --- /dev/null +++ b/test/prism/errors/invalid_operator_write_dot.txt @@ -0,0 +1,3 @@ +foo.+= 1 + ^ unexpected write target + diff --git a/test/prism/errors/invalid_operator_write_fcall.txt b/test/prism/errors/invalid_operator_write_fcall.txt new file mode 100644 index 00000000000..2748bf32918 --- /dev/null +++ b/test/prism/errors/invalid_operator_write_fcall.txt @@ -0,0 +1,3 @@ +foo! += 1 +^~~~ unexpected write target + diff --git a/test/prism/errors/invalid_splat.txt b/test/prism/errors/invalid_splat.txt new file mode 100644 index 00000000000..cffd0f98791 --- /dev/null +++ b/test/prism/errors/invalid_splat.txt @@ -0,0 +1,4 @@ +(1 +*a) +^~ unexpected write target + diff --git a/test/prism/errors/it_with_ordinary_parameter.txt b/test/prism/errors/it_with_ordinary_parameter.txt new file mode 100644 index 00000000000..0fc34e9cc88 --- /dev/null +++ b/test/prism/errors/it_with_ordinary_parameter.txt @@ -0,0 +1,3 @@ +proc { || it } + ^~ `it` is not allowed when an ordinary parameter is defined + diff --git a/test/prism/errors/keywords_parameters_before_required_parameters.txt b/test/prism/errors/keywords_parameters_before_required_parameters.txt new file mode 100644 index 00000000000..42d036e9501 --- /dev/null +++ b/test/prism/errors/keywords_parameters_before_required_parameters.txt @@ -0,0 +1,4 @@ +def foo(b:, a) + ^ unexpected parameter order +end + diff --git a/test/prism/errors/label_in_parentheses.txt b/test/prism/errors/label_in_parentheses.txt new file mode 100644 index 00000000000..4f6e3e9e36d --- /dev/null +++ b/test/prism/errors/label_in_parentheses.txt @@ -0,0 +1,3 @@ +("a":) + ^~~~ unexpected label + diff --git a/test/prism/errors/loop_conditional_is_closed.txt b/test/prism/errors/loop_conditional_is_closed.txt new file mode 100644 index 00000000000..2be13533199 --- /dev/null +++ b/test/prism/errors/loop_conditional_is_closed.txt @@ -0,0 +1,4 @@ +while 0 0; foo; end; until 0 0; foo; end + ^ expected a predicate expression for the `while` statement + ^ expected a predicate expression for the `until` statement + diff --git a/test/prism/errors/match_plus.txt b/test/prism/errors/match_plus.txt new file mode 100644 index 00000000000..5e349a96ad6 --- /dev/null +++ b/test/prism/errors/match_plus.txt @@ -0,0 +1,7 @@ +a in b + c + ^ unexpected '+', expecting end-of-input + ^ unexpected '+', ignoring it +a => b + c + ^ unexpected '+', expecting end-of-input + ^ unexpected '+', ignoring it + diff --git a/test/prism/errors/method_parameters_after_arguments_forwarding.txt b/test/prism/errors/method_parameters_after_arguments_forwarding.txt new file mode 100644 index 00000000000..ec2aefda1de --- /dev/null +++ b/test/prism/errors/method_parameters_after_arguments_forwarding.txt @@ -0,0 +1,4 @@ +def foo(..., a) + ^ unexpected parameter order +end + diff --git a/test/prism/errors/method_parameters_after_block.txt b/test/prism/errors/method_parameters_after_block.txt new file mode 100644 index 00000000000..6e2091d5d1e --- /dev/null +++ b/test/prism/errors/method_parameters_after_block.txt @@ -0,0 +1,4 @@ +def foo(&block, a) + ^ unexpected parameter order +end + diff --git a/test/prism/errors/method_with_arguments_after_anonymous_block.txt b/test/prism/errors/method_with_arguments_after_anonymous_block.txt new file mode 100644 index 00000000000..0d986b3c010 --- /dev/null +++ b/test/prism/errors/method_with_arguments_after_anonymous_block.txt @@ -0,0 +1,4 @@ +def foo(&, a) + ^ unexpected parameter order +end + diff --git a/test/prism/errors/missing_terminator_in_parentheses.txt b/test/prism/errors/missing_terminator_in_parentheses.txt new file mode 100644 index 00000000000..af4b698f0c9 --- /dev/null +++ b/test/prism/errors/missing_terminator_in_parentheses.txt @@ -0,0 +1,3 @@ +(0 0) + ^ unexpected integer, expecting end-of-input + diff --git a/test/prism/errors/module_definition_in_method_body.txt b/test/prism/errors/module_definition_in_method_body.txt new file mode 100644 index 00000000000..59900c96dde --- /dev/null +++ b/test/prism/errors/module_definition_in_method_body.txt @@ -0,0 +1,3 @@ +def foo;module A;end;end + ^~~~~~ unexpected module definition in method body + diff --git a/test/prism/errors/module_definition_in_method_body_within_block.txt b/test/prism/errors/module_definition_in_method_body_within_block.txt new file mode 100644 index 00000000000..204be356079 --- /dev/null +++ b/test/prism/errors/module_definition_in_method_body_within_block.txt @@ -0,0 +1,7 @@ +def foo + bar do + module Foo;end + ^~~~~~ unexpected module definition in method body + end +end + diff --git a/test/prism/errors/module_definition_in_method_defs.txt b/test/prism/errors/module_definition_in_method_defs.txt new file mode 100644 index 00000000000..c5a6a8a2e8a --- /dev/null +++ b/test/prism/errors/module_definition_in_method_defs.txt @@ -0,0 +1,7 @@ +def foo(bar = module A;end);end + ^~~~~~ unexpected module definition in method body +def foo;rescue;module A;end;end + ^~~~~~ unexpected module definition in method body +def foo;ensure;module A;end;end + ^~~~~~ unexpected module definition in method body + diff --git a/test/prism/errors/module_name_recoverable.txt b/test/prism/errors/module_name_recoverable.txt new file mode 100644 index 00000000000..58a28a60c56 --- /dev/null +++ b/test/prism/errors/module_name_recoverable.txt @@ -0,0 +1,4 @@ +module Parent module end + ^~~~~~ unexpected constant path after `module`; class/module name must be CONSTANT + ^~~ unexpected 'end', assuming it is closing the parent module definition + diff --git a/test/prism/errors/multi_target_parens.txt b/test/prism/errors/multi_target_parens.txt new file mode 100644 index 00000000000..fe1b9a4b180 --- /dev/null +++ b/test/prism/errors/multi_target_parens.txt @@ -0,0 +1,19 @@ +( + ( * ) ) + ^~~~~ unexpected write target +( a ( * ) ) + ^~~~~ unexpected write target +( 1 + ( * ) ) + ^~~~~ unexpected write target +( .. ( * ) ) + ^~~~~ unexpected write target +( a = ( * ) ) + ^~~~~ unexpected write target +( * = ( * ) ) + ^~~~~ unexpected write target +( a if ( * ) ) + ^~~~~ unexpected write target +( 1; ( * ) ) + ^~~~~ unexpected write target +( def f() = ( * ) ) + ^~~~~ unexpected write target + diff --git a/test/prism/errors/multi_target_star.txt b/test/prism/errors/multi_target_star.txt new file mode 100644 index 00000000000..3d6d7f42867 --- /dev/null +++ b/test/prism/errors/multi_target_star.txt @@ -0,0 +1,17 @@ +[(*),] + ^~~ unexpected write target +[1,(a,*b,(c,d)),1] + ^~~~~~~~~~~~ unexpected write target +{a:(*),} + ^~~ unexpected write target +[1+(*),] + ^~~ unexpected write target +x=(*),1 + ^~~ unexpected write target +p((*),) + ^~~ unexpected write target +p (*),1 + ^~~ unexpected write target +x = def f = (*),1 + ^~~ unexpected write target + diff --git a/test/prism/errors/multiple_error_in_parameters_order.txt b/test/prism/errors/multiple_error_in_parameters_order.txt new file mode 100644 index 00000000000..5dae0a105ac --- /dev/null +++ b/test/prism/errors/multiple_error_in_parameters_order.txt @@ -0,0 +1,5 @@ +def foo(**args, a, b:) + ^ unexpected parameter order + ^~ unexpected parameter order +end + diff --git a/test/prism/errors/next_1.txt b/test/prism/errors/next_1.txt new file mode 100644 index 00000000000..83ce038ebbd --- /dev/null +++ b/test/prism/errors/next_1.txt @@ -0,0 +1,4 @@ +next 1,; + ^ unexpected ';'; expected an argument +^~~~~~~ Invalid next + diff --git a/test/prism/errors/next_1_2_3.txt b/test/prism/errors/next_1_2_3.txt new file mode 100644 index 00000000000..7abe577ab34 --- /dev/null +++ b/test/prism/errors/next_1_2_3.txt @@ -0,0 +1,8 @@ +next(1, 2, 3) + ^ unexpected ',', expecting end-of-input + ^ unexpected ',', ignoring it + ^ expected a matching `)` + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it +^~~~~~~~~~~~ Invalid next + diff --git a/test/prism/errors/non_assoc_equality.txt b/test/prism/errors/non_assoc_equality.txt new file mode 100644 index 00000000000..9b3f1375491 --- /dev/null +++ b/test/prism/errors/non_assoc_equality.txt @@ -0,0 +1,25 @@ +1 == 2 == 3 + ^~ unexpected '=='; '==' is a non-associative operator + ^~ unexpected '==', expecting end-of-input + ^~ unexpected '==', ignoring it +1 != 2 != 3 + ^~ unexpected '!='; '!=' is a non-associative operator + ^~ unexpected '!=', expecting end-of-input + ^~ unexpected '!=', ignoring it +1 === 2 === 3 + ^~~ unexpected '==='; '===' is a non-associative operator + ^~~ unexpected '===', expecting end-of-input + ^~~ unexpected '===', ignoring it +1 =~ 2 =~ 3 + ^~ unexpected '=~'; '=~' is a non-associative operator + ^~ unexpected '=~', expecting end-of-input + ^~ unexpected '=~', ignoring it +1 !~ 2 !~ 3 + ^~ unexpected '!~'; '!~' is a non-associative operator + ^~ unexpected '!~', expecting end-of-input + ^~ unexpected '!~', ignoring it +1 <=> 2 <=> 3 + ^~~ unexpected '<=>'; '<=>' is a non-associative operator + ^~~ unexpected '<=>', expecting end-of-input + ^~~ unexpected '<=>', ignoring it + diff --git a/test/prism/errors/non_assoc_range.txt b/test/prism/errors/non_assoc_range.txt new file mode 100644 index 00000000000..12eec105940 --- /dev/null +++ b/test/prism/errors/non_assoc_range.txt @@ -0,0 +1,5 @@ +1....2 + ^ unexpected '.'; ... is a non-associative operator + ^ unexpected '.', expecting end-of-input + ^ unexpected '.', ignoring it + diff --git a/test/prism/errors/numbered_parameters_in_block_arguments.txt b/test/prism/errors/numbered_parameters_in_block_arguments.txt new file mode 100644 index 00000000000..d01999c53ea --- /dev/null +++ b/test/prism/errors/numbered_parameters_in_block_arguments.txt @@ -0,0 +1,3 @@ +foo { |_1| } + ^~ _1 is reserved for numbered parameters + diff --git a/test/prism/errors/optional_block_parameters_with_unary_operator.txt b/test/prism/errors/optional_block_parameters_with_unary_operator.txt new file mode 100644 index 00000000000..fd45f126487 --- /dev/null +++ b/test/prism/errors/optional_block_parameters_with_unary_operator.txt @@ -0,0 +1,3 @@ +foo { |a = +b| } + ^ unexpected '+'; unary calls are not allowed in this context + diff --git a/test/prism/errors/optional_block_parameters_with_unary_operator_2.txt b/test/prism/errors/optional_block_parameters_with_unary_operator_2.txt new file mode 100644 index 00000000000..ba98f36f84e --- /dev/null +++ b/test/prism/errors/optional_block_parameters_with_unary_operator_2.txt @@ -0,0 +1,3 @@ +foo { |a = -b| } + ^ unexpected '-'; unary calls are not allowed in this context + diff --git a/test/prism/errors/optional_block_parameters_with_unary_operator_3.txt b/test/prism/errors/optional_block_parameters_with_unary_operator_3.txt new file mode 100644 index 00000000000..97700598918 --- /dev/null +++ b/test/prism/errors/optional_block_parameters_with_unary_operator_3.txt @@ -0,0 +1,3 @@ +foo { |a = !b| } + ^ unexpected '!'; unary calls are not allowed in this context + diff --git a/test/prism/errors/optional_block_parameters_with_unary_operator_4.txt b/test/prism/errors/optional_block_parameters_with_unary_operator_4.txt new file mode 100644 index 00000000000..9bec68d7b35 --- /dev/null +++ b/test/prism/errors/optional_block_parameters_with_unary_operator_4.txt @@ -0,0 +1,3 @@ +foo { |a = ~b| } + ^ unexpected '~'; unary calls are not allowed in this context + diff --git a/test/prism/errors/parameter_name_ending_with_bang_or_question_mark.txt b/test/prism/errors/parameter_name_ending_with_bang_or_question_mark.txt new file mode 100644 index 00000000000..db4fd6928ab --- /dev/null +++ b/test/prism/errors/parameter_name_ending_with_bang_or_question_mark.txt @@ -0,0 +1,4 @@ +def foo(x!,y?); end + ^~ unexpected name for a parameter + ^~ unexpected name for a parameter + diff --git a/test/prism/errors/parameters_invalid_comma.txt b/test/prism/errors/parameters_invalid_comma.txt new file mode 100644 index 00000000000..2d22f7ca76e --- /dev/null +++ b/test/prism/errors/parameters_invalid_comma.txt @@ -0,0 +1,4 @@ +def f(a +,b);end +^ invalid comma + diff --git a/test/prism/errors/pre_execution_context.txt b/test/prism/errors/pre_execution_context.txt new file mode 100644 index 00000000000..18b11bae97a --- /dev/null +++ b/test/prism/errors/pre_execution_context.txt @@ -0,0 +1,4 @@ +BEGIN { 1 + } + ^ unexpected '}'; expected an expression after the operator + ^ unexpected '}', assuming it is closing the parent 'BEGIN' block + diff --git a/test/prism/errors/pre_execution_missing_brace.txt b/test/prism/errors/pre_execution_missing_brace.txt new file mode 100644 index 00000000000..e51cd0732e2 --- /dev/null +++ b/test/prism/errors/pre_execution_missing_brace.txt @@ -0,0 +1,3 @@ +BEGIN 1 } + ^ expected a `{` after `BEGIN` + diff --git a/test/prism/errors/range_and_bin_op.txt b/test/prism/errors/range_and_bin_op.txt new file mode 100644 index 00000000000..55928c409b8 --- /dev/null +++ b/test/prism/errors/range_and_bin_op.txt @@ -0,0 +1,5 @@ +1..2..3 + ^~ unexpected ..; .. is a non-associative operator + ^~ unexpected .., expecting end-of-input + ^~ unexpected .., ignoring it + diff --git a/test/prism/errors/range_and_bin_op_2.txt b/test/prism/errors/range_and_bin_op_2.txt new file mode 100644 index 00000000000..6ca91a26eb9 --- /dev/null +++ b/test/prism/errors/range_and_bin_op_2.txt @@ -0,0 +1,5 @@ +1..2.. + ^~ unexpected ..; .. is a non-associative operator + ^~ unexpected .., expecting end-of-input + ^~ unexpected .., ignoring it + diff --git a/test/prism/errors/range_and_bin_op_3.txt b/test/prism/errors/range_and_bin_op_3.txt new file mode 100644 index 00000000000..34390d0776a --- /dev/null +++ b/test/prism/errors/range_and_bin_op_3.txt @@ -0,0 +1,3 @@ +1.. || 2 + ^ unexpected '|'; expected an expression after the operator + diff --git a/test/prism/errors/range_and_bin_op_4.txt b/test/prism/errors/range_and_bin_op_4.txt new file mode 100644 index 00000000000..ce6e79e5ff5 --- /dev/null +++ b/test/prism/errors/range_and_bin_op_4.txt @@ -0,0 +1,5 @@ +1.. & 2 + ^ unexpected '&'; .. is a non-associative operator + ^ unexpected '&', expecting end-of-input + ^ unexpected '&', ignoring it + diff --git a/test/prism/errors/range_and_bin_op_5.txt b/test/prism/errors/range_and_bin_op_5.txt new file mode 100644 index 00000000000..4ed91e10520 --- /dev/null +++ b/test/prism/errors/range_and_bin_op_5.txt @@ -0,0 +1,6 @@ +1.. * 2 + ^ unexpected *; .. is a non-associative operator + ^ unexpected *, expecting end-of-input + ^ unexpected write target + ^~~ unexpected write target + diff --git a/test/prism/errors/range_and_bin_op_6.txt b/test/prism/errors/range_and_bin_op_6.txt new file mode 100644 index 00000000000..5cdd7a4f44d --- /dev/null +++ b/test/prism/errors/range_and_bin_op_6.txt @@ -0,0 +1,3 @@ +1.. / 2 + ^ unterminated regexp meets end of file; expected a closing delimiter + diff --git a/test/prism/errors/range_and_bin_op_7.txt b/test/prism/errors/range_and_bin_op_7.txt new file mode 100644 index 00000000000..3f91b5e97ff --- /dev/null +++ b/test/prism/errors/range_and_bin_op_7.txt @@ -0,0 +1,3 @@ +1.. % 2 + ^ unterminated string meets end of file + diff --git a/test/prism/errors/range_and_bin_op_8.txt b/test/prism/errors/range_and_bin_op_8.txt new file mode 100644 index 00000000000..afbf3719d55 --- /dev/null +++ b/test/prism/errors/range_and_bin_op_8.txt @@ -0,0 +1,4 @@ +1.. ** 2 + ^~ unexpected **, expecting end-of-input + ^~ unexpected **, ignoring it + diff --git a/test/prism/errors/range_doubled.txt b/test/prism/errors/range_doubled.txt new file mode 100644 index 00000000000..ef63d1bedea --- /dev/null +++ b/test/prism/errors/range_doubled.txt @@ -0,0 +1,3 @@ +p(...1...) + ^~~ unexpected range operator; .. and ... are non-associative and cannot be chained + diff --git a/test/prism/errors/rational_number_with_exponential_portion.txt b/test/prism/errors/rational_number_with_exponential_portion.txt new file mode 100644 index 00000000000..01a03d538f8 --- /dev/null +++ b/test/prism/errors/rational_number_with_exponential_portion.txt @@ -0,0 +1,4 @@ +1e1r; 1e1ri + ^ unexpected local variable or method, expecting end-of-input + ^~ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/regexp_unicode_too_short.txt b/test/prism/errors/regexp_unicode_too_short.txt new file mode 100644 index 00000000000..b6504ec9f9e --- /dev/null +++ b/test/prism/errors/regexp_unicode_too_short.txt @@ -0,0 +1,4 @@ +/\u + ^~ too short escape sequence: \u +^ unterminated regexp meets end of file; expected a closing delimiter + diff --git a/test/prism/errors/regular_expression_with_unknown_regexp_options.txt b/test/prism/errors/regular_expression_with_unknown_regexp_options.txt new file mode 100644 index 00000000000..c37291ca40f --- /dev/null +++ b/test/prism/errors/regular_expression_with_unknown_regexp_options.txt @@ -0,0 +1,3 @@ +/foo/AZaz + ^~~~~ unknown regexp options - AZaz + diff --git a/test/prism/errors/repeated_parameter_name_in_destructured_params.txt b/test/prism/errors/repeated_parameter_name_in_destructured_params.txt new file mode 100644 index 00000000000..766c235325b --- /dev/null +++ b/test/prism/errors/repeated_parameter_name_in_destructured_params.txt @@ -0,0 +1,3 @@ +def f(a, (b, (a))); end + ^ duplicated argument name + diff --git a/test/prism/errors/rest_keywords_parameters_before_required_parameters.txt b/test/prism/errors/rest_keywords_parameters_before_required_parameters.txt new file mode 100644 index 00000000000..406f326712e --- /dev/null +++ b/test/prism/errors/rest_keywords_parameters_before_required_parameters.txt @@ -0,0 +1,4 @@ +def foo(**rest, b:) + ^~ unexpected parameter order +end + diff --git a/test/prism/errors/return_1.txt b/test/prism/errors/return_1.txt new file mode 100644 index 00000000000..ca3c3494d23 --- /dev/null +++ b/test/prism/errors/return_1.txt @@ -0,0 +1,3 @@ +return 1,; + ^ unexpected ';'; expected an argument + diff --git a/test/prism/errors/return_1_2_3.txt b/test/prism/errors/return_1_2_3.txt new file mode 100644 index 00000000000..8f6dbaf1941 --- /dev/null +++ b/test/prism/errors/return_1_2_3.txt @@ -0,0 +1,7 @@ +return(1, 2, 3) + ^ unexpected ',', expecting end-of-input + ^ unexpected ',', ignoring it + ^ expected a matching `)` + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/returning_to_optional_parameters_multiple_times.txt b/test/prism/errors/returning_to_optional_parameters_multiple_times.txt new file mode 100644 index 00000000000..83ca7318509 --- /dev/null +++ b/test/prism/errors/returning_to_optional_parameters_multiple_times.txt @@ -0,0 +1,4 @@ +def foo(a, b = 1, c, d = 2, e) + ^ unexpected parameter order +end + diff --git a/test/prism/errors/semicolon_after_inheritance_operator.txt b/test/prism/errors/semicolon_after_inheritance_operator.txt new file mode 100644 index 00000000000..6b67e6048ac --- /dev/null +++ b/test/prism/errors/semicolon_after_inheritance_operator.txt @@ -0,0 +1,3 @@ +class Foo < Bar end + ^ unexpected `end`, expecting ';' or '\n' + diff --git a/test/prism/errors/setter_method_cannot_be_defined_in_an_endless_method_definition.txt b/test/prism/errors/setter_method_cannot_be_defined_in_an_endless_method_definition.txt new file mode 100644 index 00000000000..c4440ccc7ec --- /dev/null +++ b/test/prism/errors/setter_method_cannot_be_defined_in_an_endless_method_definition.txt @@ -0,0 +1,3 @@ +def a=() = 42 + ^~ invalid method name; a setter method cannot be defined in an endless method definition + diff --git a/test/prism/errors/shadow_args_in_block.txt b/test/prism/errors/shadow_args_in_block.txt new file mode 100644 index 00000000000..1e7d5f9cd45 --- /dev/null +++ b/test/prism/errors/shadow_args_in_block.txt @@ -0,0 +1,3 @@ +tap{|a;a|} + ^ duplicated argument name + diff --git a/test/prism/errors/shadow_args_in_lambda.txt b/test/prism/errors/shadow_args_in_lambda.txt new file mode 100644 index 00000000000..2399a0ebd54 --- /dev/null +++ b/test/prism/errors/shadow_args_in_lambda.txt @@ -0,0 +1,5 @@ +->a;b{} + ^ expected a `do` keyword or a `{` to open the lambda block + ^ unexpected end-of-input, assuming it is closing the parent top level context + ^ expected a lambda block beginning with `do` to end with `end` + diff --git a/test/prism/errors/singleton_class_delimiter.txt b/test/prism/errors/singleton_class_delimiter.txt new file mode 100644 index 00000000000..6a0232cb400 --- /dev/null +++ b/test/prism/errors/singleton_class_delimiter.txt @@ -0,0 +1,3 @@ +class < { _1, = 0 } + ^~ _1 is reserved for numbered parameters + diff --git a/test/prism/errors/top_level_constant_starting_with_downcased_identifier.txt b/test/prism/errors/top_level_constant_starting_with_downcased_identifier.txt new file mode 100644 index 00000000000..b7b54dd74e0 --- /dev/null +++ b/test/prism/errors/top_level_constant_starting_with_downcased_identifier.txt @@ -0,0 +1,4 @@ +::foo::A + ^ expected a constant after the `::` operator + ^~~ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/top_level_constant_with_downcased_identifier.txt b/test/prism/errors/top_level_constant_with_downcased_identifier.txt new file mode 100644 index 00000000000..032bcfaebb7 --- /dev/null +++ b/test/prism/errors/top_level_constant_with_downcased_identifier.txt @@ -0,0 +1,4 @@ +::foo + ^ expected a constant after the `::` operator + ^~~ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/trailing_comma_after_block.txt b/test/prism/errors/trailing_comma_after_block.txt new file mode 100644 index 00000000000..d25db0efbec --- /dev/null +++ b/test/prism/errors/trailing_comma_after_block.txt @@ -0,0 +1,3 @@ +p{|&,|} + ^ unexpected `,` in parameters + diff --git a/test/prism/errors/trailing_comma_in_calls.txt b/test/prism/errors/trailing_comma_in_calls.txt new file mode 100644 index 00000000000..966d911087f --- /dev/null +++ b/test/prism/errors/trailing_comma_in_calls.txt @@ -0,0 +1,3 @@ +foo 1, + ^ unexpected end-of-input; expected an argument + diff --git a/test/prism/errors/unexpected_block.txt b/test/prism/errors/unexpected_block.txt new file mode 100644 index 00000000000..2c0741cd306 --- /dev/null +++ b/test/prism/errors/unexpected_block.txt @@ -0,0 +1,3 @@ +def foo = yield(&:+) + ^~~ block argument should not be given + diff --git a/test/prism/errors/unterminated_W_list.txt b/test/prism/errors/unterminated_W_list.txt new file mode 100644 index 00000000000..89cab68abb8 --- /dev/null +++ b/test/prism/errors/unterminated_W_list.txt @@ -0,0 +1,3 @@ +%w[ +^~~ unterminated list; expected a closing delimiter for the `%w` + diff --git a/test/prism/errors/unterminated_argument_expression.txt b/test/prism/errors/unterminated_argument_expression.txt new file mode 100644 index 00000000000..c250a94becb --- /dev/null +++ b/test/prism/errors/unterminated_argument_expression.txt @@ -0,0 +1,5 @@ +a % + ^ unterminated quoted string meets end of file + ^ unexpected end-of-input; expected an expression after the operator + ^ unexpected end-of-input, assuming it is closing the parent top level context + diff --git a/test/prism/errors/unterminated_embdoc.txt b/test/prism/errors/unterminated_embdoc.txt new file mode 100644 index 00000000000..1dd9ea3ac49 --- /dev/null +++ b/test/prism/errors/unterminated_embdoc.txt @@ -0,0 +1,3 @@ +=begin +^~~~~~ embedded document meets end of file + diff --git a/test/prism/errors/unterminated_embdoc_2.txt b/test/prism/errors/unterminated_embdoc_2.txt new file mode 100644 index 00000000000..1dd9ea3ac49 --- /dev/null +++ b/test/prism/errors/unterminated_embdoc_2.txt @@ -0,0 +1,3 @@ +=begin +^~~~~~ embedded document meets end of file + diff --git a/test/prism/errors/unterminated_empty_string.txt b/test/prism/errors/unterminated_empty_string.txt new file mode 100644 index 00000000000..597102f7ee7 --- /dev/null +++ b/test/prism/errors/unterminated_empty_string.txt @@ -0,0 +1,3 @@ +" + ^ unterminated string meets end of file + diff --git a/test/prism/errors/unterminated_global_variable.txt b/test/prism/errors/unterminated_global_variable.txt new file mode 100644 index 00000000000..ce3e960b2e2 --- /dev/null +++ b/test/prism/errors/unterminated_global_variable.txt @@ -0,0 +1,3 @@ +$ +^ '$' without identifiers is not allowed as a global variable name + diff --git a/test/prism/errors/unterminated_global_variable_2.txt b/test/prism/errors/unterminated_global_variable_2.txt new file mode 100644 index 00000000000..302293b538d --- /dev/null +++ b/test/prism/errors/unterminated_global_variable_2.txt @@ -0,0 +1,3 @@ +$ +^ '$' without identifiers is not allowed as a global variable name + diff --git a/test/prism/errors/unterminated_i_list.txt b/test/prism/errors/unterminated_i_list.txt new file mode 100644 index 00000000000..c48be9971d5 --- /dev/null +++ b/test/prism/errors/unterminated_i_list.txt @@ -0,0 +1,3 @@ +%i[ +^~~ unterminated list; expected a closing delimiter for the `%i` + diff --git a/test/prism/errors/unterminated_interpolated_string.txt b/test/prism/errors/unterminated_interpolated_string.txt new file mode 100644 index 00000000000..e74a4c9e204 --- /dev/null +++ b/test/prism/errors/unterminated_interpolated_string.txt @@ -0,0 +1,3 @@ +"hello + ^ unterminated string meets end of file + diff --git a/test/prism/errors/unterminated_interpolated_symbol.txt b/test/prism/errors/unterminated_interpolated_symbol.txt new file mode 100644 index 00000000000..faa75972809 --- /dev/null +++ b/test/prism/errors/unterminated_interpolated_symbol.txt @@ -0,0 +1,3 @@ +:"# + ^ unterminated symbol; expected a closing delimiter for the interpolated symbol + diff --git a/test/prism/errors/unterminated_parenthesized_expression.txt b/test/prism/errors/unterminated_parenthesized_expression.txt new file mode 100644 index 00000000000..9025eec453d --- /dev/null +++ b/test/prism/errors/unterminated_parenthesized_expression.txt @@ -0,0 +1,4 @@ +(1 + 2 + ^ unexpected end-of-input, assuming it is closing the parent top level context + ^ expected a matching `)` + diff --git a/test/prism/errors/unterminated_regular_expression.txt b/test/prism/errors/unterminated_regular_expression.txt new file mode 100644 index 00000000000..48f3a308108 --- /dev/null +++ b/test/prism/errors/unterminated_regular_expression.txt @@ -0,0 +1,3 @@ +/hello +^ unterminated regexp meets end of file; expected a closing delimiter + diff --git a/test/prism/errors/unterminated_regular_expression_with_heredoc.txt b/test/prism/errors/unterminated_regular_expression_with_heredoc.txt new file mode 100644 index 00000000000..d4688d6c9e6 --- /dev/null +++ b/test/prism/errors/unterminated_regular_expression_with_heredoc.txt @@ -0,0 +1,4 @@ +<<-END + /b + ^ unterminated regexp meets end of file; expected a closing delimiter +END + diff --git a/test/prism/errors/unterminated_s_symbol.txt b/test/prism/errors/unterminated_s_symbol.txt new file mode 100644 index 00000000000..0f4be932b3b --- /dev/null +++ b/test/prism/errors/unterminated_s_symbol.txt @@ -0,0 +1,3 @@ +%s[abc +^~~ unterminated quoted string; expected a closing delimiter for the dynamic symbol + diff --git a/test/prism/errors/unterminated_string.txt b/test/prism/errors/unterminated_string.txt new file mode 100644 index 00000000000..89c0a08b3e8 --- /dev/null +++ b/test/prism/errors/unterminated_string.txt @@ -0,0 +1,3 @@ +'hello +^ unterminated string meets end of file + diff --git a/test/prism/errors/unterminated_unicode_brackets_should_be_a_syntax_error.txt b/test/prism/errors/unterminated_unicode_brackets_should_be_a_syntax_error.txt new file mode 100644 index 00000000000..f3ac9f29ab9 --- /dev/null +++ b/test/prism/errors/unterminated_unicode_brackets_should_be_a_syntax_error.txt @@ -0,0 +1,3 @@ +?\u{3 + ^~~~ invalid Unicode list: \u{3 + diff --git a/test/prism/errors/unterminated_xstring.txt b/test/prism/errors/unterminated_xstring.txt new file mode 100644 index 00000000000..ccd529774c3 --- /dev/null +++ b/test/prism/errors/unterminated_xstring.txt @@ -0,0 +1,3 @@ +`hello +^ expected a closing delimiter for the `%x` or backtick string + diff --git a/test/prism/errors/void_value_expression_in_arguments.txt b/test/prism/errors/void_value_expression_in_arguments.txt new file mode 100644 index 00000000000..f57aee14543 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_arguments.txt @@ -0,0 +1,17 @@ +foo(return) + ^~~~~~ unexpected void value expression +foo(1, return) + ^~~~~~ unexpected void value expression +foo(*return) + ^~~~~~ unexpected void value expression +foo(**return) + ^~~~~~ unexpected void value expression +foo(&return) + ^~~~~~ unexpected void value expression +foo(return => 1) + ^~~~~~ unexpected void value expression +foo(:a => return) + ^~~~~~ unexpected void value expression +foo(a: return) + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_array.txt b/test/prism/errors/void_value_expression_in_array.txt new file mode 100644 index 00000000000..a0e86fb1356 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_array.txt @@ -0,0 +1,15 @@ +[return] + ^~~~~~ unexpected void value expression +[1, return] + ^~~~~~ unexpected void value expression +[ return => 1 ] + ^~~~~~ unexpected void value expression +[ 1 => return ] + ^~~~~~ unexpected void value expression +[ a: return ] + ^~~~~~ unexpected void value expression +[ *return ] + ^~~~~~ unexpected void value expression +[ **return ] + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_assignment.txt b/test/prism/errors/void_value_expression_in_assignment.txt new file mode 100644 index 00000000000..c651d7f39ee --- /dev/null +++ b/test/prism/errors/void_value_expression_in_assignment.txt @@ -0,0 +1,9 @@ +a = return + ^~~~~~ unexpected void value expression +a = 1, return + ^~~~~~ unexpected void value expression +a, b = return, 1 + ^~~~~~ unexpected void value expression +a, b = 1, *return + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_begin_statement.txt b/test/prism/errors/void_value_expression_in_begin_statement.txt new file mode 100644 index 00000000000..aa8f1ded964 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_begin_statement.txt @@ -0,0 +1,21 @@ +x = return 1 + ^~~~~~~~ unexpected void value expression +x = return, 1 + ^~~~~~ unexpected void value expression +x = 1, return + ^~~~~~ unexpected void value expression +x, y = return + ^~~~~~ unexpected void value expression +x = begin return ensure end + ^~~~~~ unexpected void value expression +x = begin ensure return end + ^~~~~~ unexpected void value expression +x = begin return ensure return end + ^~~~~~ unexpected void value expression +x = begin return; rescue; return end + ^~~~~~ unexpected void value expression +x = begin return; rescue; return; else return end + ^~~~~~ unexpected void value expression +x = begin; return; rescue; retry; end + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_binary_call.txt b/test/prism/errors/void_value_expression_in_binary_call.txt new file mode 100644 index 00000000000..096b42be4de --- /dev/null +++ b/test/prism/errors/void_value_expression_in_binary_call.txt @@ -0,0 +1,11 @@ +1 + (return) + ^~~~~~ unexpected void value expression +(return) + 1 + ^~~~~~ unexpected void value expression +1 and (return) +(return) and 1 + ^~~~~~ unexpected void value expression +1 or (return) +(return) or 1 + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_call.txt b/test/prism/errors/void_value_expression_in_call.txt new file mode 100644 index 00000000000..90e6481c4ce --- /dev/null +++ b/test/prism/errors/void_value_expression_in_call.txt @@ -0,0 +1,11 @@ +(return).foo + ^~~~~~ unexpected void value expression +(return).(1) + ^~~~~~ unexpected void value expression +(return)[1] + ^~~~~~ unexpected void value expression +(return)[1] = 2 + ^~~~~~ unexpected void value expression +(return)::foo + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_constant_path.txt b/test/prism/errors/void_value_expression_in_constant_path.txt new file mode 100644 index 00000000000..1dab6902a27 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_constant_path.txt @@ -0,0 +1,5 @@ +(return)::A + ^~~~~~ unexpected void value expression +class (return)::A; end + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_def.txt b/test/prism/errors/void_value_expression_in_def.txt new file mode 100644 index 00000000000..fed52a66776 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_def.txt @@ -0,0 +1,10 @@ +def (return).x + ^~~~~~ unexpected void value expression +end +def x(a = return) + ^~~~~~ unexpected void value expression +end +def x(a: return) + ^~~~~~ unexpected void value expression +end + diff --git a/test/prism/errors/void_value_expression_in_expression.txt b/test/prism/errors/void_value_expression_in_expression.txt new file mode 100644 index 00000000000..f6165a7ba63 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_expression.txt @@ -0,0 +1,19 @@ +(return) ? 1 : 1 + ^~~~~~ unexpected void value expression +(return)..1 + ^~~~~~ unexpected void value expression +1..(return) + ^~~~~~ unexpected void value expression +(return)...1 + ^~~~~~ unexpected void value expression +1...(return) + ^~~~~~ unexpected void value expression +(..(return)) + ^~~~~~ unexpected void value expression +(...(return)) + ^~~~~~ unexpected void value expression +((return)..) + ^~~~~~ unexpected void value expression +((return)...) + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_hash.txt b/test/prism/errors/void_value_expression_in_hash.txt new file mode 100644 index 00000000000..77955114437 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_hash.txt @@ -0,0 +1,9 @@ +{ return => 1 } + ^~~~~~ unexpected void value expression +{ 1 => return } + ^~~~~~ unexpected void value expression +{ a: return } + ^~~~~~ unexpected void value expression +{ **return } + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_modifier.txt b/test/prism/errors/void_value_expression_in_modifier.txt new file mode 100644 index 00000000000..7d7b444e331 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_modifier.txt @@ -0,0 +1,13 @@ +1 if (return) + ^~~~~~ unexpected void value expression +1 unless (return) + ^~~~~~ unexpected void value expression +1 while (return) + ^~~~~~ unexpected void value expression +1 until (return) + ^~~~~~ unexpected void value expression +(return) => a + ^~~~~~ unexpected void value expression +(return) in a + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_statement.txt b/test/prism/errors/void_value_expression_in_statement.txt new file mode 100644 index 00000000000..87dbfa5cc92 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_statement.txt @@ -0,0 +1,26 @@ +if (return) + ^~~~~~ unexpected void value expression +end +unless (return) + ^~~~~~ unexpected void value expression +end +while (return) + ^~~~~~ unexpected void value expression +end +until (return) + ^~~~~~ unexpected void value expression +end +case (return) + ^~~~~~ unexpected void value expression +when 1 +end +class A < (return) + ^~~~~~ unexpected void value expression +end +class << (return) + ^~~~~~ unexpected void value expression +end +for x in (return) + ^~~~~~ unexpected void value expression +end + diff --git a/test/prism/errors/void_value_expression_in_unary_call.txt b/test/prism/errors/void_value_expression_in_unary_call.txt new file mode 100644 index 00000000000..61e849255c7 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_unary_call.txt @@ -0,0 +1,5 @@ ++(return) + ^~~~~~ unexpected void value expression +not return + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/while_endless_method.txt b/test/prism/errors/while_endless_method.txt new file mode 100644 index 00000000000..6f062d89d0f --- /dev/null +++ b/test/prism/errors/while_endless_method.txt @@ -0,0 +1,5 @@ +while def f = g do end + ^ expected a predicate expression for the `while` statement + ^ unexpected end-of-input, assuming it is closing the parent top level context + ^ expected an `end` to close the `while` statement + diff --git a/test/prism/errors/writing_numbered_parameter.txt b/test/prism/errors/writing_numbered_parameter.txt new file mode 100644 index 00000000000..17dcc6e8f03 --- /dev/null +++ b/test/prism/errors/writing_numbered_parameter.txt @@ -0,0 +1,3 @@ +-> { _1 = 0 } + ^~ _1 is reserved for numbered parameters + diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 280bf63a24b..f46cb942a20 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -4,1952 +4,71 @@ module Prism class ErrorsTest < TestCase - include DSL + base = File.expand_path("errors", __dir__) + filepaths = Dir["*.txt", base: base] - def test_constant_path_with_invalid_token_after - assert_error_messages "A::$b", [ - "expected a constant after the `::` operator", - "unexpected global variable, expecting end-of-input" + if RUBY_VERSION < "3.0" + filepaths -= [ + "cannot_assign_to_a_reserved_numbered_parameter.txt", + "writing_numbered_parameter.txt", + "targeting_numbered_parameter.txt", + "defining_numbered_parameter.txt", + "defining_numbered_parameter_2.txt", + "numbered_parameters_in_block_arguments.txt" ] end - def test_module_name_recoverable - expected = ModuleNode( - [], - Location(), - ConstantReadNode(:Parent), - StatementsNode( - [ModuleNode([], Location(), MissingNode(), nil, Location(), :"")] - ), - Location(), - :Parent - ) - - assert_errors expected, "module Parent module end", [ - ["unexpected constant path after `module`; class/module name must be CONSTANT", 14..20], - ["unexpected 'end', assuming it is closing the parent module definition", 21..24] - ] - end - - def test_for_loops_index_missing - expected = ForNode( - MissingNode(), - expression("1..10"), - StatementsNode([expression("i")]), - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "for in 1..10\ni\nend", [ - ["expected an index after `for`", 0..3] - ] - end - - def test_for_loops_only_end - expected = ForNode( - MissingNode(), - MissingNode(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "for end", [ - ["expected an index after `for`", 0..3], - ["expected an `in` after the index in a `for` statement", 3..3], - ["expected a collection after the `in` in a `for` statement", 3..3] - ] - end - - def test_pre_execution_missing_brace - expected = PreExecutionNode( - StatementsNode([expression("1")]), - Location(), - Location(), - Location() - ) - - assert_errors expected, "BEGIN 1 }", [ - ["expected a `{` after `BEGIN`", 5..5] - ] - end - - def test_pre_execution_context - expected = PreExecutionNode( - StatementsNode([ - CallNode( - 0, - expression("1"), - nil, - :+, - Location(), - nil, - ArgumentsNode(0, [MissingNode()]), - nil, - nil - ) - ]), - Location(), - Location(), - Location() - ) - - assert_errors expected, "BEGIN { 1 + }", [ - ["expected an expression after the operator", 10..11], - ["unexpected '}', assuming it is closing the parent 'BEGIN' block", 12..13] - ] - end - - def test_unterminated_embdoc - message = "embedded document meets end of file" - assert_error_messages "=begin", [message] - assert_error_messages "=begin\n", [message] - - refute_error_messages "=begin\n=end" - refute_error_messages "=begin\n=end\0" - refute_error_messages "=begin\n=end\C-d" - refute_error_messages "=begin\n=end\C-z" - end - - def test_unterminated_i_list - assert_errors expression("%i["), "%i[", [ - ["unterminated list; expected a closing delimiter for the `%i`", 0..3] - ] - end - - def test_unterminated_w_list - assert_errors expression("%w["), "%w[", [ - ["unterminated list; expected a closing delimiter for the `%w`", 0..3] - ] - end - - def test_unterminated_W_list - assert_errors expression("%W["), "%W[", [ - ["unterminated list; expected a closing delimiter for the `%W`", 0..3] - ] - end - - def test_unterminated_regular_expression - assert_errors expression("/hello"), "/hello", [ - ["unterminated regexp meets end of file; expected a closing delimiter", 0..1] - ] - end - - def test_unterminated_regular_expression_with_heredoc - source = "<<-END + /b\nEND\n" - - assert_errors expression(source), source, [ - ["unterminated regexp meets end of file; expected a closing delimiter", 9..10] - ] - end - - def test_unterminated_xstring - assert_errors expression("`hello"), "`hello", [ - ["expected a closing delimiter for the `%x` or backtick string", 0..1] - ] - end - - def test_unterminated_interpolated_string - expr = expression('"hello') - assert_errors expr, '"hello', [ - ["unterminated string meets end of file", 6..6] - ] - assert_equal expr.unescaped, "hello" - assert_equal expr.closing, "" - end - - def test_unterminated_string - expr = expression("'hello") - assert_errors expr, "'hello", [ - ["unterminated string meets end of file", 0..1] - ] - assert_equal expr.unescaped, "hello" - assert_equal expr.closing, "" - end - - def test_unterminated_empty_string - expr = expression('"') - assert_errors expr, '"', [ - ["unterminated string meets end of file", 1..1] - ] - assert_equal expr.unescaped, "" - assert_equal expr.closing, "" - end - - def test_incomplete_instance_var_string - assert_errors expression('%@#@@#'), '%@#@@#', [ - ["'@' without identifiers is not allowed as an instance variable name", 4..5], - ["unexpected instance variable, expecting end-of-input", 4..5] - ] - end - - def test_unterminated_s_symbol - assert_errors expression("%s[abc"), "%s[abc", [ - ["unterminated quoted string; expected a closing delimiter for the dynamic symbol", 0..3] - ] - end - - def test_unterminated_parenthesized_expression - assert_errors expression('(1 + 2'), '(1 + 2', [ - ["unexpected end of file, expecting end-of-input", 6..6], - ["unexpected end of file, assuming it is closing the parent top level context", 6..6], - ["expected a matching `)`", 6..6] - ] - end - - def test_missing_terminator_in_parentheses - assert_error_messages "(0 0)", [ - "unexpected integer, expecting end-of-input" - ] - end - - def test_unterminated_argument_expression - assert_errors expression('a %'), 'a %', [ - ["invalid `%` token", 2..3], - ["expected an expression after the operator", 2..3], - ["unexpected end of file, assuming it is closing the parent top level context", 3..3] - ] - end - - def test_unterminated_interpolated_symbol - assert_error_messages ":\"#", [ - "expected a closing delimiter for the interpolated symbol" - ] - end - - def test_cr_without_lf_in_percent_expression - assert_errors expression("%\r"), "%\r", [ - ["invalid `%` token", 0..2], - ] - end - - def test_1_2_3 - assert_errors expression("(1, 2, 3)"), "(1, 2, 3)", [ - ["unexpected ',', expecting end-of-input", 2..3], - ["unexpected ',', ignoring it", 2..3], - ["expected a matching `)`", 2..2], - ["unexpected ',', expecting end-of-input", 2..3], - ["unexpected ',', ignoring it", 2..3], - ["unexpected ',', expecting end-of-input", 5..6], - ["unexpected ',', ignoring it", 5..6], - ["unexpected ')', expecting end-of-input", 8..9], - ["unexpected ')', ignoring it", 8..9] - ] - end - - def test_return_1_2_3 - assert_error_messages "return(1, 2, 3)", [ - "unexpected ',', expecting end-of-input", - "unexpected ',', ignoring it", - "expected a matching `)`", - "unexpected ')', expecting end-of-input", - "unexpected ')', ignoring it" - ] - end - - def test_return_1 - assert_errors expression("return 1,;"), "return 1,;", [ - ["expected an argument", 8..9] - ] - end - - def test_next_1_2_3 - assert_errors expression("next(1, 2, 3)"), "next(1, 2, 3)", [ - ["unexpected ',', expecting end-of-input", 6..7], - ["unexpected ',', ignoring it", 6..7], - ["expected a matching `)`", 6..6], - ["Invalid next", 0..12], - ["unexpected ')', expecting end-of-input", 12..13], - ["unexpected ')', ignoring it", 12..13] - ] - end - - def test_next_1 - assert_errors expression("next 1,;"), "next 1,;", [ - ["expected an argument", 6..7], - ["Invalid next", 0..7] - ] - end - - def test_break_1_2_3 - assert_errors expression("break(1, 2, 3)"), "break(1, 2, 3)", [ - ["unexpected ',', expecting end-of-input", 7..8], - ["unexpected ',', ignoring it", 7..8], - ["expected a matching `)`", 7..7], - ["Invalid break", 0..13], - ["unexpected ')', expecting end-of-input", 13..14], - ["unexpected ')', ignoring it", 13..14] - ] - end - - def test_break_1 - assert_errors expression("break 1,;"), "break 1,;", [ - ["expected an argument", 7..8], - ["Invalid break", 0..8] - ] - end - - def test_argument_forwarding_when_parent_is_not_forwarding - assert_errors expression('def a(x, y, z); b(...); end'), 'def a(x, y, z); b(...); end', [ - ["unexpected ... when the parent method is not forwarding", 18..21] - ] - end - - def test_argument_forwarding_only_effects_its_own_internals - assert_errors expression('def a(...); b(...); end; def c(x, y, z); b(...); end'), - 'def a(...); b(...); end; def c(x, y, z); b(...); end', [ - ["unexpected ... when the parent method is not forwarding", 43..46] - ] - end - - def test_top_level_constant_with_downcased_identifier - assert_error_messages "::foo", [ - "expected a constant after the `::` operator", - "unexpected local variable or method, expecting end-of-input" - ] - end - - def test_top_level_constant_starting_with_downcased_identifier - assert_error_messages "::foo::A", [ - "expected a constant after the `::` operator", - "unexpected local variable or method, expecting end-of-input" - ] - end - - def test_aliasing_global_variable_with_non_global_variable - assert_errors expression("alias $a b"), "alias $a b", [ - ["invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable", 9..10] - ] - end - - def test_aliasing_non_global_variable_with_global_variable - assert_errors expression("alias a $b"), "alias a $b", [ - ["invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable", 8..10] - ] - end - - def test_aliasing_global_variable_with_global_number_variable - assert_errors expression("alias $a $1"), "alias $a $1", [ - ["invalid argument being passed to `alias`; can't make alias for the number variables", 9..11] - ] - end - - def test_def_with_expression_receiver_and_no_identifier - assert_errors expression("def (a); end"), "def (a); end", [ - ["expected a `.` or `::` after the receiver in a method definition", 7..7], - ["unexpected ';'; expected a method name", 7..8] - ] - end - - def test_def_with_multiple_statements_receiver - assert_errors expression("def (\na\nb\n).c; end"), "def (\na\nb\n).c; end", [ - ["expected a matching `)`", 8..8], - ["expected a `.` or `::` after the receiver in a method definition", 8..8], - ["expected a delimiter to close the parameters", 9..9], - ["unexpected ')', ignoring it", 10..11], - ["unexpected '.', ignoring it", 11..12] - ] - end - - def test_def_with_empty_expression_receiver - assert_errors expression("def ().a; end"), "def ().a; end", [ - ["expected a receiver for the method definition", 4..5] - ] - end - - def test_block_beginning_with_brace_and_ending_with_end - assert_error_messages "x.each { x end", [ - "unexpected 'end', expecting end-of-input", - "unexpected 'end', ignoring it", - "unexpected end of file, assuming it is closing the parent top level context", - "expected a block beginning with `{` to end with `}`" - ] - end - - def test_double_splat_followed_by_splat_argument - expected = CallNode( - CallNodeFlags::IGNORE_VISIBILITY, - nil, - nil, - :a, - Location(), - Location(), - ArgumentsNode( - ArgumentsNodeFlags::CONTAINS_KEYWORDS | ArgumentsNodeFlags::CONTAINS_KEYWORD_SPLAT, - [ - KeywordHashNode(0, [AssocSplatNode(expression("kwargs"), Location())]), - SplatNode(Location(), expression("args")) - ] - ), - Location(), - nil - ) - - assert_errors expected, "a(**kwargs, *args)", [ - ["unexpected `*` splat argument after a `**` keyword splat argument", 12..17] - ] - end - - def test_arguments_after_block - expected = CallNode( - CallNodeFlags::IGNORE_VISIBILITY, - nil, - nil, - :a, - Location(), - Location(), - ArgumentsNode(0, [expression("foo")]), - Location(), - BlockArgumentNode(expression("block"), Location()) - ) - - assert_errors expected, "a(&block, foo)", [ - ["unexpected argument after a block argument", 10..13] - ] - end - - def test_arguments_binding_power_for_and - assert_error_messages "foo(*bar and baz)", [ - "unexpected 'and'; expected a `)` to close the arguments", - "unexpected ')', expecting end-of-input", - "unexpected ')', ignoring it" - ] - end - - def test_splat_argument_after_keyword_argument - expected = CallNode( - CallNodeFlags::IGNORE_VISIBILITY, - nil, - nil, - :a, - Location(), - Location(), - ArgumentsNode(ArgumentsNodeFlags::CONTAINS_KEYWORDS, [ - KeywordHashNode(1, [ - AssocNode( - SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, nil, Location(), Location(), "foo"), - expression("bar"), - nil - ) - ]), - SplatNode(Location(), expression("args")) - ]), - Location(), - nil - ) - - assert_errors expected, "a(foo: bar, *args)", [ - ["unexpected `*` splat argument after a `**` keyword splat argument", 12..17] - ] - end - - def test_module_definition_in_method_body - expected = DefNode( - :foo, - Location(), - nil, - nil, - StatementsNode([ModuleNode([], Location(), ConstantReadNode(:A), nil, Location(), :A)]), - [], - Location(), - nil, - nil, - nil, - nil, - Location() - ) - - assert_errors expected, "def foo;module A;end;end", [ - ["unexpected module definition in method body", 8..14] - ] - end - - def test_module_definition_in_method_body_within_block - expected = DefNode( - :foo, - Location(), - nil, - nil, - StatementsNode( - [CallNode( - CallNodeFlags::IGNORE_VISIBILITY, - nil, - nil, - :bar, - Location(), - nil, - nil, - nil, - BlockNode( - [], - nil, - StatementsNode([ModuleNode([], Location(), ConstantReadNode(:Foo), nil, Location(), :Foo)]), - Location(), - Location() - ) - )] - ), - [], - Location(), - nil, - nil, - nil, - nil, - Location() - ) - - assert_errors expected, <<~RUBY, [["unexpected module definition in method body", 21..27]] - def foo - bar do - module Foo;end - end - end - RUBY - end - - def test_module_definition_in_method_defs - source = <<~RUBY - def foo(bar = module A;end);end - def foo;rescue;module A;end;end - def foo;ensure;module A;end;end - RUBY - message = "unexpected module definition in method body" - assert_errors expression(source), source, [ - [message, 14..20], - [message, 47..53], - [message, 79..85], - ] - end - - def test_class_definition_in_method_body - expected = DefNode( - :foo, - Location(), - nil, - nil, - StatementsNode( - [ClassNode( - [], - Location(), - ConstantReadNode(:A), - nil, - nil, - nil, - Location(), - :A - )] - ), - [], - Location(), - nil, - nil, - nil, - nil, - Location() - ) - - assert_errors expected, "def foo;class A;end;end", [ - ["unexpected class definition in method body", 8..13] - ] - end - - def test_class_definition_in_method_defs - source = <<~RUBY - def foo(bar = class A;end);end - def foo;rescue;class A;end;end - def foo;ensure;class A;end;end - RUBY - message = "unexpected class definition in method body" - assert_errors expression(source), source, [ - [message, 14..19], - [message, 46..51], - [message, 77..82], - ] - end - - def test_bad_arguments - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode([ - RequiredParameterNode(0, :A), - RequiredParameterNode(0, :@a), - RequiredParameterNode(0, :$A), - RequiredParameterNode(0, :@@a), - ], [], nil, [], [], nil, nil), - nil, - [:A, :@a, :$A, :@@a], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(A, @a, $A, @@a);end", [ - ["invalid formal argument; formal argument cannot be a constant", 8..9], - ["invalid formal argument; formal argument cannot be an instance variable", 11..13], - ["invalid formal argument; formal argument cannot be a global variable", 15..17], - ["invalid formal argument; formal argument cannot be a class variable", 19..22], - ] - end - - if RUBY_VERSION >= "3.0" - def test_cannot_assign_to_a_reserved_numbered_parameter - expected = BeginNode( - Location(), - StatementsNode([ - LocalVariableWriteNode(:_1, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_2, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_3, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_4, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_5, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_6, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_7, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_8, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_9, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_10, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()) - ]), - nil, - nil, - nil, - Location() - ) - source = <<~RUBY - begin - _1=:a;_2=:a;_3=:a;_4=:a;_5=:a - _6=:a;_7=:a;_8=:a;_9=:a;_10=:a - end - RUBY - assert_errors expected, source, [ - ["_1 is reserved for numbered parameters", 8..10], - ["_2 is reserved for numbered parameters", 14..16], - ["_3 is reserved for numbered parameters", 20..22], - ["_4 is reserved for numbered parameters", 26..28], - ["_5 is reserved for numbered parameters", 32..34], - ["_6 is reserved for numbered parameters", 40..42], - ["_7 is reserved for numbered parameters", 46..48], - ["_8 is reserved for numbered parameters", 52..54], - ["_9 is reserved for numbered parameters", 58..60], - ] - end - end - - def test_do_not_allow_trailing_commas_in_method_parameters - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode( - [RequiredParameterNode(0, :a), RequiredParameterNode(0, :b), RequiredParameterNode(0, :c)], - [], - nil, - [], - [], - nil, - nil - ), - nil, - [:a, :b, :c], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(a,b,c,);end", [ - ["unexpected `,` in parameters", 13..14] - ] - end - - def test_do_not_allow_trailing_commas_in_lambda_parameters - expected = LambdaNode( - [:a, :b], - Location(), - Location(), - Location(), - BlockParametersNode( - ParametersNode([RequiredParameterNode(0, :a), RequiredParameterNode(0, :b)], [], nil, [], [], nil, nil), - [], - Location(), - Location() - ), - nil - ) - assert_errors expected, "-> (a, b, ) {}", [ - ["unexpected `,` in parameters", 8..9] - ] - end - - def test_do_not_allow_multiple_codepoints_in_a_single_character_literal - expected = StringNode(StringFlags::FORCED_UTF8_ENCODING, Location(), Location(), nil, "\u0001\u0002") - - assert_errors expected, '?\u{0001 0002}', [ - ["invalid Unicode escape sequence; Multiple codepoints at single character literal are disallowed", 9..12] - ] - end - - def test_invalid_hex_escape - assert_errors expression('"\\xx"'), '"\\xx"', [ - ["invalid hex escape sequence", 1..3], - ] - end - - def test_do_not_allow_more_than_6_hexadecimal_digits_in_u_Unicode_character_notation - expected = StringNode(0, Location(), Location(), Location(), "\u0001") - - assert_errors expected, '"\u{0000001}"', [ - ["invalid Unicode escape sequence; maximum length is 6 digits", 4..11], - ] - end - - def test_do_not_allow_characters_other_than_0_9_a_f_and_A_F_in_u_Unicode_character_notation - expected = StringNode(0, Location(), Location(), Location(), "\u0000z}") - - assert_errors expected, '"\u{000z}"', [ - ["invalid Unicode escape sequence", 7..7], - ] - end - - def test_unterminated_unicode_brackets_should_be_a_syntax_error - assert_errors expression('?\\u{3'), '?\\u{3', [ - ["invalid Unicode escape sequence; needs closing `}`", 1..5], - ] - end - - def test_method_parameters_after_block - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode( - [], - [], - nil, - [RequiredParameterNode(0, :a)], - [], - nil, - BlockParameterNode(0, :block, Location(), Location()) - ), - nil, - [:block, :a], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - assert_errors expected, "def foo(&block, a)\nend", [ - ["unexpected parameter order", 16..17] - ] - end - - def test_method_with_arguments_after_anonymous_block - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode([], [], nil, [RequiredParameterNode(0, :a)], [], nil, BlockParameterNode(0, nil, nil, Location())), - nil, - [:a], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(&, a)\nend", [ - ["unexpected parameter order", 11..12] - ] - end - - def test_method_parameters_after_arguments_forwarding - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode( - [], - [], - nil, - [RequiredParameterNode(0, :a)], - [], - ForwardingParameterNode(), - nil - ), - nil, - [:a], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - assert_errors expected, "def foo(..., a)\nend", [ - ["unexpected parameter order", 13..14] - ] - end - - def test_keywords_parameters_before_required_parameters - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode( - [], - [], - nil, - [RequiredParameterNode(0, :a)], - [RequiredKeywordParameterNode(0, :b, Location())], - nil, - nil - ), - nil, - [:b, :a], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - assert_errors expected, "def foo(b:, a)\nend", [ - ["unexpected parameter order", 12..13] - ] - end - - def test_rest_keywords_parameters_before_required_parameters - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode( - [], - [], - nil, - [], - [RequiredKeywordParameterNode(0, :b, Location())], - KeywordRestParameterNode(0, :rest, Location(), Location()), - nil - ), - nil, - [:rest, :b], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(**rest, b:)\nend", [ - ["unexpected parameter order", 16..18] - ] - end - - def test_double_arguments_forwarding - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode([], [], nil, [], [], ForwardingParameterNode(), nil), - nil, - [], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(..., ...)\nend", [ - ["unexpected parameter order", 13..16] - ] - end - - def test_multiple_error_in_parameters_order - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode( - [], - [], - nil, - [RequiredParameterNode(0, :a)], - [RequiredKeywordParameterNode(0, :b, Location())], - KeywordRestParameterNode(0, :args, Location(), Location()), - nil - ), - nil, - [:args, :a, :b], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(**args, a, b:)\nend", [ - ["unexpected parameter order", 16..17], - ["unexpected parameter order", 19..21] - ] - end - - def test_switching_to_optional_arguments_twice - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode( - [], - [], - nil, - [RequiredParameterNode(0, :a)], - [RequiredKeywordParameterNode(0, :b, Location())], - KeywordRestParameterNode(0, :args, Location(), Location()), - nil - ), - nil, - [:args, :a, :b], - Location(), - nil, - Location(), - Location(), - nil, - Location(), - ) - - assert_errors expected, "def foo(**args, a, b:)\nend", [ - ["unexpected parameter order", 16..17], - ["unexpected parameter order", 19..21] - ] - end - - def test_switching_to_named_arguments_twice - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode( - [], - [], - nil, - [RequiredParameterNode(0, :a)], - [RequiredKeywordParameterNode(0, :b, Location())], - KeywordRestParameterNode(0, :args, Location(), Location()), - nil - ), - nil, - [:args, :a, :b], - Location(), - nil, - Location(), - Location(), - nil, - Location(), - ) - - assert_errors expected, "def foo(**args, a, b:)\nend", [ - ["unexpected parameter order", 16..17], - ["unexpected parameter order", 19..21] - ] - end - - def test_returning_to_optional_parameters_multiple_times - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode( - [RequiredParameterNode(0, :a)], - [ - OptionalParameterNode(0, :b, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL, 1)), - OptionalParameterNode(0, :d, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL, 2)) - ], - nil, - [RequiredParameterNode(0, :c), RequiredParameterNode(0, :e)], - [], - nil, - nil - ), - nil, - [:a, :b, :c, :d, :e], - Location(), - nil, - Location(), - Location(), - nil, - Location(), - ) - - assert_errors expected, "def foo(a, b = 1, c, d = 2, e)\nend", [ - ["unexpected parameter order", 23..24] - ] - end - - def test_case_without_when_clauses_errors_on_else_clause - expected = CaseMatchNode( - SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), - [], - ElseNode(Location(), nil, Location()), - Location(), - Location() - ) - - assert_errors expected, "case :a\nelse\nend", [ - ["expected a `when` or `in` clause after `case`", 0..4] - ] - end - - def test_case_without_clauses - expected = CaseNode( - SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), - [], - nil, - Location(), - Location() - ) - - assert_errors expected, "case :a\nend", [ - ["expected a `when` or `in` clause after `case`", 0..4] - ] - end - - def test_setter_method_cannot_be_defined_in_an_endless_method_definition - expected = DefNode( - :a=, - Location(), - nil, - nil, - StatementsNode([IntegerNode(IntegerBaseFlags::DECIMAL, 42)]), - [], - Location(), - nil, - Location(), - Location(), - Location(), - nil - ) - - assert_errors expected, "def a=() = 42", [ - ["invalid method name; a setter method cannot be defined in an endless method definition", 4..6] - ] - end - - def test_do_not_allow_forward_arguments_in_lambda_literals - expected = LambdaNode( - [], - Location(), - Location(), - Location(), - BlockParametersNode(ParametersNode([], [], nil, [], [], ForwardingParameterNode(), nil), [], Location(), Location()), - nil - ) - - assert_errors expected, "->(...) {}", [ - ["unexpected ... when the parent method is not forwarding", 3..6] - ] - end - - def test_do_not_allow_forward_arguments_in_blocks - expected = CallNode( - CallNodeFlags::IGNORE_VISIBILITY, - nil, - nil, - :a, - Location(), - nil, - nil, - nil, - BlockNode( - [], - BlockParametersNode(ParametersNode([], [], nil, [], [], ForwardingParameterNode(), nil), [], Location(), Location()), - nil, - Location(), - Location() - ) - ) - - assert_errors expected, "a {|...|}", [ - ["unexpected ... when the parent method is not forwarding", 4..7] - ] - end - - def test_dont_allow_return_inside_class_body - expected = ClassNode( - [], - Location(), - ConstantReadNode(:A), - nil, - nil, - StatementsNode([ReturnNode(0, Location(), nil)]), - Location(), - :A - ) - - assert_errors expected, "class A; return; end", [ - ["Invalid return in class/module body", 9..15] - ] - end - - def test_dont_allow_return_inside_module_body - expected = ModuleNode( - [], - Location(), - ConstantReadNode(:A), - StatementsNode([ReturnNode(0, Location(), nil)]), - Location(), - :A - ) - - assert_errors expected, "module A; return; end", [ - ["Invalid return in class/module body", 10..16] - ] - end - - def test_dont_allow_setting_to_back_and_nth_reference - expected = BeginNode( - Location(), - StatementsNode([ - GlobalVariableWriteNode(:$+, Location(), NilNode(), Location()), - GlobalVariableWriteNode(:$1466, Location(), NilNode(), Location()) - ]), - nil, - nil, - nil, - Location() - ) - - assert_errors expected, "begin\n$+ = nil\n$1466 = nil\nend", [ - ["Can't set variable $+", 6..8], - ["Can't set variable $1466", 15..20] - ] - end - - def test_duplicated_parameter_names - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode([RequiredParameterNode(0, :a), RequiredParameterNode(0, :b), RequiredParameterNode(ParameterFlags::REPEATED_PARAMETER, :a)], [], nil, [], [], nil, nil), - nil, - [:a, :b], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(a,b,a);end", [ - ["duplicated argument name", 12..13] - ] - - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode([RequiredParameterNode(0, :a), RequiredParameterNode(0, :b)], [], RestParameterNode(ParameterFlags::REPEATED_PARAMETER, :a, Location(), Location()), [], [], nil, nil), - nil, - [:a, :b], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(a,b,*a);end", [ - ["duplicated argument name", 13..14] - ] - - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode([RequiredParameterNode(0, :a), RequiredParameterNode(0, :b)], [], nil, [], [], KeywordRestParameterNode(ParameterFlags::REPEATED_PARAMETER, :a, Location(), Location()), nil), - nil, - [:a, :b], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(a,b,**a);end", [ - ["duplicated argument name", 14..15] - ] - - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode([RequiredParameterNode(0, :a), RequiredParameterNode(0, :b)], [], nil, [], [], nil, BlockParameterNode(ParameterFlags::REPEATED_PARAMETER, :a, Location(), Location())), - nil, - [:a, :b], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(a,b,&a);end", [ - ["duplicated argument name", 13..14] - ] - - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode([], [OptionalParameterNode(0, :a, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL, 1))], RestParameterNode(0, :c, Location(), Location()), [RequiredParameterNode(0, :b)], [], nil, nil), - nil, - [:a, :b, :c], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(a = 1,b,*c);end", [["unexpected parameter `*`", 16..17]] - end - - def test_content_after_unterminated_heredoc - receiver = StringNode(0, Location(), Location(), Location(), "") - expected = CallNode(0, receiver, Location(), :foo, Location(), nil, nil, nil, nil) - - assert_errors expected, "<<~FOO.foo\n", [ - ["unterminated heredoc; can't find string \"FOO\"", 3..6] - ] - end - - def test_invalid_message_name - result = Prism.parse("+.@foo,+=foo") - assert_equal :"", result.value.statements.body.first.write_name - end - - def test_invalid_operator_write_fcall - source = "foo! += 1" - assert_errors expression(source), source, [ - ["unexpected write target", 0..4] - ] - end - - def test_invalid_operator_write_dot - source = "foo.+= 1" - assert_errors expression(source), source, [ - ["unexpected write target", 5..6] - ] - end - - def test_unterminated_global_variable - message = "'$' without identifiers is not allowed as a global variable name" - - assert_errors expression("$"), "$", [[message, 0..1]] - assert_errors expression("$ "), "$ ", [[message, 0..1]] - end - - def test_invalid_global_variable_write - assert_errors expression("$',"), "$',", [ - ["Can't set variable $'", 0..2], - ["unexpected write target", 0..2] - ] - end - - def test_invalid_multi_target - error_messages = ["unexpected write target"] - - assert_error_messages "foo,", error_messages - assert_error_messages "foo = 1; foo,", error_messages - assert_error_messages "foo.bar,", error_messages - assert_error_messages "*foo,", error_messages - assert_error_messages "@foo,", error_messages - assert_error_messages "@@foo,", error_messages - assert_error_messages "$foo,", error_messages - assert_error_messages "$1,", ["Can't set variable $1", *error_messages] - assert_error_messages "$+,", ["Can't set variable $+", *error_messages] - assert_error_messages "Foo,", error_messages - assert_error_messages "::Foo,", error_messages - assert_error_messages "Foo::Foo,", error_messages - assert_error_messages "Foo::foo,", error_messages - assert_error_messages "foo[foo],", error_messages - assert_error_messages "(foo, bar)", error_messages - assert_error_messages "foo((foo, bar))", error_messages - assert_error_messages "foo((*))", error_messages - assert_error_messages "foo(((foo, bar), *))", error_messages - assert_error_messages "(foo, bar) + 1", error_messages - assert_error_messages "(foo, bar) in baz", error_messages - end - - def test_call_with_block_and_write - source = "foo {} &&= 1" - assert_errors expression(source), source, [ - ["unexpected write target", 0..6], - ["unexpected operator after a call with a block", 7..10] - ] - end - - def test_call_with_block_or_write - source = "foo {} ||= 1" - assert_errors expression(source), source, [ - ["unexpected write target", 0..6], - ["unexpected operator after a call with a block", 7..10] - ] - end - - def test_call_with_block_operator_write - source = "foo {} += 1" - assert_errors expression(source), source, [ - ["unexpected write target", 0..6], - ["unexpected operator after a call with a block", 7..9] - ] - end - - def test_index_call_with_block_and_write - source = "foo[1] {} &&= 1" - assert_errors expression(source), source, [ - ["unexpected write target", 0..9], - ["unexpected operator after a call with arguments", 10..13], - ["unexpected operator after a call with a block", 10..13] - ] - end - - def test_index_call_with_block_or_write - source = "foo[1] {} ||= 1" - assert_errors expression(source), source, [ - ["unexpected write target", 0..9], - ["unexpected operator after a call with arguments", 10..13], - ["unexpected operator after a call with a block", 10..13] - ] - end - - def test_index_call_with_block_operator_write - source = "foo[1] {} += 1" - assert_errors expression(source), source, [ - ["unexpected write target", 0..9], - ["unexpected operator after a call with arguments", 10..12], - ["unexpected operator after a call with a block", 10..12] - ] - end - - if RUBY_VERSION >= "3.0" - def test_writing_numbered_parameter - assert_errors expression("-> { _1 = 0 }"), "-> { _1 = 0 }", [ - ["_1 is reserved for numbered parameters", 5..7] - ] - end - - def test_targeting_numbered_parameter - assert_errors expression("-> { _1, = 0 }"), "-> { _1, = 0 }", [ - ["_1 is reserved for numbered parameters", 5..7] - ] - end - - def test_defining_numbered_parameter - error_messages = ["_1 is reserved for numbered parameters"] - - assert_error_messages "def _1; end", error_messages - assert_error_messages "def self._1; end", error_messages - end - end - - def test_double_scope_numbered_parameters - source = "-> { _1 + -> { _2 } }" - errors = [["numbered parameter is already used in outer scope", 15..17]] - - assert_errors expression(source), source, errors + if RUBY_VERSION < "3.4" + filepaths -= ["it_with_ordinary_parameter.txt"] end - def test_invalid_number_underscores - error_messages = ["invalid underscore placement in number"] - assert_error_messages "1__1", error_messages - assert_error_messages "0b1__1", error_messages - assert_error_messages "0o1__1", error_messages - assert_error_messages "01__1", error_messages - assert_error_messages "0d1__1", error_messages - assert_error_messages "0x1__1", error_messages - - error_messages = ["trailing '_' in number"] - assert_error_messages "1_1_", error_messages - assert_error_messages "0b1_1_", error_messages - assert_error_messages "0o1_1_", error_messages - assert_error_messages "01_1_", error_messages - assert_error_messages "0d1_1_", error_messages - assert_error_messages "0x1_1_", error_messages - end - - def test_alnum_delimiters - error_messages = ["invalid `%` token"] - - assert_error_messages "%qXfooX", error_messages - assert_error_messages "%QXfooX", error_messages - assert_error_messages "%wXfooX", error_messages - assert_error_messages "%WxfooX", error_messages - assert_error_messages "%iXfooX", error_messages - assert_error_messages "%IXfooX", error_messages - assert_error_messages "%xXfooX", error_messages - assert_error_messages "%rXfooX", error_messages - assert_error_messages "%sXfooX", error_messages + if RUBY_VERSION < "3.4" || RUBY_RELEASE_DATE < "2024-07-24" + filepaths -= ["dont_allow_return_inside_sclass_body.txt"] end - def test_begin_at_toplevel - source = "def foo; BEGIN {}; end" - assert_errors expression(source), source, [ - ["BEGIN is permitted only at toplevel", 9..14], - ] - end - - if RUBY_VERSION >= "3.0" - def test_numbered_parameters_in_block_arguments - source = "foo { |_1| }" - assert_errors expression(source), source, [ - ["_1 is reserved for numbered parameters", 7..9], - ] + filepaths.each do |filepath| + define_method(:"test_#{File.basename(filepath, ".txt")}") do + assert_errors(File.join(base, filepath)) end end - def test_conditional_predicate_closed - source = "if 0 0; elsif 0 0; end\nunless 0 0; end" - assert_errors expression(source), source, [ - ["expected `then` or `;` or '\\n" + "'", 5..6], - ["expected `then` or `;` or '\\n" + "'", 16..17], - ["expected `then` or `;` or '\\n" + "'", 32..33], - ] - end - - def test_parameter_name_ending_with_bang_or_question_mark - source = "def foo(x!,y?); end" - errors = [ - ["unexpected name for a parameter", 8..10], - ["unexpected name for a parameter", 11..13] - ] - assert_errors expression(source), source, errors - end - - def test_class_name - source = "class 0.X end" - assert_errors expression(source), source, [ - ["unexpected constant path after `class`; class/module name must be CONSTANT", 6..9], - ] - end - - def test_loop_conditional_is_closed - source = "while 0 0; foo; end; until 0 0; foo; end" - assert_errors expression(source), source, [ - ["expected a predicate expression for the `while` statement", 7..7], - ["expected a predicate expression for the `until` statement", 28..28], - ] - end - - def test_forwarding_arg_after_keyword_rest - source = "def f(**,...);end" - assert_errors expression(source), source, [ - ["unexpected `...` in parameters", 9..12], - ] - end - - def test_semicolon_after_inheritance_operator - source = "class Foo < Bar end" - assert_errors expression(source), source, [ - ["unexpected `end`, expecting ';' or '\\n'", 15..15], - ] - end - - def test_shadow_args_in_lambda - source = "->a;b{}" - - assert_errors expression(source), source, [ - ["expected a `do` keyword or a `{` to open the lambda block", 3..3], - ["unexpected end of file, expecting end-of-input", 7..7], - ["unexpected end of file, assuming it is closing the parent top level context", 7..7], - ["expected a lambda block beginning with `do` to end with `end`", 7..7] - ] - end - - def test_shadow_args_in_block - source = "tap{|a;a|}" - assert_errors expression(source), source, [ - ["duplicated argument name", 7..8], - ] - end - - def test_repeated_parameter_name_in_destructured_params - source = "def f(a, (b, (a))); end" - - assert_errors expression(source), source, [ - ["duplicated argument name", 14..15], - ] - end - - def test_assign_to_numbered_parameter - source = <<~RUBY - a in _1 - a => _1 - 1 => a, _1 - 1 in a, _1 - /(?<_1>)/ =~ a - RUBY - - message = "_1 is reserved for numbered parameters" - assert_errors expression(source), source, [ - [message, 5..7], - [message, 13..15], - [message, 24..26], - [message, 35..37], - [message, 42..44] - ] - end - - def test_symbol_in_keyword_parameter - source = "def foo(x:'y':); end" - assert_errors expression(source), source, [ - ["unexpected label terminator, expected a string literal terminator", 12..14] - ] - end - - def test_symbol_in_hash - source = "{x:'y':}" - assert_errors expression(source), source, [ - ["unexpected label terminator, expected a string literal terminator", 5..7] - ] - end - - def test_while_endless_method - source = "while def f = g do end" - - assert_errors expression(source), source, [ - ["expected a predicate expression for the `while` statement", 22..22], - ["unexpected end of file, assuming it is closing the parent top level context", 22..22], - ["expected an `end` to close the `while` statement", 22..22] - ] - end - - def test_match_plus - source = <<~RUBY - a in b + c - a => b + c - RUBY - - assert_errors expression(source), source, [ - ["unexpected '+', expecting end-of-input", 7..8], - ["unexpected '+', ignoring it", 7..8], - ["unexpected '+', expecting end-of-input", 18..19], - ["unexpected '+', ignoring it", 18..19] - ] - end - - def test_rational_number_with_exponential_portion - source = '1e1r; 1e1ri' - - assert_errors expression(source), source, [ - ["unexpected local variable or method, expecting end-of-input", 3..4], - ["unexpected local variable or method, expecting end-of-input", 9..11] - ] - end - - def test_check_value_expression - source = <<~RUBY - 1 => ^(return) - while true - 1 => ^(break) - 1 => ^(next) - 1 => ^(redo) - 1 => ^(retry) - 1 => ^(2 => a) - end - 1 => ^(if 1; (return) else (return) end) - 1 => ^(unless 1; (return) else (return) end) - RUBY - - message = "unexpected void value expression" - assert_errors expression(source), source, [ - [message, 7..13], - [message, 35..40], - [message, 51..55], - [message, 66..70], - ["Invalid retry without rescue", 81..86], - [message, 81..86], - [message, 97..103], - [message, 123..129], - [message, 168..174], - ] - end - - def test_void_value_expression_in_statement - source = <<~RUBY - if (return) - end - unless (return) - end - while (return) - end - until (return) - end - case (return) - when 1 - end - class A < (return) - end - class << (return) - end - for x in (return) - end - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 4..10], - [message, 24..30], - [message, 43..49], - [message, 62..68], - [message, 80..86], - [message, 110..116], - [message, 132..138], - [message, 154..160], - ] - end - - def test_void_value_expression_in_def - source = <<~RUBY - def (return).x - end - def x(a = return) - end - def x(a: return) - end - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 5..11], - [message, 29..35], - [message, 50..56], - ] - end - - def test_void_value_expression_in_assignment - source = <<~RUBY - a = return - a = 1, return - a, b = return, 1 - a, b = 1, *return - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 4..10], - [message, 18..24], - [message, 32..38], - [message, 53..59], - ] - end - - def test_void_value_expression_in_modifier - source = <<~RUBY - 1 if (return) - 1 unless (return) - 1 while (return) - 1 until (return) - (return) => a - (return) in a - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 6..12], - [message, 24..30], - [message, 41..47], - [message, 58..64], - [message, 67..73], - [message, 81..87] - ] - end - - def test_void_value_expression_in_expression - source = <<~RUBY - (return) ? 1 : 1 - (return)..1 - 1..(return) - (return)...1 - 1...(return) - (..(return)) - (...(return)) - ((return)..) - ((return)...) - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 1..7], - [message, 18..24], - [message, 33..39], - [message, 42..48], - [message, 59..65], - [message, 71..77], - [message, 85..91], - [message, 96..102], - [message, 109..115] - ] - end - - def test_void_value_expression_in_array - source = <<~RUBY - [return] - [1, return] - [ return => 1 ] - [ 1 => return ] - [ a: return ] - [ *return ] - [ **return ] - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 1..7], - [message, 13..19], - [message, 23..29], - [message, 44..50], - [message, 58..64], - [message, 70..76], - [message, 83..89], - ] - end - - def test_void_value_expression_in_hash + def test_embdoc_ending source = <<~RUBY - { return => 1 } - { 1 => return } - { a: return } - { **return } + =begin\n=end + =begin\n=end\0 + =begin\n=end\C-d + =begin\n=end\C-z RUBY - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 2..8], - [message, 23..29], - [message, 37..43], - [message, 50..56], - ] - end - - def test_void_value_expression_in_call - source = <<~RUBY - (return).foo - (return).(1) - (return)[1] - (return)[1] = 2 - (return)::foo - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 1..7], - [message, 14..20], - [message, 27..33], - [message, 39..45], - [message, 55..61], - ] - end - - def test_void_value_expression_in_constant_path - source = <<~RUBY - (return)::A - class (return)::A; end - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 1..7], - [message, 19..25], - ] - end - - def test_void_value_expression_in_arguments - source = <<~RUBY - foo(return) - foo(1, return) - foo(*return) - foo(**return) - foo(&return) - foo(return => 1) - foo(:a => return) - foo(a: return) - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 4..10], - [message, 19..25], - [message, 32..38], - [message, 46..52], - [message, 59..65], - [message, 71..77], - [message, 94..100], - [message, 109..115], - ] - end - - def test_void_value_expression_in_unary_call - source = <<~RUBY - +(return) - not return - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 2..8], - [message, 14..20], - ] - end - - def test_void_value_expression_in_binary_call - source = <<~RUBY - 1 + (return) - (return) + 1 - 1 and (return) - (return) and 1 - 1 or (return) - (return) or 1 - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 5..11], - [message, 14..20], - [message, 42..48], - [message, 71..77], - ] - end - - def test_trailing_comma_in_calls - assert_errors expression("foo 1,"), "foo 1,", [ - ["expected an argument", 5..6] - ] - end - - def test_argument_after_ellipsis - source = 'def foo(...); foo(..., 1); end' - assert_errors expression(source), source, [ - ['unexpected argument after `...`', 23..24] - ] - end - - def test_ellipsis_in_no_paren_call - source = 'def foo(...); foo 1, ...; end' - assert_errors expression(source), source, [ - ['unexpected `...` in an non-parenthesized call', 21..24] - ] - end - - def test_non_assoc_range - source = '1....2' - - assert_errors expression(source), source, [ - ["unexpected '.', expecting end-of-input", 4..5], - ["unexpected '.', ignoring it", 4..5] - ] - end - - def test_upcase_end_in_def - assert_warning_messages "def foo; END { }; end", [ - "END in method; use at_exit" - ] + source.each_line do |line| + assert_valid_syntax(source) + assert_predicate Prism.parse(source), :success? + end end - def test_warnings_verbosity - warning = Prism.parse("def foo; END { }; end").warnings[0] - assert_equal "END in method; use at_exit", warning.message - assert_equal :default, warning.level - - warning = Prism.parse("foo /regexp/").warnings[0] - assert_equal "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", warning.message - assert_equal :verbose, warning.level + def test_unterminated_string_closing + statement = Prism.parse_statement("'hello") + assert_equal statement.unescaped, "hello" + assert_empty statement.closing end - def test_statement_operators - source = <<~RUBY - alias x y + 1 - alias x y.z - BEGIN { bar } + 1 - BEGIN { bar }.z - END { bar } + 1 - END { bar }.z - undef x + 1 - undef x.z - RUBY - - assert_errors expression(source), source, [ - ["unexpected '+', expecting end-of-input", 10..11], - ["unexpected '+', ignoring it", 10..11], - ["unexpected '.', expecting end-of-input", 23..24], - ["unexpected '.', ignoring it", 23..24], - ["unexpected '+', expecting end-of-input", 40..41], - ["unexpected '+', ignoring it", 40..41], - ["unexpected '.', expecting end-of-input", 57..58], - ["unexpected '.', ignoring it", 57..58], - ["unexpected '+', expecting end-of-input", 72..73], - ["unexpected '+', ignoring it", 72..73], - ["unexpected '.', expecting end-of-input", 87..88], - ["unexpected '.', ignoring it", 87..88], - ["unexpected '+', expecting end-of-input", 98..99], - ["unexpected '+', ignoring it", 98..99], - ["unexpected '.', expecting end-of-input", 109..110], - ["unexpected '.', ignoring it", 109..110] - ] + def test_unterminated_interpolated_string_closing + statement = Prism.parse_statement('"hello') + assert_equal statement.unescaped, "hello" + assert_empty statement.closing end - def test_statement_at_non_statement - source = <<~RUBY - foo(alias x y) - foo(BEGIN { bar }) - foo(END { bar }) - foo(undef x) - RUBY - assert_errors expression(source), source, [ - ['unexpected an `alias` at a non-statement position', 4..9], - ['unexpected a `BEGIN` at a non-statement position', 19..24], - ['unexpected an `END` at a non-statement position', 38..41], - ['unexpected an `undef` at a non-statement position', 55..60], - ] + def test_unterminated_empty_string_closing + statement = Prism.parse_statement('"') + assert_empty statement.unescaped + assert_empty statement.closing end - def test_binary_range_with_left_unary_range - source = <<~RUBY - ..1.. - ...1.. - RUBY - - assert_errors expression(source), source, [ - ["unexpected '..', expecting end-of-input", 3..5], - ["unexpected '..', ignoring it", 3..5], - ["unexpected '..', expecting end-of-input", 10..12], - ["unexpected '..', ignoring it", 10..12] - ] + def test_invalid_message_name + assert_equal :"", Prism.parse_statement("+.@foo,+=foo").write_name end - def test_circular_param + def test_circular_parameters source = <<~RUBY def foo(bar = bar) = 42 def foo(bar: bar) = 42 @@ -1957,288 +76,26 @@ def foo(bar: bar) = 42 proc { |foo: foo| } RUBY - assert_errors expression(source), source, [ - ["circular argument reference - bar", 8..11], - ["circular argument reference - bar", 32..35], - ["circular argument reference - foo", 55..58], - ["circular argument reference - foo", 76..79] - ] - - refute_error_messages("def foo(bar: bar = 1); end") - end - - def test_command_calls - sources = <<~RUBY.lines - [a b] - {a: b c} - ...a b - if ...a b; end - a b, c d - a(b, c d) - a(*b c) - a(**b c) - a(&b c) - +a b - a + b c - a && b c - a =~ b c - a = b, c d - a = *b c - a, b = c = d f - a ? b c : d e - defined? a b - ! ! a b - def f a = b c; end - def f(a = b c); end - a = b rescue c d - def a = b rescue c d - ->a=b c{} - ->(a=b c){} - case; when a b; end - case; in a if a b; end - case; in a unless a b; end - begin; rescue a b; end - begin; rescue a b => c; end - RUBY - - sources.each do |source| - refute_valid_syntax(source) - assert_false(Prism.parse(source).success?) - end - end - - def test_range_and_bin_op - sources = <<~RUBY.lines - 1..2..3 - 1..2.. - 1.. || 2 - 1.. & 2 - 1.. * 2 - 1.. / 2 - 1.. % 2 - 1.. ** 2 - RUBY - - sources.each do |source| - refute_valid_syntax(source) - assert_false(Prism.parse(source).success?) + source.each_line do |line| + assert_predicate Prism.parse(line, version: "3.3.0"), :failure? + assert_predicate Prism.parse(line), :success? end end - def test_command_call_in - source = <<~RUBY - foo 1 in a - a = foo 2 in b - RUBY - - assert_errors expression(source), source, [ - ["unexpected `in` keyword in arguments", 9..10], - ["unexpected local variable or method, expecting end-of-input", 9..10], - ["unexpected `in` keyword in arguments", 24..25], - ["unexpected local variable or method, expecting end-of-input", 24..25] - ] - end - - def test_constant_assignment_in_method - source = 'def foo();A=1;end' - assert_errors expression(source), source, [ - ['dynamic constant assignment', 10..13] - ] - end - - def test_non_assoc_equality - source = <<~RUBY - 1 == 2 == 3 - 1 != 2 != 3 - 1 === 2 === 3 - 1 =~ 2 =~ 3 - 1 !~ 2 !~ 3 - 1 <=> 2 <=> 3 - RUBY - - assert_errors expression(source), source, [ - ["unexpected '==', expecting end-of-input", 7..9], - ["unexpected '==', ignoring it", 7..9], - ["unexpected '!=', expecting end-of-input", 19..21], - ["unexpected '!=', ignoring it", 19..21], - ["unexpected '===', expecting end-of-input", 32..35], - ["unexpected '===', ignoring it", 32..35], - ["unexpected '=~', expecting end-of-input", 45..47], - ["unexpected '=~', ignoring it", 45..47], - ["unexpected '!~', expecting end-of-input", 57..59], - ["unexpected '!~', ignoring it", 57..59], - ["unexpected '<=>', expecting end-of-input", 70..73], - ["unexpected '<=>', ignoring it", 70..73] - ] - end - - def test_block_arg_and_block - source = 'foo(&1) { }' - assert_errors expression(source), source, [ - ["both block arg and actual block given; only one block is allowed", 8..11] - ] - end - - def test_forwarding_arg_and_block - source = 'def foo(...) = foo(...) { }' - assert_errors expression(source), source, [ - ['both a block argument and a forwarding argument; only one block is allowed', 24..27] - ] - end - - def test_it_with_ordinary_parameter - source = "proc { || it }" - errors = [["`it` is not allowed when an ordinary parameter is defined", 10..12]] - - assert_errors expression(source), source, errors, check_valid_syntax: RUBY_VERSION >= "3.4.0" - end - - def test_regular_expression_with_unknown_regexp_options - source = "/foo/AZaz" - errors = [["unknown regexp options: AZaz", 4..9]] - - assert_errors expression(source), source, errors - end - - def test_interpolated_regular_expression_with_unknown_regexp_options - source = "/\#{foo}/AZaz" - errors = [["unknown regexp options: AZaz", 7..12]] - - assert_errors expression(source), source, errors - end - - def test_singleton_method_for_literals - source = <<~'RUBY' - def (1).g; end - def ((a; 1)).foo; end - def ((return; 1)).bar; end - def (((1))).foo; end - def (__FILE__).foo; end - def (__ENCODING__).foo; end - def (__LINE__).foo; end - def ("foo").foo; end - def (3.14).foo; end - def (3.14i).foo; end - def (:foo).foo; end - def (:'foo').foo; end - def (:'f{o}').foo; end - def ('foo').foo; end - def ("foo").foo; end - def ("#{fo}o").foo; end - def (/foo/).foo; end - def (/f#{oo}/).foo; end - def ([1]).foo; end - RUBY - errors = [ - ["cannot define singleton method for literals", 5..6], - ["cannot define singleton method for literals", 24..25], - ["cannot define singleton method for literals", 51..52], - ["cannot define singleton method for literals", 71..72], - ["cannot define singleton method for literals", 90..98], - ["cannot define singleton method for literals", 114..126], - ["cannot define singleton method for literals", 142..150], - ["cannot define singleton method for literals", 166..171], - ["cannot define singleton method for literals", 187..191], - ["cannot define singleton method for literals", 207..212], - ["cannot define singleton method for literals", 228..232], - ["cannot define singleton method for literals", 248..254], - ["cannot define singleton method for literals", 270..277], - ["cannot define singleton method for literals", 293..298], - ["cannot define singleton method for literals", 314..319], - ["cannot define singleton method for literals", 335..343], - ["cannot define singleton method for literals", 359..364], - ["cannot define singleton method for literals", 380..388], - ["cannot define singleton method for literals", 404..407] - ] - assert_errors expression(source), source, errors - end - - def test_assignment_to_literal_in_conditionals - source = <<~RUBY - if (a = 2); end - if ($a = 2); end - if (@a = 2); end - if (@@a = 2); end - if a elsif b = 2; end - unless (a = 2); end - unless ($a = 2); end - unless (@a = 2); end - unless (@@a = 2); end - while (a = 2); end - while ($a = 2); end - while (@a = 2); end - while (@@a = 2); end - until (a = 2); end - until ($a = 2); end - until (@a = 2); end - until (@@a = 2); end - foo if a = 2 - foo if (a, b = 2) - (@foo = 1) ? a : b - !(a = 2) - not a = 2 - RUBY - assert_warning_messages source, [ - "found '= literal' in conditional, should be ==" - ] * source.lines.count - end - - def test_duplicate_pattern_capture - source = <<~RUBY - case (); in [a, a]; end - case (); in [a, *a]; end - case (); in {a: a, b: a}; end - case (); in {a: a, **a}; end - case (); in [a, {a:}]; end - case (); in [a, {a: {a: {a: [a]}}}]; end - case (); in a => a; end - case (); in [A => a, {a: b => a}]; end - RUBY - - assert_error_messages source, Array.new(source.lines.length, "duplicated variable name") - refute_error_messages "case (); in [_a, _a]; end" - end - - def test_duplicate_pattern_hash_key - assert_error_messages "case (); in {a:, a:}; end", ["duplicated key name", "duplicated variable name"] - assert_error_messages "case (); in {a:1, a:2}; end", ["duplicated key name"] - refute_error_messages "case (); in [{a:1}, {a:2}]; end" - end - - def test_unexpected_block - assert_error_messages "def foo = yield(&:+)", ["block argument should not be given"] - end - private - def assert_errors(expected, source, errors, check_valid_syntax: true) - refute_valid_syntax(source) if check_valid_syntax - - result = Prism.parse(source) - node = result.value.statements.body.last - - assert_equal_nodes(expected, node, compare_location: false) - assert_equal(errors, result.errors.map { |e| [e.message, e.location.start_offset..e.location.end_offset] }) - end + def assert_errors(filepath) + expected = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8) - def assert_error_messages(source, errors) + source = expected.lines.grep_v(/^\s*\^/).join.gsub(/\n*\z/, "") refute_valid_syntax(source) - result = Prism.parse(source) - assert_equal(errors, result.errors.map(&:message)) - end - - def refute_error_messages(source) - assert_valid_syntax(source) - assert Prism.parse_success?(source), "Expected #{source.inspect} to parse successfully" - end - def assert_warning_messages(source, warnings) result = Prism.parse(source) - assert_equal(warnings, result.warnings.map(&:message)) - end + errors = result.errors + refute_empty errors, "Expected errors in #{filepath}" - def expression(source) - Prism.parse(source).value.statements.body.last + actual = result.errors_format + assert_equal expected, actual, "Expected errors to match for #{filepath}" end end end diff --git a/test/prism/fixtures/break.txt b/test/prism/fixtures/break.txt index 82fa45bdb4f..5532322c5ce 100644 --- a/test/prism/fixtures/break.txt +++ b/test/prism/fixtures/break.txt @@ -23,3 +23,7 @@ tap { break(1) } foo { break 42 } == 42 foo { |a| break } == 42 + +while _ && break; end + +until _ && break; end diff --git a/test/prism/fixtures/methods.txt b/test/prism/fixtures/methods.txt index 4bfd976edaa..d59196bdfdf 100644 --- a/test/prism/fixtures/methods.txt +++ b/test/prism/fixtures/methods.txt @@ -181,3 +181,8 @@ end def foo(bar = (def baz(bar) = bar; 1)) = 2 def (class Foo; end).foo(bar = 1) = 2 + +module Foo + def clone(opts = nil || (return self)) + end +end diff --git a/test/prism/fixtures/patterns.txt b/test/prism/fixtures/patterns.txt index 7ce3b9e4a8e..5b3bc496522 100644 --- a/test/prism/fixtures/patterns.txt +++ b/test/prism/fixtures/patterns.txt @@ -87,10 +87,7 @@ foo => *bar, baz, qux foo => bar, *baz, qux foo => bar, baz, *qux foo => *bar, baz, *qux - -foo => bar, - -; # end the previous pattern for ParseTest#test_filepath_patterns.txt which parses the whole file at once +foo => bar,; foo => [] foo => [[[[[]]]]] @@ -127,10 +124,7 @@ foo in __FILE__ foo in __LINE__ foo in __ENCODING__ foo in -> { bar } - -foo in bar, - -; # end the previous pattern for ParseTest#test_filepath_patterns.txt which parses the whole file at once +foo in bar,; case foo; in bar then end case foo; in 1 then end @@ -215,3 +209,6 @@ foo => Object[{x:}] a, b ) = c + +case (); in [_a, _a]; end +case (); in [{a:1}, {a:2}]; end diff --git a/test/prism/fixtures/range_beginless.txt b/test/prism/fixtures/range_beginless.txt new file mode 100644 index 00000000000..a55b9b57e77 --- /dev/null +++ b/test/prism/fixtures/range_beginless.txt @@ -0,0 +1,5 @@ +def f(x = ...?a); end + +def f(x: ...?a); end + +def f() ...:a; end diff --git a/test/prism/fixtures/regex.txt b/test/prism/fixtures/regex.txt index 84b5ca0600f..4623733f589 100644 --- a/test/prism/fixtures/regex.txt +++ b/test/prism/fixtures/regex.txt @@ -44,3 +44,5 @@ tap { /(?
)/ =~ to_s } /(?)/ =~ "" def foo(nil:) = /(?)/ =~ "" + +/(?-x:#)/x diff --git a/test/prism/fixtures/regex_escape_encoding.txt b/test/prism/fixtures/regex_escape_encoding.txt new file mode 100644 index 00000000000..74e1647d675 --- /dev/null +++ b/test/prism/fixtures/regex_escape_encoding.txt @@ -0,0 +1,3 @@ +# encoding: US-ASCII +str = "hello \xFC" +str =~ /hello \u{fc}/ diff --git a/test/prism/fixtures/seattlerb/pct_Q_backslash_nl.txt b/test/prism/fixtures/seattlerb/pct_Q_backslash_nl.txt index d88e1fd21cf..4420560d2be 100644 --- a/test/prism/fixtures/seattlerb/pct_Q_backslash_nl.txt +++ b/test/prism/fixtures/seattlerb/pct_Q_backslash_nl.txt @@ -1,2 +1,2 @@ -%Q{ \ +%q{ \ } diff --git a/test/prism/fixtures/unparser/corpus/literal/unary.txt b/test/prism/fixtures/unparser/corpus/literal/unary.txt index 77685cb71d0..6992d86bb02 100644 --- a/test/prism/fixtures/unparser/corpus/literal/unary.txt +++ b/test/prism/fixtures/unparser/corpus/literal/unary.txt @@ -6,3 +6,4 @@ -a +a -(-a).foo ++(+a).foo diff --git a/test/prism/fixtures/whitequark/method_definition_in_while_cond.txt b/test/prism/fixtures/whitequark/method_definition_in_while_cond.txt new file mode 100644 index 00000000000..6ec38906a1e --- /dev/null +++ b/test/prism/fixtures/whitequark/method_definition_in_while_cond.txt @@ -0,0 +1,7 @@ +while def foo a = tap do end; end; break; end + +while def foo; tap do end; end; break; end + +while def self.foo a = tap do end; end; break; end + +while def self.foo; tap do end; end; break; end diff --git a/test/prism/fixtures_test.rb b/test/prism/fixtures_test.rb new file mode 100644 index 00000000000..7225b4ac66c --- /dev/null +++ b/test/prism/fixtures_test.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +return if RUBY_VERSION < "3.2.0" + +require_relative "test_helper" + +module Prism + class FixturesTest < TestCase + except = [] + + # Ruby < 3.3.0 cannot parse heredocs where there are leading whitespace + # characters in the heredoc start. + # Example: <<~' EOF' or <<-' EOF' + # https://bugs.ruby-lang.org/issues/19539 + except << "heredocs_leading_whitespace.txt" if RUBY_VERSION < "3.3.0" + + Fixture.each(except: except) do |fixture| + define_method(fixture.test_name) { assert_valid_syntax(fixture.read) } + end + end +end diff --git a/test/prism/format_errors_test.rb b/test/prism/format_errors_test.rb deleted file mode 100644 index a1edbef2e86..00000000000 --- a/test/prism/format_errors_test.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -require_relative "test_helper" - -return if Prism::BACKEND == :FFI - -module Prism - class FormatErrorsTest < TestCase - def test_format_errors - assert_equal <<~ERROR, Debug.format_errors("<>", false) - > 1 | <> - | ^ unexpected '<', ignoring it - | ^ unexpected '>', ignoring it - ERROR - - assert_equal <<~'ERROR', Debug.format_errors('"%W"\u"', false) - > 1 | "%W"\u" - | ^ unexpected backslash, ignoring it - | ^ unexpected local variable or method, expecting end-of-input - | ^ unterminated string meets end of file - ERROR - end - end -end diff --git a/test/prism/fuzzer_test.rb b/test/prism/fuzzer_test.rb index 511210e7ee1..4927478bdc2 100644 --- a/test/prism/fuzzer_test.rb +++ b/test/prism/fuzzer_test.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -return if ENV["PRISM_BUILD_MINIMAL"] - require_relative "test_helper" module Prism @@ -9,7 +7,7 @@ module Prism # invalid memory access. class FuzzerTest < TestCase def self.snippet(name, source) - define_method(:"test_fuzzer_#{name}") { Prism.dump(source) } + define_method(:"test_fuzzer_#{name}") { Prism.profile(source) } end snippet "incomplete global variable", "$" @@ -39,29 +37,31 @@ def self.snippet(name, source) snippet "escaped unicode at end of file 8", '"\\u33' snippet "escaped unicode at end of file 9", '"\\u333' snippet "float suffix at end of file", "1e" + snippet "parameter name that is zero length", "a { |b;" snippet "statements node with multiple heredocs", <<~EOF for <= "3.2.0") + +require_relative "test_helper" + +module Prism + class LexTest < TestCase + except = [ + # It seems like there are some oddities with nested heredocs and ripper. + # Waiting for feedback on https://bugs.ruby-lang.org/issues/19838. + "seattlerb/heredoc_nested.txt", + "whitequark/dedenting_heredoc.txt", + # Ripper seems to have a bug that the regex portions before and after + # the heredoc are combined into a single token. See + # https://bugs.ruby-lang.org/issues/19838. + "spanning_heredoc.txt", + "spanning_heredoc_newlines.txt" + ] + + if RUBY_VERSION < "3.3.0" + # This file has changed behavior in Ripper in Ruby 3.3, so we skip it if + # we're on an earlier version. + except << "seattlerb/pct_w_heredoc_interp_nested.txt" + + # Ruby < 3.3.0 cannot parse heredocs where there are leading whitespace + # characters in the heredoc start. + # Example: <<~' EOF' or <<-' EOF' + # https://bugs.ruby-lang.org/issues/19539 + except << "heredocs_leading_whitespace.txt" + end + + Fixture.each(except: except) do |fixture| + define_method(fixture.test_name) { assert_lex(fixture) } + end + + def test_lex_file + assert_nothing_raised do + Prism.lex_file(__FILE__) + end + + error = assert_raise Errno::ENOENT do + Prism.lex_file("idontexist.rb") + end + + assert_equal "No such file or directory - idontexist.rb", error.message + + assert_raise TypeError do + Prism.lex_file(nil) + end + end + + def test_parse_lex + node, tokens = Prism.parse_lex("def foo; end").value + + assert_kind_of ProgramNode, node + assert_equal 5, tokens.length + end + + def test_parse_lex_file + node, tokens = Prism.parse_lex_file(__FILE__).value + + assert_kind_of ProgramNode, node + refute_empty tokens + + error = assert_raise Errno::ENOENT do + Prism.parse_lex_file("idontexist.rb") + end + + assert_equal "No such file or directory - idontexist.rb", error.message + + assert_raise TypeError do + Prism.parse_lex_file(nil) + end + end + + private + + def assert_lex(fixture) + source = fixture.read + + result = Prism.lex_compat(source) + assert_equal [], result.errors + + Prism.lex_ripper(source).zip(result.value).each do |(ripper, prism)| + assert_equal ripper, prism + end + end + end +end diff --git a/test/prism/library_symbols_test.rb b/test/prism/library_symbols_test.rb index b10a367c183..44f225478bd 100644 --- a/test/prism/library_symbols_test.rb +++ b/test/prism/library_symbols_test.rb @@ -3,8 +3,6 @@ require_relative "test_helper" return if RUBY_PLATFORM !~ /linux/ - -# TODO: determine why these symbols are incorrect on ppc64le return if RUBY_PLATFORM =~ /powerpc64le/ module Prism diff --git a/test/prism/locals_test.rb b/test/prism/locals_test.rb index 0eb73f1b9c7..2c0036289cd 100644 --- a/test/prism/locals_test.rb +++ b/test/prism/locals_test.rb @@ -9,6 +9,15 @@ # to test on the most recent versions. return if !defined?(RubyVM::InstructionSequence) || RUBY_VERSION < "3.4.0" +# If we're on Ruby 3.4.0 and the default parser is Prism, then there is no point +# in comparing the locals because they will be the same. +return if RubyVM::InstructionSequence.compile("").to_a[4][:parser] == :prism + +# In Ruby 3.4.0, the local table for method forwarding changed. But 3.4.0 can +# refer to the dev version, so while 3.4.0 still isn't released, we need to +# check if we have a high enough revision. +return if RubyVM::InstructionSequence.compile("def foo(...); end").to_a[13][2][2][10].length != 1 + # Omit tests if running on a 32-bit machine because there is a bug with how # Ruby is handling large ISeqs on 32-bit machines return if RUBY_PLATFORM =~ /i686/ @@ -17,14 +26,14 @@ module Prism class LocalsTest < TestCase - base = File.join(__dir__, "fixtures") - Dir["**/*.txt", base: base].each do |relative| + except = [ # Skip this fixture because it has a different number of locals because # CRuby is eliminating dead code. - next if relative == "whitequark/ruby_bug_10653.txt" + "whitequark/ruby_bug_10653.txt" + ] - filepath = File.join(base, relative) - define_method("test_#{relative}") { assert_locals(filepath) } + Fixture.each(except: except) do |fixture| + define_method(fixture.test_name) { assert_locals(fixture) } end def setup @@ -38,21 +47,192 @@ def teardown private - def assert_locals(filepath) - source = File.read(filepath) + def assert_locals(fixture) + source = fixture.read - expected = Debug.cruby_locals(source) - actual = Debug.prism_locals(source) + expected = cruby_locals(source) + actual = prism_locals(source) assert_equal(expected, actual) end - def ignore_warnings - previous_verbosity = $VERBOSE - $VERBOSE = nil - yield - ensure - $VERBOSE = previous_verbosity + # A wrapper around a RubyVM::InstructionSequence that provides a more + # convenient interface for accessing parts of the iseq. + class ISeq + attr_reader :parts + + def initialize(parts) + @parts = parts + end + + def type + parts[0] + end + + def local_table + parts[10] + end + + def instructions + parts[13] + end + + def each_child + instructions.each do |instruction| + # Only look at arrays. Other instructions are line numbers or + # tracepoint events. + next unless instruction.is_a?(Array) + + instruction.each do |opnd| + # Only look at arrays. Other operands are literals. + next unless opnd.is_a?(Array) + + # Only look at instruction sequences. Other operands are literals. + next unless opnd[0] == "YARVInstructionSequence/SimpleDataFormat" + + yield ISeq.new(opnd) + end + end + end + end + + # Used to hold the place of a local that will be in the local table but + # cannot be accessed directly from the source code. For example, the + # iteration variable in a for loop or the positional parameter on a method + # definition that is destructured. + AnonymousLocal = Object.new + + # For the given source, compiles with CRuby and returns a list of all of the + # sets of local variables that were encountered. + def cruby_locals(source) + locals = [] #: Array[Array[Symbol | Integer]] + stack = [ISeq.new(ignore_warnings { RubyVM::InstructionSequence.compile(source) }.to_a)] + + while (iseq = stack.pop) + names = [*iseq.local_table] + names.map!.with_index do |name, index| + # When an anonymous local variable is present in the iseq's local + # table, it is represented as the stack offset from the top. + # However, when these are dumped to binary and read back in, they + # are replaced with the symbol :#arg_rest. To consistently handle + # this, we replace them here with their index. + if name == :"#arg_rest" + names.length - index + 1 + else + name + end + end + + locals << names + iseq.each_child { |child| stack << child } + end + + locals + end + + # For the given source, parses with prism and returns a list of all of the + # sets of local variables that were encountered. + def prism_locals(source) + locals = [] #: Array[Array[Symbol | Integer]] + stack = [Prism.parse(source).value] #: Array[Prism::node] + + while (node = stack.pop) + case node + when BlockNode, DefNode, LambdaNode + names = node.locals + params = + if node.is_a?(DefNode) + node.parameters + elsif node.parameters.is_a?(NumberedParametersNode) + nil + else + node.parameters&.parameters + end + + # prism places parameters in the same order that they appear in the + # source. CRuby places them in the order that they need to appear + # according to their own internal calling convention. We mimic that + # order here so that we can compare properly. + if params + sorted = [ + *params.requireds.map do |required| + if required.is_a?(RequiredParameterNode) + required.name + else + AnonymousLocal + end + end, + *params.optionals.map(&:name), + *((params.rest.name || :*) if params.rest && !params.rest.is_a?(ImplicitRestNode)), + *params.posts.map do |post| + if post.is_a?(RequiredParameterNode) + post.name + else + AnonymousLocal + end + end, + *params.keywords.grep(RequiredKeywordParameterNode).map(&:name), + *params.keywords.grep(OptionalKeywordParameterNode).map(&:name), + ] + + sorted << AnonymousLocal if params.keywords.any? + + if params.keyword_rest.is_a?(ForwardingParameterNode) + if sorted.length == 0 + sorted.push(:"...") + else + sorted.push(:*, :**, :&, :"...") + end + elsif params.keyword_rest.is_a?(KeywordRestParameterNode) + sorted << (params.keyword_rest.name || :**) + end + + # Recurse down the parameter tree to find any destructured + # parameters and add them after the other parameters. + param_stack = params.requireds.concat(params.posts).grep(MultiTargetNode).reverse + while (param = param_stack.pop) + case param + when MultiTargetNode + param_stack.concat(param.rights.reverse) + param_stack << param.rest if param.rest&.expression && !sorted.include?(param.rest.expression.name) + param_stack.concat(param.lefts.reverse) + when RequiredParameterNode + sorted << param.name + when SplatNode + sorted << param.expression.name + end + end + + if params.block + sorted << (params.block.name || :&) + end + + names = sorted.concat(names - sorted) + end + + names.map!.with_index do |name, index| + if name == AnonymousLocal + names.length - index + 1 + else + name + end + end + + locals << names + when ClassNode, ModuleNode, ProgramNode, SingletonClassNode + locals << node.locals + when ForNode + locals << [2] + when PostExecutionNode + locals.push([], []) + when InterpolatedRegularExpressionNode + locals << [] if node.once? + end + + stack.concat(node.compact_child_nodes) + end + + locals end end end diff --git a/test/prism/magic_comment_test.rb b/test/prism/magic_comment_test.rb index 9e2e92af927..ab4b5f56e51 100644 --- a/test/prism/magic_comment_test.rb +++ b/test/prism/magic_comment_test.rb @@ -2,32 +2,116 @@ require_relative "test_helper" -return if RUBY_ENGINE != "ruby" - module Prism class MagicCommentTest < TestCase - examples = [ - "# encoding: ascii", - "# coding: ascii", - "# eNcOdInG: ascii", - "# CoDiNg: ascii", - "# \s\t\v encoding \s\t\v : \s\t\v ascii \s\t\v", - "# -*- encoding: ascii -*-", - "# -*- coding: ascii -*-", - "# -*- eNcOdInG: ascii -*-", - "# -*- CoDiNg: ascii -*-", - "# -*- \s\t\v encoding \s\t\v : \s\t\v ascii \s\t\v -*-", - "# -*- foo: bar; encoding: ascii -*-", - "# coding \t \r \v : \t \v \r ascii-8bit", - "# vim: filetype=ruby, fileencoding=windows-31j, tabsize=3, shiftwidth=3" - ] - - examples.each.with_index(1) do |example, index| - define_method(:"test_magic_comment_#{index}") do - expected = RubyVM::InstructionSequence.compile(%Q{#{example}\n""}).eval.encoding - actual = Prism.parse(example).encoding + if RUBY_ENGINE == "ruby" + class MagicCommentRipper < Ripper + attr_reader :magic_comments + + def initialize(*) + super + @magic_comments = [] + end + + def on_magic_comment(key, value) + @magic_comments << [key, value] + super + end + end + + Fixture.each do |fixture| + define_method(fixture.test_name) { assert_magic_comments(fixture) } + end + end + + def test_encoding + assert_magic_encoding(Encoding::US_ASCII, "# encoding: ascii") + end + + def test_coding + assert_magic_encoding(Encoding::US_ASCII, "# coding: ascii") + end + + def test_eNcOdInG + assert_magic_encoding(Encoding::US_ASCII, "# eNcOdInG: ascii") + end + + def test_CoDiNg + assert_magic_encoding(Encoding::US_ASCII, "# CoDiNg: ascii") + end + + def test_encoding_whitespace + assert_magic_encoding(Encoding::US_ASCII, "# \s\t\v encoding \s\t\v : \s\t\v ascii \s\t\v") + end + + def test_emacs_encoding + assert_magic_encoding(Encoding::US_ASCII, "# -*- encoding: ascii -*-") + end + + def test_emacs_coding + assert_magic_encoding(Encoding::US_ASCII, "# -*- coding: ascii -*-") + end + + def test_emacs_eNcOdInG + assert_magic_encoding(Encoding::US_ASCII, "# -*- eNcOdInG: ascii -*-") + end + + def test_emacs_CoDiNg + assert_magic_encoding(Encoding::US_ASCII, "# -*- CoDiNg: ascii -*-") + end + + def test_emacs_whitespace + assert_magic_encoding(Encoding::US_ASCII, "# -*- \s\t\v encoding \s\t\v : \s\t\v ascii \s\t\v -*-") + end + + def test_emacs_multiple + assert_magic_encoding(Encoding::US_ASCII, "# -*- foo: bar; encoding: ascii -*-") + end + + def test_coding_whitespace + assert_magic_encoding(Encoding::ASCII_8BIT, "# coding \t \r \v : \t \v \r ascii-8bit") + end + + def test_vim + assert_magic_encoding(Encoding::Windows_31J, "# vim: filetype=ruby, fileencoding=windows-31j, tabsize=3, shiftwidth=3") + end + + private + + def assert_magic_encoding(expected, line) + source = %Q{#{line}\n""} + actual = Prism.parse(source).encoding + + # Compare against our expectation. + assert_equal expected, actual + + # Compare against Ruby's expectation. + if defined?(RubyVM::InstructionSequence) + previous = $VERBOSE + expected = + begin + $VERBOSE = nil + RubyVM::InstructionSequence.compile(source).eval.encoding + ensure + $VERBOSE = previous + end assert_equal expected, actual end end + + def assert_magic_comments(fixture) + source = fixture.read + + # Check that we get the correct number of magic comments when lexing with + # ripper. + expected = MagicCommentRipper.new(source).tap(&:parse).magic_comments + actual = Prism.parse(source).magic_comments + + assert_equal expected.length, actual.length + expected.zip(actual).each do |(expected_key, expected_value), magic_comment| + assert_equal expected_key, magic_comment.key + assert_equal expected_value, magic_comment.value + end + end end end diff --git a/test/prism/memsize_test.rb b/test/prism/memsize_test.rb deleted file mode 100644 index d7e1448dbc0..00000000000 --- a/test/prism/memsize_test.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -require_relative "test_helper" - -return if Prism::BACKEND == :FFI - -module Prism - class MemsizeTest < TestCase - def test_memsize - result = Debug.memsize("2 + 3") - - assert_equal 5, result[:length] - assert_kind_of Integer, result[:memsize] - assert_equal 6, result[:node_count] - end - end -end diff --git a/test/prism/newline_offsets_test.rb b/test/prism/newline_offsets_test.rb new file mode 100644 index 00000000000..99b808b1df6 --- /dev/null +++ b/test/prism/newline_offsets_test.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require_relative "test_helper" + +module Prism + class NewlineOffsetsTest < TestCase + Fixture.each do |fixture| + define_method(fixture.test_name) { assert_newline_offsets(fixture) } + end + + private + + def assert_newline_offsets(fixture) + source = fixture.read + + expected = [0] + source.b.scan("\n") { expected << $~.offset(0)[0] + 1 } + + assert_equal expected, Prism.parse(source).source.offsets + end + end +end diff --git a/test/prism/newline_test.rb b/test/prism/newline_test.rb index e9975b346e8..fefe9def91f 100644 --- a/test/prism/newline_test.rb +++ b/test/prism/newline_test.rb @@ -6,11 +6,24 @@ module Prism class NewlineTest < TestCase - base = File.expand_path("../", __FILE__) - filepaths = Dir["*.rb", base: base] - %w[encoding_test.rb errors_test.rb parser_test.rb static_literals_test.rb unescape_test.rb] - - filepaths.each do |relative| - define_method("test_newline_flags_#{relative}") do + skips = %w[ + errors_test.rb + locals_test.rb + regexp_test.rb + test_helper.rb + unescape_test.rb + encoding/regular_expression_encoding_test.rb + encoding/string_encoding_test.rb + result/breadth_first_search_test.rb + result/static_literals_test.rb + result/warnings_test.rb + ruby/parser_test.rb + ruby/ruby_parser_test.rb + ] + + base = __dir__ + (Dir["{,api/,encoding/,result/,ruby/}*.rb", base: base] - skips).each do |relative| + define_method(:"test_#{relative}") do assert_newlines(base, relative) end end @@ -56,14 +69,6 @@ def assert_newlines(base, relative) assert_equal expected, actual end - def ignore_warnings - previous_verbosity = $VERBOSE - $VERBOSE = nil - yield - ensure - $VERBOSE = previous_verbosity - end - def rubyvm_lines(source) queue = [ignore_warnings { RubyVM::InstructionSequence.compile(source) }] lines = [] @@ -84,7 +89,7 @@ def prism_lines(result) while node = queue.shift queue.concat(node.compact_child_nodes) - newlines << result.source.line(node.location.start_offset) if node&.newline? + newlines << result.source.line(node.location.start_offset) if node&.newline_flag? end newlines.sort diff --git a/test/prism/onigmo_test.rb b/test/prism/onigmo_test.rb new file mode 100644 index 00000000000..03f44c4e4ce --- /dev/null +++ b/test/prism/onigmo_test.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +return if RUBY_ENGINE != "ruby" + +require_relative "test_helper" + +begin + require "onigmo" +rescue LoadError + # In CRuby's CI, we're not going to test against the parser gem because we + # don't want to have to install it. So in this case we'll just skip this test. + return +end + +module Prism + class OnigmoTest < TestCase + def test_ONIGERR_PARSE_DEPTH_LIMIT_OVER + assert_error(%Q{#{"(" * 4096}a#{")" * 4096}}, "parse depth limit over") + end + + def test_ONIGERR_EMPTY_CHAR_CLASS + assert_error("[]", "empty char-class") + end + + def test_ONIGERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED + assert_error("*", "target of repeat operator is not specified") + assert_error("+", "target of repeat operator is not specified") + assert_error("?", "target of repeat operator is not specified") + end + + def test_ONIGERR_EMPTY_GROUP_NAME + assert_error("(?<>)", "group name is empty") + end + + def test_ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS + assert_error("(", "end pattern with unmatched parenthesis") + assert_error("(|", "end pattern with unmatched parenthesis") + assert_error("(?<", "end pattern with unmatched parenthesis") + end + + def test_ONIGERR_END_PATTERN_IN_GROUP + assert_error("(?", "end pattern in group") + assert_error("(?#", "end pattern in group") + end + + def test_ONIGERR_UNDEFINED_GROUP_OPTION + assert_error("(?P", "undefined group option") + end + + def test_ONIGERR_UNMATCHED_CLOSE_PARENTHESIS + assert_error(")", "unmatched close parenthesis") + end + + private + + def assert_error(source, message) + result = Prism.parse("/#{source}/") + + assert result.failure?, "Expected #{source.inspect} to error" + assert_equal message, result.errors.first.message + + error = assert_raise(ArgumentError) { Onigmo.parse(source) } + assert_equal message, error.message + end + end +end diff --git a/test/prism/parse_test.rb b/test/prism/parse_test.rb deleted file mode 100644 index afb53e06685..00000000000 --- a/test/prism/parse_test.rb +++ /dev/null @@ -1,371 +0,0 @@ -# frozen_string_literal: true - -require_relative "test_helper" - -module Prism - class ParseTest < TestCase - # A subclass of Ripper that extracts out magic comments. - class MagicCommentRipper < Ripper - attr_reader :magic_comments - - def initialize(*) - super - @magic_comments = [] - end - - def on_magic_comment(key, value) - @magic_comments << [key, value] - super - end - end - - # When we pretty-print the trees to compare against the snapshots, we want to - # be certain that we print with the same external encoding. This is because - # methods like Symbol#inspect take into account external encoding and it could - # change how the snapshot is generated. On machines with certain settings - # (like LANG=C or -Eascii-8bit) this could have been changed. So here we're - # going to force it to be UTF-8 to keep the snapshots consistent. - def setup - @previous_default_external = Encoding.default_external - ignore_warnings { Encoding.default_external = Encoding::UTF_8 } - end - - def teardown - ignore_warnings { Encoding.default_external = @previous_default_external } - end - - def test_empty_string - result = Prism.parse("") - assert_equal [], result.value.statements.body - end - - def test_parse_takes_file_path - filepath = "filepath.rb" - result = Prism.parse("def foo; __FILE__; end", filepath: filepath) - - assert_equal filepath, find_source_file_node(result.value).filepath - end - - def test_parse_takes_line - line = 4 - result = Prism.parse("def foo\n __FILE__\nend", line: line) - - assert_equal line, result.value.location.start_line - assert_equal line + 1, find_source_file_node(result.value).location.start_line - - result = Prism.parse_lex("def foo\n __FILE__\nend", line: line) - assert_equal line, result.value.first.location.start_line - end - - def test_parse_takes_negative_lines - line = -2 - result = Prism.parse("def foo\n __FILE__\nend", line: line) - - assert_equal line, result.value.location.start_line - assert_equal line + 1, find_source_file_node(result.value).location.start_line - - result = Prism.parse_lex("def foo\n __FILE__\nend", line: line) - assert_equal line, result.value.first.location.start_line - end - - def test_parse_lex - node, tokens = Prism.parse_lex("def foo; end").value - - assert_kind_of ProgramNode, node - assert_equal 5, tokens.length - end - - if !ENV["PRISM_BUILD_MINIMAL"] - def test_dump_file - assert_nothing_raised do - Prism.dump_file(__FILE__) - end - - error = assert_raise Errno::ENOENT do - Prism.dump_file("idontexist.rb") - end - - assert_equal "No such file or directory - idontexist.rb", error.message - - assert_raise TypeError do - Prism.dump_file(nil) - end - end - end - - def test_lex_file - assert_nothing_raised do - Prism.lex_file(__FILE__) - end - - error = assert_raise Errno::ENOENT do - Prism.lex_file("idontexist.rb") - end - - assert_equal "No such file or directory - idontexist.rb", error.message - - assert_raise TypeError do - Prism.lex_file(nil) - end - end - - def test_parse_lex_file - node, tokens = Prism.parse_lex_file(__FILE__).value - - assert_kind_of ProgramNode, node - refute_empty tokens - - error = assert_raise Errno::ENOENT do - Prism.parse_lex_file("idontexist.rb") - end - - assert_equal "No such file or directory - idontexist.rb", error.message - - assert_raise TypeError do - Prism.parse_lex_file(nil) - end - end - - def test_parse_file - node = Prism.parse_file(__FILE__).value - assert_kind_of ProgramNode, node - - error = assert_raise Errno::ENOENT do - Prism.parse_file("idontexist.rb") - end - - assert_equal "No such file or directory - idontexist.rb", error.message - - assert_raise TypeError do - Prism.parse_file(nil) - end - end - - def test_parse_file_success - assert_predicate Prism.parse_file_comments(__FILE__), :any? - - error = assert_raise Errno::ENOENT do - Prism.parse_file_comments("idontexist.rb") - end - - assert_equal "No such file or directory - idontexist.rb", error.message - - assert_raise TypeError do - Prism.parse_file_comments(nil) - end - end - - def test_parse_file_comments - assert_predicate Prism.parse_file_comments(__FILE__), :any? - - error = assert_raise Errno::ENOENT do - Prism.parse_file_comments("idontexist.rb") - end - - assert_equal "No such file or directory - idontexist.rb", error.message - - assert_raise TypeError do - Prism.parse_file_comments(nil) - end - end - - # To accurately compare against Ripper, we need to make sure that we're - # running on CRuby 3.2+. - ripper_enabled = RUBY_ENGINE == "ruby" && RUBY_VERSION >= "3.2.0" - - # The FOCUS environment variable allows you to specify one particular fixture - # to test, instead of all of them. - base = File.join(__dir__, "fixtures") - relatives = ENV["FOCUS"] ? [ENV["FOCUS"]] : Dir["**/*.txt", base: base] - - relatives.each do |relative| - # These fail on TruffleRuby due to a difference in Symbol#inspect: :测试 vs :"测试" - next if RUBY_ENGINE == "truffleruby" and %w[emoji_method_calls.txt seattlerb/bug202.txt seattlerb/magic_encoding_comment.txt].include?(relative) - - filepath = File.join(base, relative) - snapshot = File.expand_path(File.join("snapshots", relative), __dir__) - - directory = File.dirname(snapshot) - FileUtils.mkdir_p(directory) unless File.directory?(directory) - - ripper_should_match = ripper_enabled - check_valid_syntax = RUBY_VERSION >= "3.2.0" - - case relative - when "seattlerb/pct_w_heredoc_interp_nested.txt" - # This file has changed behavior in Ripper in Ruby 3.3, so we skip it if - # we're on an earlier version. - ripper_should_match = false if RUBY_VERSION < "3.3.0" - when "seattlerb/heredoc_nested.txt", "whitequark/dedenting_heredoc.txt" - # It seems like there are some oddities with nested heredocs and ripper. - # Waiting for feedback on https://bugs.ruby-lang.org/issues/19838. - ripper_should_match = false - when "spanning_heredoc.txt", "spanning_heredoc_newlines.txt" - # Ripper seems to have a bug that the regex portions before and after - # the heredoc are combined into a single token. See - # https://bugs.ruby-lang.org/issues/19838. - ripper_should_match = false - when "heredocs_leading_whitespace.txt" - # Ruby < 3.3.0 cannot parse heredocs where there are leading whitespace - # characters in the heredoc start. - # Example: <<~' EOF' or <<-' EOF' - # https://bugs.ruby-lang.org/issues/19539 - if RUBY_VERSION < "3.3.0" - ripper_should_match = false - check_valid_syntax = false - end - end - - define_method "test_filepath_#{relative}" do - # First, read the source from the filepath. Use binmode to avoid - # converting CRLF on Windows, and explicitly set the external encoding - # to UTF-8 to override the binmode default. - source = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8) - - # Make sure that the given source is valid syntax, otherwise we have an - # invalid fixture. - assert_valid_syntax(source) if check_valid_syntax - - # Next, assert that there were no errors during parsing. - result = Prism.parse(source, filepath: relative) - assert_empty result.errors - - # Next, pretty print the source. - printed = PP.pp(result.value, +"", 79) - - if File.exist?(snapshot) - saved = File.read(snapshot) - - # If the snapshot file exists, but the printed value does not match the - # snapshot, then update the snapshot file. - if printed != saved - File.write(snapshot, printed) - warn("Updated snapshot at #{snapshot}.") - end - - # If the snapshot file exists, then assert that the printed value - # matches the snapshot. - assert_equal(saved, printed) - else - # If the snapshot file does not yet exist, then write it out now. - File.write(snapshot, printed) - warn("Created snapshot at #{snapshot}.") - end - - if !ENV["PRISM_BUILD_MINIMAL"] - # Next, assert that the value can be serialized and deserialized - # without changing the shape of the tree. - assert_equal_nodes(result.value, Prism.load(source, Prism.dump(source, filepath: relative)).value) - end - - # Next, check that the location ranges of each node in the tree are a - # superset of their respective child nodes. - assert_non_overlapping_locations(result.value) - - # Next, assert that the newlines are in the expected places. - expected_newlines = [0] - source.b.scan("\n") { expected_newlines << $~.offset(0)[0] + 1 } - assert_equal expected_newlines, Debug.newlines(source) - - if ripper_should_match - # Finally, assert that we can lex the source and get the same tokens as - # Ripper. - lex_result = Prism.lex_compat(source) - assert_equal [], lex_result.errors - tokens = lex_result.value - - begin - Prism.lex_ripper(source).zip(tokens).each do |(ripper, prism)| - assert_equal ripper, prism - end - rescue SyntaxError - raise ArgumentError, "Test file has invalid syntax #{filepath}" - end - - # Next, check that we get the correct number of magic comments when - # lexing with ripper. - expected = MagicCommentRipper.new(source).tap(&:parse).magic_comments - actual = result.magic_comments - - assert_equal expected.length, actual.length - expected.zip(actual).each do |(expected_key, expected_value), magic_comment| - assert_equal expected_key, magic_comment.key - assert_equal expected_value, magic_comment.value - end - end - end - end - - Dir["*.txt", base: base].each do |relative| - next if relative == "newline_terminated.txt" || relative == "spanning_heredoc_newlines.txt" - - # We test every snippet (separated by \n\n) in isolation - # to ensure the parser does not try to read bytes further than the end of each snippet - define_method "test_individual_snippets_#{relative}" do - filepath = File.join(base, relative) - - # First, read the source from the filepath. Use binmode to avoid converting CRLF on Windows, - # and explicitly set the external encoding to UTF-8 to override the binmode default. - file_contents = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8) - - file_contents.split(/(?<=\S)\n\n(?=\S)/).each do |snippet| - snippet = snippet.rstrip - result = Prism.parse(snippet, filepath: relative) - assert_empty result.errors - - if !ENV["PRISM_BUILD_MINIMAL"] - assert_equal_nodes(result.value, Prism.load(snippet, Prism.dump(snippet, filepath: relative)).value) - end - end - end - end - - private - - # Check that the location ranges of each node in the tree are a superset of - # their respective child nodes. - def assert_non_overlapping_locations(node) - queue = [node] - - while (current = queue.shift) - # We only want to compare parent/child location overlap in the case that - # we are not looking at a heredoc. That's because heredoc locations are - # special in that they only use the declaration of the heredoc. - compare = !(current.is_a?(StringNode) || - current.is_a?(XStringNode) || - current.is_a?(InterpolatedStringNode) || - current.is_a?(InterpolatedXStringNode)) || - !current.opening&.start_with?("<<") - - current.child_nodes.each do |child| - # child_nodes can return nil values, so we need to skip those. - next unless child - - # Now that we know we have a child node, add that to the queue. - queue << child - - if compare - assert_operator current.location.start_offset, :<=, child.location.start_offset - assert_operator current.location.end_offset, :>=, child.location.end_offset - end - end - end - end - - def find_source_file_node(program) - queue = [program] - while (node = queue.shift) - return node if node.is_a?(SourceFileNode) - queue.concat(node.compact_child_nodes) - end - end - - def ignore_warnings - previous_verbosity = $VERBOSE - $VERBOSE = nil - yield - ensure - $VERBOSE = previous_verbosity - end - end -end diff --git a/test/prism/parser_test.rb b/test/prism/parser_test.rb deleted file mode 100644 index 79b65cf75b4..00000000000 --- a/test/prism/parser_test.rb +++ /dev/null @@ -1,186 +0,0 @@ -# frozen_string_literal: true - -require_relative "test_helper" - -begin - verbose, $VERBOSE = $VERBOSE, nil - require "parser/ruby33" - require "prism/translation/parser33" -rescue LoadError - # In CRuby's CI, we're not going to test against the parser gem because we - # don't want to have to install it. So in this case we'll just skip this test. - return -ensure - $VERBOSE = verbose -end - -# First, opt in to every AST feature. -Parser::Builders::Default.modernize - -# Modify the source map == check so that it doesn't check against the node -# itself so we don't get into a recursive loop. -Parser::Source::Map.prepend( - Module.new { - def ==(other) - self.class == other.class && - (instance_variables - %i[@node]).map do |ivar| - instance_variable_get(ivar) == other.instance_variable_get(ivar) - end.reduce(:&) - end - } -) - -# Next, ensure that we're comparing the nodes and also comparing the source -# ranges so that we're getting all of the necessary information. -Parser::AST::Node.prepend( - Module.new { - def ==(other) - super && (location == other.location) - end - } -) - -module Prism - class ParserTest < TestCase - base = File.join(__dir__, "fixtures") - - # These files are erroring because of the parser gem being wrong. - skip_incorrect = [ - "embdoc_no_newline_at_end.txt" - ] - - # These files are either failing to parse or failing to translate, so we'll - # skip them for now. - skip_all = skip_incorrect | [ - "dash_heredocs.txt", - "dos_endings.txt", - "heredocs_with_ignored_newlines.txt", - "regex.txt", - "regex_char_width.txt", - "spanning_heredoc.txt", - "spanning_heredoc_newlines.txt", - "unescaping.txt" - ] - - # Not sure why these files are failing on JRuby, but skipping them for now. - if RUBY_ENGINE == "jruby" - skip_all.push("emoji_method_calls.txt", "symbols.txt") - end - - # These files are failing to translate their lexer output into the lexer - # output expected by the parser gem, so we'll skip them for now. - skip_tokens = [ - "comments.txt", - "heredoc_with_comment.txt", - "indented_file_end.txt", - "methods.txt", - "strings.txt", - "tilde_heredocs.txt", - "xstring_with_backslash.txt" - ] - - Dir["*.txt", base: base].each do |name| - next if skip_all.include?(name) - - define_method("test_#{name}") do - assert_equal_parses(File.join(base, name), compare_tokens: !skip_tokens.include?(name)) - end - end - - private - - def assert_equal_parses(filepath, compare_tokens: true) - buffer = Parser::Source::Buffer.new(filepath, 1) - buffer.source = File.read(filepath) - - parser = Parser::Ruby33.new - parser.diagnostics.consumer = ->(*) {} - parser.diagnostics.all_errors_are_fatal = true - - expected_ast, expected_comments, expected_tokens = - begin - parser.tokenize(buffer) - rescue ArgumentError, Parser::SyntaxError - return - end - - actual_ast, actual_comments, actual_tokens = - Prism::Translation::Parser33.new.tokenize(buffer) - - assert_equal expected_ast, actual_ast, -> { assert_equal_asts_message(expected_ast, actual_ast) } - assert_equal_tokens(expected_tokens, actual_tokens) if compare_tokens - assert_equal_comments(expected_comments, actual_comments) - end - - def assert_equal_asts_message(expected_ast, actual_ast) - queue = [[expected_ast, actual_ast]] - - while (left, right = queue.shift) - if left.type != right.type - return "expected: #{left.type}\nactual: #{right.type}" - end - - if left.location != right.location - return "expected:\n#{left.inspect}\n#{left.location.inspect}\nactual:\n#{right.inspect}\n#{right.location.inspect}" - end - - if left.type == :str && left.children[0] != right.children[0] - return "expected: #{left.inspect}\nactual: #{right.inspect}" - end - - left.children.zip(right.children).each do |left_child, right_child| - queue << [left_child, right_child] if left_child.is_a?(Parser::AST::Node) - end - end - - "expected: #{expected_ast.inspect}\nactual: #{actual_ast.inspect}" - end - - def assert_equal_tokens(expected_tokens, actual_tokens) - if expected_tokens != actual_tokens - expected_index = 0 - actual_index = 0 - - while expected_index < expected_tokens.length - expected_token = expected_tokens[expected_index] - actual_token = actual_tokens[actual_index] - - expected_index += 1 - actual_index += 1 - - # The parser gem always has a space before a string end in list - # literals, but we don't. So we'll skip over the space. - if expected_token[0] == :tSPACE && actual_token[0] == :tSTRING_END - expected_index += 1 - next - end - - # There are a lot of tokens that have very specific meaning according - # to the context of the parser. We don't expose that information in - # prism, so we need to normalize these tokens a bit. - case actual_token[0] - when :kDO - actual_token[0] = expected_token[0] if %i[kDO_BLOCK kDO_LAMBDA].include?(expected_token[0]) - when :tLPAREN - actual_token[0] = expected_token[0] if expected_token[0] == :tLPAREN2 - when :tPOW - actual_token[0] = expected_token[0] if expected_token[0] == :tDSTAR - end - - # Now we can assert that the tokens are actually equal. - assert_equal expected_token, actual_token, -> { - "expected: #{expected_token.inspect}\n" \ - "actual: #{actual_token.inspect}" - } - end - end - end - - def assert_equal_comments(expected_comments, actual_comments) - assert_equal expected_comments, actual_comments, -> { - "expected: #{expected_comments.inspect}\n" \ - "actual: #{actual_comments.inspect}" - } - end - end -end diff --git a/test/prism/redundant_return_test.rb b/test/prism/redundant_return_test.rb deleted file mode 100644 index c6681692452..00000000000 --- a/test/prism/redundant_return_test.rb +++ /dev/null @@ -1,73 +0,0 @@ -# frozen_string_literal: true - -require_relative "test_helper" - -module Prism - class RedundantReturnTest < TestCase - def test_statements - assert_redundant_return("def foo; return; end") - refute_redundant_return("def foo; return; 1; end") - end - - def test_begin_implicit - assert_redundant_return("def foo; return; rescue; end") - refute_redundant_return("def foo; return; 1; rescue; end") - refute_redundant_return("def foo; return; rescue; else; end") - end - - def test_begin_explicit - assert_redundant_return("def foo; begin; return; rescue; end; end") - refute_redundant_return("def foo; begin; return; 1; rescue; end; end") - refute_redundant_return("def foo; begin; return; rescue; else; end; end") - end - - def test_if - assert_redundant_return("def foo; return if bar; end") - end - - def test_unless - assert_redundant_return("def foo; return unless bar; end") - end - - def test_else - assert_redundant_return("def foo; if bar; baz; else; return; end; end") - end - - def test_case_when - assert_redundant_return("def foo; case bar; when baz; return; end; end") - end - - def test_case_else - assert_redundant_return("def foo; case bar; when baz; else; return; end; end") - end - - def test_case_match_in - assert_redundant_return("def foo; case bar; in baz; return; end; end") - end - - def test_case_match_else - assert_redundant_return("def foo; case bar; in baz; else; return; end; end") - end - - private - - def assert_redundant_return(source) - assert find_return(source).redundant? - end - - def refute_redundant_return(source) - refute find_return(source).redundant? - end - - def find_return(source) - queue = [Prism.parse(source).value] - - while (current = queue.shift) - return current if current.is_a?(ReturnNode) - queue.concat(current.compact_child_nodes) - end - - flunk "Could not find return node in #{node.inspect}" - end - end -end diff --git a/test/prism/regexp_test.rb b/test/prism/regexp_test.rb index 0a5fc2b4fc4..297020fc72e 100644 --- a/test/prism/regexp_test.rb +++ b/test/prism/regexp_test.rb @@ -2,78 +2,84 @@ require_relative "test_helper" -return if Prism::BACKEND == :FFI - module Prism class RegexpTest < TestCase - ############################################################################## + ############################################################################ # These tests test the actual use case of extracting named capture groups - ############################################################################## + ############################################################################ def test_named_captures_with_arrows - assert_equal(["foo"], named_captures("(?bar)")) + assert_equal([:foo], named_captures("(?bar)")) end def test_named_captures_with_single_quotes - assert_equal(["foo"], named_captures("(?'foo'bar)")) + assert_equal([:foo], named_captures("(?'foo'bar)")) end def test_nested_named_captures_with_arrows - assert_equal(["foo", "bar"], named_captures("(?(?baz))")) + assert_equal([:foo, :bar], named_captures("(?(?baz))")) end def test_nested_named_captures_with_single_quotes - assert_equal(["foo", "bar"], named_captures("(?'foo'(?'bar'baz))")) + assert_equal([:foo, :bar], named_captures("(?'foo'(?'bar'baz))")) end def test_allows_duplicate_named_captures - assert_equal(["foo", "foo"], named_captures("(?bar)(?baz)")) + assert_equal([:foo], named_captures("(?bar)(?baz)")) end def test_named_capture_inside_fake_range_quantifier - assert_equal(["foo"], named_captures("foo{1, (?2)}")) + assert_equal([:foo], named_captures("foo{1, (?2)}")) + end + + def test_fake_named_captures_inside_character_sets + assert_equal([], named_captures("[a-z(?)]")) end - ############################################################################## + def test_fake_named_capture_inside_character_set_with_escaped_ending + assert_equal([], named_captures("[a-z\\](?)]")) + end + + ############################################################################ # These tests test the rest of the AST. They are not exhaustive, but they # should cover the most common cases. We test these to make sure we don't # accidentally regress and stop being able to extract named captures. - ############################################################################## + ############################################################################ def test_alternation - refute_nil(named_captures("foo|bar")) + assert_valid_regexp("foo|bar") end def test_anchors - refute_nil(named_captures("^foo$")) + assert_valid_regexp("^foo$") end def test_any - refute_nil(named_captures(".")) + assert_valid_regexp(".") end def test_posix_character_classes - refute_nil(named_captures("[[:digit:]]")) + assert_valid_regexp("[[:digit:]]") end def test_negated_posix_character_classes - refute_nil(named_captures("[[:^digit:]]")) + assert_valid_regexp("[[:^digit:]]") end def test_invalid_posix_character_classes_should_fall_back_to_regular_classes - refute_nil(named_captures("[[:foo]]")) + assert_valid_regexp("[[:foo]]") end def test_character_sets - refute_nil(named_captures("[abc]")) + assert_valid_regexp("[abc]") end def test_nested_character_sets - refute_nil(named_captures("[[abc]]")) + assert_valid_regexp("[[abc]]") end def test_nested_character_sets_with_operators - refute_nil(named_captures("[[abc] && [def]]")) + assert_valid_regexp("[[abc] && [def]]") end def test_named_capture_inside_nested_character_set @@ -81,120 +87,108 @@ def test_named_capture_inside_nested_character_set end def test_negated_character_sets - refute_nil(named_captures("[^abc]")) + assert_valid_regexp("[^abc]") end def test_character_ranges - refute_nil(named_captures("[a-z]")) + assert_valid_regexp("[a-z]") end def test_negated_character_ranges - refute_nil(named_captures("[^a-z]")) - end - - def test_fake_named_captures_inside_character_sets - assert_equal([], named_captures("[a-z(?)]")) - end - - def test_fake_named_capture_inside_character_set_with_escaped_ending - assert_equal([], named_captures("[a-z\\](?)]")) + assert_valid_regexp("[^a-z]") end def test_comments - refute_nil(named_captures("(?#foo)")) + assert_valid_regexp("(?#foo)") end def test_comments_with_escaped_parentheses - refute_nil(named_captures("(?#foo\\)\\))")) + assert_valid_regexp("(?#foo\\)\\))") end def test_non_capturing_groups - refute_nil(named_captures("(?:foo)")) + assert_valid_regexp("(?:foo)") end def test_positive_lookaheads - refute_nil(named_captures("(?=foo)")) + assert_valid_regexp("(?=foo)") end def test_negative_lookaheads - refute_nil(named_captures("(?!foo)")) + assert_valid_regexp("(?!foo)") end def test_positive_lookbehinds - refute_nil(named_captures("(?<=foo)")) + assert_valid_regexp("(?<=foo)") end def test_negative_lookbehinds - refute_nil(named_captures("(?foo)")) + assert_valid_regexp("(?>foo)") end def test_absence_operator - refute_nil(named_captures("(?~foo)")) + assert_valid_regexp("(?~foo)") end def test_conditional_expression_with_index - refute_nil(named_captures("(?(1)foo)")) + assert_valid_regexp("(?(1)foo)") end def test_conditional_expression_with_name - refute_nil(named_captures("(?(foo)bar)")) + assert_valid_regexp("(?(foo)bar)") end def test_conditional_expression_with_group - refute_nil(named_captures("(?()bar)")) + assert_valid_regexp("(?()bar)") end def test_options_on_groups - refute_nil(named_captures("(?imxdau:foo)")) - end - - def test_options_on_groups_with_invalid_options - assert_nil(named_captures("(?z:bar)")) + assert_valid_regexp("(?imxdau:foo)") end def test_options_on_groups_getting_turned_off - refute_nil(named_captures("(?-imx:foo)")) + assert_valid_regexp("(?-imx:foo)") end def test_options_on_groups_some_getting_turned_on_some_getting_turned_off - refute_nil(named_captures("(?im-x:foo)")) + assert_valid_regexp("(?im-x:foo)") end def test_star_quantifier - refute_nil(named_captures("foo*")) + assert_valid_regexp("foo*") end def test_plus_quantifier - refute_nil(named_captures("foo+")) + assert_valid_regexp("foo+") end def test_question_mark_quantifier - refute_nil(named_captures("foo?")) + assert_valid_regexp("foo?") end def test_endless_range_quantifier - refute_nil(named_captures("foo{1,}")) + assert_valid_regexp("foo{1,}") end def test_beginless_range_quantifier - refute_nil(named_captures("foo{,1}")) + assert_valid_regexp("foo{,1}") end def test_range_quantifier - refute_nil(named_captures("foo{1,2}")) + assert_valid_regexp("foo{1,2}") end def test_fake_range_quantifier_because_of_spaces - refute_nil(named_captures("foo{1, 2}")) + assert_valid_regexp("foo{1, 2}") end - ############################################################################## + ############################################################################ # These test that flag values are correct. - ############################################################################## + ############################################################################ def test_flag_ignorecase assert_equal(Regexp::IGNORECASE, options("i")) @@ -229,26 +223,30 @@ def test_flag_combined def test_last_encoding_option_wins regex = "/foo/nu" - option = Prism.parse(regex).value.statements.body.first.options + option = Prism.parse_statement(regex).options assert_equal Regexp::FIXEDENCODING, option regex = "/foo/un" - option = Prism.parse(regex).value.statements.body.first.options + option = Prism.parse_statement(regex).options assert_equal Regexp::NOENCODING, option end private + def assert_valid_regexp(source) + assert Prism.parse_success?("/#{source}/ =~ \"\"") + end + def named_captures(source) - Debug.named_captures(source) + Prism.parse("/#{source}/ =~ \"\"").value.locals end def options(flags) options = ["/foo/#{flags}", "/foo\#{1}/#{flags}"].map do |source| - Prism.parse(source).value.statements.body.first.options + Prism.parse_statement(source).options end # Check that we get the same set of options from both regular expressions diff --git a/test/prism/attribute_write_test.rb b/test/prism/result/attribute_write_test.rb similarity index 86% rename from test/prism/attribute_write_test.rb rename to test/prism/result/attribute_write_test.rb index bd83d72da35..8f2e3527380 100644 --- a/test/prism/attribute_write_test.rb +++ b/test/prism/result/attribute_write_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "test_helper" +require_relative "../test_helper" module Prism class AttributeWriteTest < TestCase @@ -41,18 +41,14 @@ def test_comparison_operators private - def parse(source) - Prism.parse(source).value.statements.body.first - end - def assert_attribute_write(source) - call = parse(source) + call = Prism.parse_statement(source) assert(call.attribute_write?) assert_equal(1, eval(source)) end def refute_attribute_write(source) - call = parse(source) + call = Prism.parse_statement(source) refute(call.attribute_write?) refute_equal(1, eval(source)) end diff --git a/test/prism/result/breadth_first_search_test.rb b/test/prism/result/breadth_first_search_test.rb new file mode 100644 index 00000000000..e2e043a9021 --- /dev/null +++ b/test/prism/result/breadth_first_search_test.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class BreadthFirstSearchTest < TestCase + def test_breadth_first_search + result = Prism.parse("[1 + 2, 2]") + found = + result.value.breadth_first_search do |node| + node.is_a?(IntegerNode) && node.value == 2 + end + + refute_nil found + assert_equal 8, found.start_offset + end + end +end diff --git a/test/prism/comments_test.rb b/test/prism/result/comments_test.rb similarity index 97% rename from test/prism/comments_test.rb rename to test/prism/result/comments_test.rb index b99c00268c3..178623a75ff 100644 --- a/test/prism/comments_test.rb +++ b/test/prism/result/comments_test.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true -require_relative "test_helper" +require_relative "../test_helper" module Prism class CommentsTest < TestCase def test_comment_inline source = "# comment" - assert_equal [0], Debug.newlines(source) + assert_equal [0], Prism.parse(source).source.offsets assert_comment( source, diff --git a/test/prism/constant_path_node_test.rb b/test/prism/result/constant_path_node_test.rb similarity index 78% rename from test/prism/constant_path_node_test.rb rename to test/prism/result/constant_path_node_test.rb index dffb55c0ffe..75925600ca7 100644 --- a/test/prism/constant_path_node_test.rb +++ b/test/prism/result/constant_path_node_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "test_helper" +require_relative "../test_helper" module Prism class ConstantPathNodeTest < TestCase @@ -11,7 +11,7 @@ def test_full_name_for_constant_path Qux RUBY - constant_path = Prism.parse(source).value.statements.body.first + constant_path = Prism.parse_statement(source) assert_equal("Foo::Bar::Baz::Qux", constant_path.full_name) end @@ -22,7 +22,7 @@ def test_full_name_for_constant_path_with_self Qux RUBY - constant_path = Prism.parse(source).value.statements.body.first + constant_path = Prism.parse_statement(source) assert_raise(ConstantPathNode::DynamicPartsInConstantPathError) do constant_path.full_name end @@ -35,7 +35,7 @@ def test_full_name_for_constant_path_with_variable Qux RUBY - constant_path = Prism.parse(source).value.statements.body.first + constant_path = Prism.parse_statement(source) assert_raise(ConstantPathNode::DynamicPartsInConstantPathError) do constant_path.full_name @@ -49,7 +49,7 @@ def test_full_name_for_constant_path_target Qux, Something = [1, 2] RUBY - node = Prism.parse(source).value.statements.body.first + node = Prism.parse_statement(source) assert_equal("Foo::Bar::Baz::Qux", node.lefts.first.full_name) end @@ -60,7 +60,7 @@ def test_full_name_for_constant_path_with_stovetop_start Qux, Something = [1, 2] RUBY - node = Prism.parse(source).value.statements.body.first + node = Prism.parse_statement(source) assert_equal("::Foo::Bar::Baz::Qux", node.lefts.first.full_name) end @@ -69,7 +69,7 @@ def test_full_name_for_constant_path_target_with_non_constant_parent self::Foo, Bar = [1, 2] RUBY - constant_target = Prism.parse(source).value.statements.body.first + constant_target = Prism.parse_statement(source) dynamic, static = constant_target.lefts assert_raise(ConstantPathNode::DynamicPartsInConstantPathError) do @@ -84,7 +84,7 @@ def test_full_name_for_constant_read_node Bar RUBY - constant = Prism.parse(source).value.statements.body.first + constant = Prism.parse_statement(source) assert_equal("Bar", constant.full_name) end end diff --git a/test/prism/result/equality_test.rb b/test/prism/result/equality_test.rb new file mode 100644 index 00000000000..4f6e665a88c --- /dev/null +++ b/test/prism/result/equality_test.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class EqualityTest < TestCase + def test_equality + assert_operator Prism.parse_statement("1"), :===, Prism.parse_statement("1") + assert_operator Prism.parse("1").value, :===, Prism.parse("1").value + + complex_source = "class Something; @var = something.else { _1 }; end" + assert_operator Prism.parse_statement(complex_source), :===, Prism.parse_statement(complex_source) + + refute_operator Prism.parse_statement("1"), :===, Prism.parse_statement("2") + refute_operator Prism.parse_statement("1"), :===, Prism.parse_statement("0x1") + + complex_source_1 = "class Something; @var = something.else { _1 }; end" + complex_source_2 = "class Something; @var = something.else { _2 }; end" + refute_operator Prism.parse_statement(complex_source_1), :===, Prism.parse_statement(complex_source_2) + end + end +end diff --git a/test/prism/result/heredoc_test.rb b/test/prism/result/heredoc_test.rb new file mode 100644 index 00000000000..7913c04a88e --- /dev/null +++ b/test/prism/result/heredoc_test.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class HeredocTest < TestCase + def test_heredoc? + refute Prism.parse_statement("\"foo\"").heredoc? + refute Prism.parse_statement("\"foo \#{1}\"").heredoc? + refute Prism.parse_statement("`foo`").heredoc? + refute Prism.parse_statement("`foo \#{1}`").heredoc? + + assert Prism.parse_statement("<<~HERE\nfoo\nHERE\n").heredoc? + assert Prism.parse_statement("<<~HERE\nfoo \#{1}\nHERE\n").heredoc? + assert Prism.parse_statement("<<~`HERE`\nfoo\nHERE\n").heredoc? + assert Prism.parse_statement("<<~`HERE`\nfoo \#{1}\nHERE\n").heredoc? + end + end +end diff --git a/test/prism/result/implicit_array_test.rb b/test/prism/result/implicit_array_test.rb new file mode 100644 index 00000000000..e7ddde70aa4 --- /dev/null +++ b/test/prism/result/implicit_array_test.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class ImplicitArrayTest < TestCase + def test_call_node + assert_implicit_array("a.a = *b") + assert_implicit_array("a.a = 1, 2, 3") + assert_implicit_array("a[a] = *b") + assert_implicit_array("a[a] = 1, 2, 3") + end + + def test_class_variable_write_node + assert_implicit_array("@@a = *b") + assert_implicit_array("@@a = 1, 2, 3") + end + + def test_constant_path_write_node + assert_implicit_array("A::A = *b") + assert_implicit_array("A::A = 1, 2, 3") + end + + def test_constant_write_node + assert_implicit_array("A = *b") + assert_implicit_array("A = 1, 2, 3") + end + + def test_global_variable_write_node + assert_implicit_array("$a = *b") + assert_implicit_array("$a = 1, 2, 3") + end + + def test_instance_variable_write_node + assert_implicit_array("@a = *b") + assert_implicit_array("@a = 1, 2, 3") + end + + def test_local_variable_write_node + assert_implicit_array("a = *b") + assert_implicit_array("a = 1, 2, 3") + end + + def test_multi_write_node + assert_implicit_array("a, b, c = *b") + assert_implicit_array("a, b, c = 1, 2, 3") + end + + private + + def assert_implicit_array(source) + assert Prism.parse_success?(source) + assert Prism.parse_failure?("if #{source} then end") + + assert_valid_syntax(source) + refute_valid_syntax("if #{source} then end") + end + end +end diff --git a/test/prism/index_write_test.rb b/test/prism/result/index_write_test.rb similarity index 98% rename from test/prism/index_write_test.rb rename to test/prism/result/index_write_test.rb index cf90eb082fe..0d5383b6012 100644 --- a/test/prism/index_write_test.rb +++ b/test/prism/result/index_write_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "test_helper" +require_relative "../test_helper" module Prism class IndexWriteTest < TestCase diff --git a/test/prism/result/integer_base_flags_test.rb b/test/prism/result/integer_base_flags_test.rb new file mode 100644 index 00000000000..e3ab8c69109 --- /dev/null +++ b/test/prism/result/integer_base_flags_test.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class IntegerBaseFlagsTest < TestCase + # Through some bit hackery, we want to allow consumers to use the integer + # base flags as the base itself. It has a nice property that the current + # alignment provides them in the correct order. So here we test that our + # assumption holds so that it doesn't change out from under us. + # + # In C, this would look something like: + # + # ((flags & ~DECIMAL) >> 1) || 10 + # + # We have to do some other work in Ruby because 0 is truthy and ~ on an + # integer doesn't have a fixed width. + def test_flags + assert_equal 2, base("0b1") + assert_equal 8, base("0o1") + assert_equal 10, base("0d1") + assert_equal 16, base("0x1") + end + + private + + def base(source) + node = Prism.parse_statement(source) + value = (node.send(:flags) & (0b111100 - IntegerBaseFlags::DECIMAL)) >> 1 + value == 0 ? 10 : value + end + end +end diff --git a/test/prism/integer_parse_test.rb b/test/prism/result/integer_parse_test.rb similarity index 84% rename from test/prism/integer_parse_test.rb rename to test/prism/result/integer_parse_test.rb index f42e817e793..7b5ce98bb6a 100644 --- a/test/prism/integer_parse_test.rb +++ b/test/prism/result/integer_parse_test.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true -require_relative "test_helper" - -return if Prism::BACKEND == :FFI +require_relative "../test_helper" module Prism class IntegerParseTest < TestCase @@ -37,9 +35,7 @@ def test_integer_parse private def assert_integer_parse(expected, source = expected.to_s) - integer, string = Debug.integer_parse(source) - assert_equal expected, integer - assert_equal expected.to_s, string + assert_equal expected, Prism.parse_statement(source).value end end end diff --git a/test/prism/result/node_id_test.rb b/test/prism/result/node_id_test.rb new file mode 100644 index 00000000000..59b79bc5746 --- /dev/null +++ b/test/prism/result/node_id_test.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class NodeIdTest < TestCase + Fixture.each do |fixture| + define_method(fixture.test_name) { assert_node_ids(fixture.read) } + end + + private + + def assert_node_ids(source) + queue = [Prism.parse(source).value] + node_ids = [] + + while (node = queue.shift) + node_ids << node.node_id + queue.concat(node.compact_child_nodes) + end + + node_ids.sort! + refute_includes node_ids, 0 + assert_equal node_ids, node_ids.uniq + end + end +end diff --git a/test/prism/result/numeric_value_test.rb b/test/prism/result/numeric_value_test.rb new file mode 100644 index 00000000000..5c89230a1fe --- /dev/null +++ b/test/prism/result/numeric_value_test.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class NumericValueTest < TestCase + def test_numeric_value + assert_equal 123, Prism.parse_statement("123").value + assert_equal 3.14, Prism.parse_statement("3.14").value + assert_equal 42i, Prism.parse_statement("42i").value + assert_equal 42.1ri, Prism.parse_statement("42.1ri").value + assert_equal 3.14i, Prism.parse_statement("3.14i").value + assert_equal 42r, Prism.parse_statement("42r").value + assert_equal 0.5r, Prism.parse_statement("0.5r").value + assert_equal 42ri, Prism.parse_statement("42ri").value + assert_equal 0.5ri, Prism.parse_statement("0.5ri").value + assert_equal 0xFFr, Prism.parse_statement("0xFFr").value + assert_equal 0xFFri, Prism.parse_statement("0xFFri").value + end + end +end diff --git a/test/prism/result/overlap_test.rb b/test/prism/result/overlap_test.rb new file mode 100644 index 00000000000..155bc870d36 --- /dev/null +++ b/test/prism/result/overlap_test.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class OverlapTest < TestCase + Fixture.each do |fixture| + define_method(fixture.test_name) { assert_overlap(fixture) } + end + + private + + # Check that the location ranges of each node in the tree are a superset of + # their respective child nodes. + def assert_overlap(fixture) + queue = [Prism.parse_file(fixture.full_path).value] + + while (current = queue.shift) + # We only want to compare parent/child location overlap in the case that + # we are not looking at a heredoc. That's because heredoc locations are + # special in that they only use the declaration of the heredoc. + compare = !(current.is_a?(StringNode) || + current.is_a?(XStringNode) || + current.is_a?(InterpolatedStringNode) || + current.is_a?(InterpolatedXStringNode)) || + !current.opening&.start_with?("<<") + + current.child_nodes.each do |child| + # child_nodes can return nil values, so we need to skip those. + next unless child + + # Now that we know we have a child node, add that to the queue. + queue << child + + if compare + assert_operator current.location.start_offset, :<=, child.location.start_offset + assert_operator current.location.end_offset, :>=, child.location.end_offset + end + end + end + end + end +end diff --git a/test/prism/result/regular_expression_options_test.rb b/test/prism/result/regular_expression_options_test.rb new file mode 100644 index 00000000000..ff6e20526fd --- /dev/null +++ b/test/prism/result/regular_expression_options_test.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class RegularExpressionOptionsTest < TestCase + def test_options + assert_equal "", Prism.parse_statement("__FILE__").filepath + assert_equal "foo.rb", Prism.parse_statement("__FILE__", filepath: "foo.rb").filepath + + assert_equal 1, Prism.parse_statement("foo").location.start_line + assert_equal 10, Prism.parse_statement("foo", line: 10).location.start_line + + refute Prism.parse_statement("\"foo\"").frozen? + assert Prism.parse_statement("\"foo\"", frozen_string_literal: true).frozen? + refute Prism.parse_statement("\"foo\"", frozen_string_literal: false).frozen? + + assert_kind_of CallNode, Prism.parse_statement("foo") + assert_kind_of LocalVariableReadNode, Prism.parse_statement("foo", scopes: [[:foo]]) + assert_equal 1, Prism.parse_statement("foo", scopes: [[:foo], []]).depth + + assert_equal [:foo], Prism.parse("foo", scopes: [[:foo]]).value.locals + end + end +end diff --git a/test/prism/location_test.rb b/test/prism/result/source_location_test.rb similarity index 97% rename from test/prism/location_test.rb rename to test/prism/result/source_location_test.rb index 07249956715..7bdc707658e 100644 --- a/test/prism/location_test.rb +++ b/test/prism/result/source_location_test.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true -require_relative "test_helper" +require_relative "../test_helper" module Prism - class LocationTest < TestCase + class SourceLocationTest < TestCase def test_AliasGlobalVariableNode assert_location(AliasGlobalVariableNode, "alias $foo $bar") end @@ -175,14 +175,6 @@ def test_CallNode assert_location(CallNode, "foo bar baz") assert_location(CallNode, "foo bar('baz')") - - assert_location(CallNode, "-> { it }", 5...7, version: "3.3.0") do |node| - node.body.body.first - end - - assert_location(LocalVariableReadNode, "-> { it }", 5...7, version: "3.4.0") do |node| - node.body.body.first - end end def test_CallAndWriteNode @@ -323,8 +315,8 @@ def test_DefinedNode end def test_ElseNode - assert_location(ElseNode, "if foo; bar; else; baz; end", 13...27, &:consequent) - assert_location(ElseNode, "foo ? bar : baz", 10...15, &:consequent) + assert_location(ElseNode, "if foo; bar; else; baz; end", 13...27, &:subsequent) + assert_location(ElseNode, "foo ? bar : baz", 10...15, &:subsequent) end def test_EmbeddedStatementsNode @@ -543,6 +535,24 @@ def test_InterpolatedXStringNode assert_location(InterpolatedXStringNode, '`foo #{bar} baz`') end + def test_ItLocalVariableReadNode + assert_location(ItLocalVariableReadNode, "-> { it }", 5...7) do |node| + node.body.body.first + end + + assert_location(ItLocalVariableReadNode, "foo { it }", 6...8) do |node| + node.block.body.body.first + end + + assert_location(CallNode, "-> { it }", 5...7, version: "3.3.0") do |node| + node.body.body.first + end + + assert_location(ItLocalVariableReadNode, "-> { it }", 5...7, version: "3.4.0") do |node| + node.body.body.first + end + end + def test_ItParametersNode assert_location(ItParametersNode, "-> { it }", &:parameters) end @@ -583,12 +593,6 @@ def test_LocalVariableOrWriteNode def test_LocalVariableReadNode assert_location(LocalVariableReadNode, "foo = 1; foo", 9...12) - assert_location(LocalVariableReadNode, "-> { it }", 5...7) do |node| - node.body.body.first - end - assert_location(LocalVariableReadNode, "foo { it }", 6...8) do |node| - node.block.body.body.first - end end def test_LocalVariableTargetNode @@ -754,7 +758,7 @@ def test_RescueNode end RUBY assert_location(RescueNode, code, 13...50) { |node| node.rescue_clause } - assert_location(RescueNode, code, 30...50) { |node| node.rescue_clause.consequent } + assert_location(RescueNode, code, 30...50) { |node| node.rescue_clause.subsequent } end def test_RescueModifierNode @@ -823,8 +827,8 @@ def test_StatementsNode assert_location(StatementsNode, "if foo; bar; end", 8...11, &:statements) assert_location(StatementsNode, "foo if bar", 0...3, &:statements) - assert_location(StatementsNode, "if foo; foo; elsif bar; bar; end", 24...27) { |node| node.consequent.statements } - assert_location(StatementsNode, "if foo; foo; else; bar; end", 19...22) { |node| node.consequent.statements } + assert_location(StatementsNode, "if foo; foo; elsif bar; bar; end", 24...27) { |node| node.subsequent.statements } + assert_location(StatementsNode, "if foo; foo; else; bar; end", 19...22) { |node| node.subsequent.statements } assert_location(StatementsNode, "unless foo; bar; end", 12...15, &:statements) assert_location(StatementsNode, "foo unless bar", 0...3, &:statements) @@ -917,7 +921,7 @@ def test_YieldNode def test_all_tested expected = Prism.constants.grep(/.Node$/).sort - %i[MissingNode ProgramNode] - actual = LocationTest.instance_methods(false).grep(/.Node$/).map { |name| name[5..].to_sym }.sort + actual = SourceLocationTest.instance_methods(false).grep(/.Node$/).map { |name| name[5..].to_sym }.sort assert_equal expected, actual end diff --git a/test/prism/static_inspect_test.rb b/test/prism/result/static_inspect_test.rb similarity index 92% rename from test/prism/static_inspect_test.rb rename to test/prism/result/static_inspect_test.rb index 8df2fd241e0..cf8cef3298a 100644 --- a/test/prism/static_inspect_test.rb +++ b/test/prism/result/static_inspect_test.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true -require_relative "test_helper" - -return if Prism::BACKEND == :FFI +require_relative "../test_helper" module Prism class StaticInspectTest < TestCase @@ -84,7 +82,8 @@ def test_true private def static_inspect(source, **options) - Debug.static_inspect(source, **options) + warnings = Prism.parse("{ #{source} => 1, #{source} => 1 }", **options).warnings + warnings.last.message[/^key (.+) is duplicated and overwritten on line \d/, 1] end end end diff --git a/test/prism/static_literals_test.rb b/test/prism/result/static_literals_test.rb similarity index 98% rename from test/prism/static_literals_test.rb rename to test/prism/result/static_literals_test.rb index 31c802bf90d..dcfc692897c 100644 --- a/test/prism/static_literals_test.rb +++ b/test/prism/result/static_literals_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "test_helper" +require_relative "../test_helper" module Prism class StaticLiteralsTest < TestCase diff --git a/test/prism/result/warnings_test.rb b/test/prism/result/warnings_test.rb new file mode 100644 index 00000000000..04542dbada1 --- /dev/null +++ b/test/prism/result/warnings_test.rb @@ -0,0 +1,432 @@ +# frozen_string_literal: true + +return if RUBY_VERSION < "3.1" + +require_relative "../test_helper" + +module Prism + class WarningsTest < TestCase + def test_ambiguous_uminus + assert_warning("a -b", "ambiguous first argument") + end + + def test_ambiguous_uplus + assert_warning("a +b", "ambiguous first argument") + end + + def test_ambiguous_ustar + assert_warning("a *b", "argument prefix") + end + + def test_ambiguous_regexp + assert_warning("a /b/", "wrap regexp in parentheses") + end + + def test_ambiguous_ampersand + assert_warning("a &b", "argument prefix") + assert_warning("a &:+", "argument prefix") + + refute_warning("a &:b") + refute_warning("a &:'b'") + refute_warning("a &:\"b\"") + end + + def test_binary_operator + [ + [:**, "argument prefix"], + [:*, "argument prefix"], + [:<<, "here document"], + [:&, "argument prefix"], + [:+, "unary operator"], + [:-, "unary operator"], + [:/, "regexp literal"], + [:%, "string literal"] + ].each do |(operator, warning)| + assert_warning("puts 1 #{operator}0", warning) + assert_warning("puts :a #{operator}0", warning) + assert_warning("m = 1; puts m #{operator}0", warning) + end + end + + def test_equal_in_conditional + assert_warning("if a = 1; end; a = a", "should be ==") + end + + def test_dot_dot_dot_eol + assert_warning("_ = foo...", "... at EOL") + assert_warning("def foo(...) = bar ...", "... at EOL") + + assert_warning("_ = foo... #", "... at EOL") + assert_warning("_ = foo... \t\v\f\n", "... at EOL") + + refute_warning("p foo...bar") + refute_warning("p foo... bar") + end + + def test_END_in_method + assert_warning("def foo; END {}; end", "END in method") + end + + def test_duplicated_hash_key + assert_warning("{ a: 1, a: 2 }", "duplicated and overwritten") + assert_warning("{ a: 1, **{ a: 2 } }", "duplicated and overwritten") + end + + def test_duplicated_when_clause + assert_warning("case 1; when 1, 1; end", "when' clause") + end + + def test_float_out_of_range + assert_warning("_ = 1.0e100000", "out of range") + end + + def test_indentation_mismatch + assert_warning("if true\n end", "mismatched indentations at 'end' with 'if'") + assert_warning("if true\n elsif true\nend", "mismatched indentations at 'elsif' with 'if'") + assert_warning("if true\n else\nend", "mismatched indentations at 'else' with 'if'", "mismatched indentations at 'end' with 'else'") + + assert_warning("unless true\n end", "mismatched indentations at 'end' with 'unless'") + assert_warning("unless true\n else\nend", "mismatched indentations at 'else' with 'unless'", "mismatched indentations at 'end' with 'else'") + + assert_warning("while true\n end", "mismatched indentations at 'end' with 'while'") + assert_warning("until true\n end", "mismatched indentations at 'end' with 'until'") + + assert_warning("begin\n end", "mismatched indentations at 'end' with 'begin'") + assert_warning("begin\n rescue\nend", "mismatched indentations at 'rescue' with 'begin'") + assert_warning("begin\n ensure\nend", "mismatched indentations at 'ensure' with 'begin'") + assert_warning("begin\nrescue\n else\nend", "mismatched indentations at 'else' with 'begin'", "mismatched indentations at 'end' with 'else'") + assert_warning("begin\n rescue\n ensure\n end", "mismatched indentations at 'rescue' with 'begin'", "mismatched indentations at 'ensure' with 'begin'", "mismatched indentations at 'end' with 'begin'"); + + assert_warning("def foo\n end", "mismatched indentations at 'end' with 'def'") + assert_warning("def foo\n rescue\nend", "mismatched indentations at 'rescue' with 'def'") + assert_warning("def foo\n ensure\nend", "mismatched indentations at 'ensure' with 'def'") + assert_warning("def foo\nrescue\n else\nend", "mismatched indentations at 'else' with 'def'", "mismatched indentations at 'end' with 'else'") + assert_warning("def foo\n rescue\n ensure\n end", "mismatched indentations at 'rescue' with 'def'", "mismatched indentations at 'ensure' with 'def'", "mismatched indentations at 'end' with 'def'"); + + assert_warning("class Foo\n end", "mismatched indentations at 'end' with 'class'") + assert_warning("class Foo\n rescue\nend", "mismatched indentations at 'rescue' with 'class'") + assert_warning("class Foo\n ensure\nend", "mismatched indentations at 'ensure' with 'class'") + assert_warning("class Foo\nrescue\n else\nend", "mismatched indentations at 'else' with 'class'", "mismatched indentations at 'end' with 'else'") + assert_warning("class Foo\n rescue\n ensure\n end", "mismatched indentations at 'rescue' with 'class'", "mismatched indentations at 'ensure' with 'class'", "mismatched indentations at 'end' with 'class'"); + + assert_warning("module Foo\n end", "mismatched indentations at 'end' with 'module'") + assert_warning("module Foo\n rescue\nend", "mismatched indentations at 'rescue' with 'module'") + assert_warning("module Foo\n ensure\nend", "mismatched indentations at 'ensure' with 'module'") + assert_warning("module Foo\nrescue\n else\nend", "mismatched indentations at 'else' with 'module'", "mismatched indentations at 'end' with 'else'") + assert_warning("module Foo\n rescue\n ensure\n end", "mismatched indentations at 'rescue' with 'module'", "mismatched indentations at 'ensure' with 'module'", "mismatched indentations at 'end' with 'module'"); + + assert_warning("class << foo\n end", "mismatched indentations at 'end' with 'class'") + assert_warning("class << foo\n rescue\nend", "mismatched indentations at 'rescue' with 'class'") + assert_warning("class << foo\n ensure\nend", "mismatched indentations at 'ensure' with 'class'") + assert_warning("class << foo\nrescue\n else\nend", "mismatched indentations at 'else' with 'class'", "mismatched indentations at 'end' with 'else'") + assert_warning("class << foo\n rescue\n ensure\n end", "mismatched indentations at 'rescue' with 'class'", "mismatched indentations at 'ensure' with 'class'", "mismatched indentations at 'end' with 'class'"); + + assert_warning("case 1; when 2\n end", "mismatched indentations at 'end' with 'case'") + assert_warning("case 1; in 2\n end", "mismatched indentations at 'end' with 'case'") + + assert_warning(" case 1\nwhen 2\n end", "mismatched indentations at 'when' with 'case'") + refute_warning("case 1\n when 2\n when 3\nend") # case/when allows more indentation + + assert_warning("-> {\n }", "mismatched indentations at '}' with '->'") + assert_warning("-> do\n end", "mismatched indentations at 'end' with '->'") + assert_warning("-> do\n rescue\nend", "mismatched indentations at 'rescue' with '->'") + assert_warning("-> do\n ensure\nend", "mismatched indentations at 'ensure' with '->'") + assert_warning("-> do\nrescue\n else\nend", "mismatched indentations at 'else' with '->'", "mismatched indentations at 'end' with 'else'") + assert_warning("-> do\n rescue\n ensure\n end", "mismatched indentations at 'rescue' with '->'", "mismatched indentations at 'ensure' with '->'", "mismatched indentations at 'end' with '->'"); + assert_warning("foo do\nrescue\n else\nend", "mismatched indentations at 'end' with 'else'") + + refute_warning("class Foo; end") # same line + refute_warning("; class Foo\nend") # non whitespace on opening line + refute_warning("\tclass Foo\n end") # tab stop matches space + refute_warning(" \tclass Foo\n end") # tab stop matches space + end + + def test_integer_in_flip_flop + assert_warning("1 if 2..foo", "integer") + end + + def test_literal_in_conditionals + sources = [ + "if (a = 2); a; end", + "if ($a = 2); end", + "if (@a = 2); end", + "if a; elsif b = 2; b end", + "unless (a = 2); a; end", + "unless ($a = 2); end", + "unless (@a = 2); end", + "while (a = 2); a; end", + "while ($a = 2); end", + "while (@a = 2); end", + "until (a = 2); a; end", + "until ($a = 2); end", + "until (@a = 2); end", + "foo if (a, b = 2); [a, b]", + "foo if a = 2 and a", + "(@foo = 1) ? a : b", + "!(a = 2) and a", + "not a = 2 and a" + ] + + if RUBY_VERSION >= "3.3" + sources.push( + "if (@@a = 2); end", + "unless (@@a = 2); end", + "while (@@a = 2); end", + "until (@@a = 2); end" + ) + end + + sources.each do |source| + assert_warning(source, "= literal' in conditional, should be ==") + end + end + + def test_keyword_eol + assert_warning("if\ntrue; end", "end of line") + assert_warning("if true\nelsif\nfalse; end", "end of line") + end + + def test_numbered_reference + assert_warning("_ = _ = $999999999999999999999", "too big for a number variable, always nil") + end + + def test_shareable_constant_value + assert_warning("foo # shareable_constant_value: none", "ignored") + assert_warning("\v # shareable_constant_value: none", "ignored") + + refute_warning("# shareable_constant_value: none") + refute_warning(" # shareable_constant_value: none") + refute_warning("\t\t# shareable_constant_value: none") + end + + def test_string_in_predicate + assert_warning("if 'foo'; end", "string") + assert_warning("if \"\#{foo}\"; end", "string") + assert_warning("if __FILE__; end", "string") + end + + def test_symbol_in_predicate + assert_warning("if :foo; end", "symbol") + assert_warning("if :\"\#{foo}\"; end", "symbol") + end + + def test_literal_in_predicate + assert_warning("if __LINE__; end", "literal") + assert_warning("if __ENCODING__; end", "literal") + assert_warning("if 1; end", "literal") + assert_warning("if 1.0; end", "literal") + assert_warning("if 1r; end", "literal") + assert_warning("if 1i; end", "literal") + end + + def test_regexp_in_predicate + assert_warning("if /foo/; end", "regex") + assert_warning("if /foo\#{bar}/; end", "regex") + end + + def test_unused_local_variables + assert_warning("foo = 1", "unused") + + refute_warning("foo = 1", compare: false, command_line: "e") + refute_warning("foo = 1", compare: false, scopes: [[]]) + + assert_warning("def foo; bar = 1; end", "unused") + assert_warning("def foo; bar, = 1; end", "unused") + + refute_warning("def foo; bar &&= 1; end") + refute_warning("def foo; bar ||= 1; end") + refute_warning("def foo; bar += 1; end") + + refute_warning("def foo; bar = bar; end") + refute_warning("def foo; bar = bar = 1; end") + refute_warning("def foo; bar = (bar = 1); end") + refute_warning("def foo; bar = begin; bar = 1; end; end") + refute_warning("def foo; bar = (qux; bar = 1); end") + refute_warning("def foo; bar, = bar = 1; end") + refute_warning("def foo; bar, = 1, bar = 1; end") + + refute_warning("def foo(bar); end") + refute_warning("def foo(bar = 1); end") + refute_warning("def foo((bar)); end") + refute_warning("def foo(*bar); end") + refute_warning("def foo(*, bar); end") + refute_warning("def foo(*, (bar)); end") + refute_warning("def foo(bar:); end") + refute_warning("def foo(**bar); end") + refute_warning("def foo(&bar); end") + refute_warning("->(bar) {}") + refute_warning("->(; bar) {}", compare: false) + + refute_warning("def foo; bar = 1; tap { bar }; end") + refute_warning("def foo; bar = 1; tap { baz = bar; baz }; end") + + refute_warning("def foo; bar = 1; end", line: -2, compare: false) + end + + def test_void_statements + assert_warning("foo = 1; foo", "a variable in void") + assert_warning("@foo", "a variable in void") + assert_warning("@@foo", "a variable in void") + assert_warning("$foo", "a variable in void") + assert_warning("$+", "a variable in void") + assert_warning("$1", "a variable in void") + + assert_warning("self", "self in void") + assert_warning("nil", "nil in void") + assert_warning("true", "true in void") + assert_warning("false", "false in void") + + assert_warning("1", "literal in void") + assert_warning("1.0", "literal in void") + assert_warning("1r", "literal in void") + assert_warning("1i", "literal in void") + assert_warning(":foo", "literal in void") + assert_warning("\"foo\"", "literal in void") + assert_warning("\"foo\#{1}\"", "literal in void") + assert_warning("/foo/", "literal in void") + assert_warning("/foo\#{1}/", "literal in void") + + assert_warning("Foo", "constant in void") + assert_warning("::Foo", ":: in void") + assert_warning("Foo::Bar", ":: in void") + + assert_warning("1..2", ".. in void") + assert_warning("1..", ".. in void") + assert_warning("..2", ".. in void") + assert_warning("1...2", "... in void") + assert_warning("1...;", "... in void") + assert_warning("...2", "... in void") + + assert_warning("defined?(foo)", "defined? in void") + + assert_warning("1 + 1", "+ in void") + assert_warning("1 - 1", "- in void") + assert_warning("1 * 1", "* in void") + assert_warning("1 / 1", "/ in void") + assert_warning("1 % 1", "% in void") + assert_warning("1 | 1", "| in void") + assert_warning("1 ^ 1", "^ in void") + assert_warning("1 & 1", "& in void") + assert_warning("1 > 1", "> in void") + assert_warning("1 < 1", "< in void") + + assert_warning("1 ** 1", "** in void") + assert_warning("1 <= 1", "<= in void") + assert_warning("1 >= 1", ">= in void") + assert_warning("1 != 1", "!= in void") + assert_warning("1 == 1", "== in void") + assert_warning("1 <=> 1", "<=> in void") + + assert_warning("+foo", "+@ in void") + assert_warning("-foo", "-@ in void") + + assert_warning("def foo; @bar; @baz; end", "variable in void") + refute_warning("def foo; @bar; end") + refute_warning("@foo", compare: false, scopes: [[]]) + end + + def test_unreachable_statement + assert_warning("begin; rescue; retry; foo; end", "statement not reached") + + assert_warning("return; foo", "statement not reached") + + assert_warning("tap { break; foo }", "statement not reached") + assert_warning("tap { break 1; foo }", "statement not reached") + + assert_warning("tap { next; foo }", "statement not reached") + assert_warning("tap { next 1; foo }", "statement not reached") + + assert_warning("tap { redo; foo }", "statement not reached") + end + + if RbConfig::CONFIG["host_os"].match?(/bccwin|cygwin|djgpp|mingw|mswin|wince/i) + def test_shebang_ending_with_carriage_return + refute_warning("#!ruby\r\np(123)\n", compare: false) + end + else + def test_shebang_ending_with_carriage_return + msg = "shebang line ending with \\r may cause problems" + + assert_warning(<<~RUBY, msg, compare: false, main_script: true) + #!ruby\r + p(123) + RUBY + + assert_warning(<<~RUBY, msg, compare: false, main_script: true) + #!ruby \r + p(123) + RUBY + + assert_warning(<<~RUBY, msg, compare: false, main_script: true) + #!ruby -Eutf-8\r + p(123) + RUBY + + # Used with the `-x` object, to ignore the script up until the first + # shebang that mentioned "ruby". + assert_warning(<<~SCRIPT, msg, compare: false, main_script: true) + #!/usr/bin/env bash + # Some initial shell script or other content + # that Ruby should ignore + echo "This is shell script part" + exit 0 + + #! /usr/bin/env ruby -Eutf-8\r + # Ruby script starts here + puts "Hello from Ruby!" + SCRIPT + + refute_warning("#ruby not_a_shebang\r\n", compare: false, main_script: true) + + # CRuby doesn't emit the warning if a malformed file only has `\r` and + # not `\n`. https://bugs.ruby-lang.org/issues/20700. + refute_warning("#!ruby\r", compare: false, main_script: true) + end + end + + def test_warnings_verbosity + warning = Prism.parse("def foo; END { }; end").warnings.first + assert_equal "END in method; use at_exit", warning.message + assert_equal :default, warning.level + + warning = Prism.parse("foo /regexp/").warnings.first + assert_equal "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", warning.message + assert_equal :verbose, warning.level + end + + private + + def assert_warning(source, *messages, compare: true, **options) + warnings = Prism.parse(source, **options).warnings + assert_equal messages.length, warnings.length, "Expected #{messages.length} warning(s) in #{source.inspect}, got #{warnings.map(&:message).inspect}" + + warnings.zip(messages).each do |warning, message| + assert_include warning.message, message + end + + if compare && defined?(RubyVM::AbstractSyntaxTree) + stderr = capture_stderr { RubyVM::AbstractSyntaxTree.parse(source) } + messages.each { |message| assert_include stderr, message } + end + end + + def refute_warning(source, compare: true, **options) + assert_empty Prism.parse(source, **options).warnings + + if compare && defined?(RubyVM::AbstractSyntaxTree) + assert_empty capture_stderr { RubyVM::AbstractSyntaxTree.parse(source) } + end + end + + def capture_stderr + stderr, $stderr, verbose, $VERBOSE = $stderr, StringIO.new, $VERBOSE, true + + begin + yield + $stderr.string + ensure + $stderr, $VERBOSE = stderr, verbose + end + end + end +end diff --git a/test/prism/compiler_test.rb b/test/prism/ruby/compiler_test.rb similarity index 94% rename from test/prism/compiler_test.rb rename to test/prism/ruby/compiler_test.rb index 9a326eb8d61..35ccfd59507 100644 --- a/test/prism/compiler_test.rb +++ b/test/prism/ruby/compiler_test.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # typed: ignore -require_relative "test_helper" +require_relative "../test_helper" module Prism class CompilerTest < TestCase diff --git a/test/prism/desugar_compiler_test.rb b/test/prism/ruby/desugar_compiler_test.rb similarity index 99% rename from test/prism/desugar_compiler_test.rb rename to test/prism/ruby/desugar_compiler_test.rb index 1a1d580d2dc..fe9a25e030c 100644 --- a/test/prism/desugar_compiler_test.rb +++ b/test/prism/ruby/desugar_compiler_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "test_helper" +require_relative "../test_helper" module Prism class DesugarCompilerTest < TestCase diff --git a/test/prism/dispatcher_test.rb b/test/prism/ruby/dispatcher_test.rb similarity index 97% rename from test/prism/dispatcher_test.rb rename to test/prism/ruby/dispatcher_test.rb index 0d8a6d35e90..1b6d7f4117e 100644 --- a/test/prism/dispatcher_test.rb +++ b/test/prism/ruby/dispatcher_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "test_helper" +require_relative "../test_helper" module Prism class DispatcherTest < TestCase diff --git a/test/prism/ruby/location_test.rb b/test/prism/ruby/location_test.rb new file mode 100644 index 00000000000..33f844243c0 --- /dev/null +++ b/test/prism/ruby/location_test.rb @@ -0,0 +1,251 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class LocationTest < TestCase + def test_join + call = Prism.parse_statement("1234 + 567") + receiver = call.receiver + argument = call.arguments.arguments.first + + joined = receiver.location.join(argument.location) + assert_equal 0, joined.start_offset + assert_equal 10, joined.length + + assert_raise(RuntimeError, "Incompatible locations") do + argument.location.join(receiver.location) + end + + other_argument = Prism.parse_statement("1234 + 567").arguments.arguments.first + + assert_raise(RuntimeError, "Incompatible sources") do + other_argument.location.join(receiver.location) + end + + assert_raise(RuntimeError, "Incompatible sources") do + receiver.location.join(other_argument.location) + end + end + + def test_character_offsets + program = Prism.parse("😀 + 😀\n😍 ||= 😍").value + + # first 😀 + location = program.statements.body.first.receiver.location + assert_equal 0, location.start_character_offset + assert_equal 1, location.end_character_offset + assert_equal 0, location.start_character_column + assert_equal 1, location.end_character_column + + # second 😀 + location = program.statements.body.first.arguments.arguments.first.location + assert_equal 4, location.start_character_offset + assert_equal 5, location.end_character_offset + assert_equal 4, location.start_character_column + assert_equal 5, location.end_character_column + + # first 😍 + location = program.statements.body.last.name_loc + assert_equal 6, location.start_character_offset + assert_equal 7, location.end_character_offset + assert_equal 0, location.start_character_column + assert_equal 1, location.end_character_column + + # second 😍 + location = program.statements.body.last.value.location + assert_equal 12, location.start_character_offset + assert_equal 13, location.end_character_offset + assert_equal 6, location.start_character_column + assert_equal 7, location.end_character_column + end + + def test_code_units + program = Prism.parse("😀 + 😀\n😍 ||= 😍").value + + # first 😀 + location = program.statements.body.first.receiver.location + + assert_equal 0, location.start_code_units_offset(Encoding::UTF_8) + assert_equal 0, location.start_code_units_offset(Encoding::UTF_16LE) + assert_equal 0, location.start_code_units_offset(Encoding::UTF_32LE) + + assert_equal 1, location.end_code_units_offset(Encoding::UTF_8) + assert_equal 2, location.end_code_units_offset(Encoding::UTF_16LE) + assert_equal 1, location.end_code_units_offset(Encoding::UTF_32LE) + + assert_equal 0, location.start_code_units_column(Encoding::UTF_8) + assert_equal 0, location.start_code_units_column(Encoding::UTF_16LE) + assert_equal 0, location.start_code_units_column(Encoding::UTF_32LE) + + assert_equal 1, location.end_code_units_column(Encoding::UTF_8) + assert_equal 2, location.end_code_units_column(Encoding::UTF_16LE) + assert_equal 1, location.end_code_units_column(Encoding::UTF_32LE) + + # second 😀 + location = program.statements.body.first.arguments.arguments.first.location + + assert_equal 4, location.start_code_units_offset(Encoding::UTF_8) + assert_equal 5, location.start_code_units_offset(Encoding::UTF_16LE) + assert_equal 4, location.start_code_units_offset(Encoding::UTF_32LE) + + assert_equal 5, location.end_code_units_offset(Encoding::UTF_8) + assert_equal 7, location.end_code_units_offset(Encoding::UTF_16LE) + assert_equal 5, location.end_code_units_offset(Encoding::UTF_32LE) + + assert_equal 4, location.start_code_units_column(Encoding::UTF_8) + assert_equal 5, location.start_code_units_column(Encoding::UTF_16LE) + assert_equal 4, location.start_code_units_column(Encoding::UTF_32LE) + + assert_equal 5, location.end_code_units_column(Encoding::UTF_8) + assert_equal 7, location.end_code_units_column(Encoding::UTF_16LE) + assert_equal 5, location.end_code_units_column(Encoding::UTF_32LE) + + # first 😍 + location = program.statements.body.last.name_loc + + assert_equal 6, location.start_code_units_offset(Encoding::UTF_8) + assert_equal 8, location.start_code_units_offset(Encoding::UTF_16LE) + assert_equal 6, location.start_code_units_offset(Encoding::UTF_32LE) + + assert_equal 7, location.end_code_units_offset(Encoding::UTF_8) + assert_equal 10, location.end_code_units_offset(Encoding::UTF_16LE) + assert_equal 7, location.end_code_units_offset(Encoding::UTF_32LE) + + assert_equal 0, location.start_code_units_column(Encoding::UTF_8) + assert_equal 0, location.start_code_units_column(Encoding::UTF_16LE) + assert_equal 0, location.start_code_units_column(Encoding::UTF_32LE) + + assert_equal 1, location.end_code_units_column(Encoding::UTF_8) + assert_equal 2, location.end_code_units_column(Encoding::UTF_16LE) + assert_equal 1, location.end_code_units_column(Encoding::UTF_32LE) + + # second 😍 + location = program.statements.body.last.value.location + + assert_equal 12, location.start_code_units_offset(Encoding::UTF_8) + assert_equal 15, location.start_code_units_offset(Encoding::UTF_16LE) + assert_equal 12, location.start_code_units_offset(Encoding::UTF_32LE) + + assert_equal 13, location.end_code_units_offset(Encoding::UTF_8) + assert_equal 17, location.end_code_units_offset(Encoding::UTF_16LE) + assert_equal 13, location.end_code_units_offset(Encoding::UTF_32LE) + + assert_equal 6, location.start_code_units_column(Encoding::UTF_8) + assert_equal 7, location.start_code_units_column(Encoding::UTF_16LE) + assert_equal 6, location.start_code_units_column(Encoding::UTF_32LE) + + assert_equal 7, location.end_code_units_column(Encoding::UTF_8) + assert_equal 9, location.end_code_units_column(Encoding::UTF_16LE) + assert_equal 7, location.end_code_units_column(Encoding::UTF_32LE) + end + + def test_cached_code_units + result = Prism.parse("😀 + 😀\n😍 ||= 😍") + + utf8_cache = result.code_units_cache(Encoding::UTF_8) + utf16_cache = result.code_units_cache(Encoding::UTF_16LE) + utf32_cache = result.code_units_cache(Encoding::UTF_32LE) + + # first 😀 + location = result.value.statements.body.first.receiver.location + + assert_equal 0, location.cached_start_code_units_offset(utf8_cache) + assert_equal 0, location.cached_start_code_units_offset(utf16_cache) + assert_equal 0, location.cached_start_code_units_offset(utf32_cache) + + assert_equal 1, location.cached_end_code_units_offset(utf8_cache) + assert_equal 2, location.cached_end_code_units_offset(utf16_cache) + assert_equal 1, location.cached_end_code_units_offset(utf32_cache) + + assert_equal 0, location.cached_start_code_units_column(utf8_cache) + assert_equal 0, location.cached_start_code_units_column(utf16_cache) + assert_equal 0, location.cached_start_code_units_column(utf32_cache) + + assert_equal 1, location.cached_end_code_units_column(utf8_cache) + assert_equal 2, location.cached_end_code_units_column(utf16_cache) + assert_equal 1, location.cached_end_code_units_column(utf32_cache) + + # second 😀 + location = result.value.statements.body.first.arguments.arguments.first.location + + assert_equal 4, location.cached_start_code_units_offset(utf8_cache) + assert_equal 5, location.cached_start_code_units_offset(utf16_cache) + assert_equal 4, location.cached_start_code_units_offset(utf32_cache) + + assert_equal 5, location.cached_end_code_units_offset(utf8_cache) + assert_equal 7, location.cached_end_code_units_offset(utf16_cache) + assert_equal 5, location.cached_end_code_units_offset(utf32_cache) + + assert_equal 4, location.cached_start_code_units_column(utf8_cache) + assert_equal 5, location.cached_start_code_units_column(utf16_cache) + assert_equal 4, location.cached_start_code_units_column(utf32_cache) + + assert_equal 5, location.cached_end_code_units_column(utf8_cache) + assert_equal 7, location.cached_end_code_units_column(utf16_cache) + assert_equal 5, location.cached_end_code_units_column(utf32_cache) + end + + def test_code_units_binary_valid_utf8 + program = Prism.parse(<<~RUBY).value + # -*- encoding: binary -*- + + 😀 + 😀 + RUBY + + receiver = program.statements.body.first.receiver + assert_equal "😀".b.to_sym, receiver.name + + location = receiver.location + assert_equal 1, location.end_code_units_column(Encoding::UTF_8) + assert_equal 2, location.end_code_units_column(Encoding::UTF_16LE) + assert_equal 1, location.end_code_units_column(Encoding::UTF_32LE) + end + + def test_code_units_binary_invalid_utf8 + program = Prism.parse(<<~RUBY).value + # -*- encoding: binary -*- + + \x90 + \x90 + RUBY + + receiver = program.statements.body.first.receiver + assert_equal "\x90".b.to_sym, receiver.name + + location = receiver.location + assert_equal 1, location.end_code_units_column(Encoding::UTF_8) + assert_equal 1, location.end_code_units_column(Encoding::UTF_16LE) + assert_equal 1, location.end_code_units_column(Encoding::UTF_32LE) + end + + def test_chop + location = Prism.parse("foo").value.location + + assert_equal "fo", location.chop.slice + assert_equal "", location.chop.chop.chop.slice + + # Check that we don't go negative. + 10.times { location = location.chop } + assert_equal "", location.slice + end + + def test_slice_lines + method = Prism.parse_statement("\nprivate def foo\nend\n").arguments.arguments.first + + assert_equal "private def foo\nend\n", method.slice_lines + end + + def test_adjoin + program = Prism.parse("foo.bar = 1").value + + location = program.statements.body.first.message_loc + adjoined = location.adjoin("=") + + assert_kind_of Location, adjoined + refute_equal location, adjoined + + assert_equal 4, adjoined.start_offset + assert_equal 9, adjoined.end_offset + end + end +end diff --git a/test/prism/parameters_signature_test.rb b/test/prism/ruby/parameters_signature_test.rb similarity index 85% rename from test/prism/parameters_signature_test.rb rename to test/prism/ruby/parameters_signature_test.rb index 0eed8d993d5..9256bcc0703 100644 --- a/test/prism/parameters_signature_test.rb +++ b/test/prism/ruby/parameters_signature_test.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true -require_relative "test_helper" - return if RUBY_VERSION < "3.2" +require_relative "../test_helper" + module Prism class ParametersSignatureTest < TestCase def test_req @@ -56,7 +56,6 @@ def test_keyrest_anonymous def test_key_ordering omit("TruffleRuby returns keys in order they were declared") if RUBY_ENGINE == "truffleruby" - assert_parameters([[:keyreq, :a], [:keyreq, :b], [:key, :c], [:key, :d]], "a:, c: 1, b:, d: 2") end @@ -75,14 +74,13 @@ def test_forwarding private def assert_parameters(expected, source) - eval("def self.m(#{source}); end") - - begin - assert_equal(expected, method(:m).parameters) - assert_equal(expected, signature(source)) - ensure - singleton_class.undef_method(:m) - end + # Compare against our expectation. + assert_equal(expected, signature(source)) + + # Compare against Ruby's expectation. + object = Object.new + eval("def object.m(#{source}); end") + assert_equal(expected, object.method(:m).parameters) end def signature(source) diff --git a/test/prism/ruby/parser_test.rb b/test/prism/ruby/parser_test.rb new file mode 100644 index 00000000000..606a0e54f64 --- /dev/null +++ b/test/prism/ruby/parser_test.rb @@ -0,0 +1,291 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +begin + verbose, $VERBOSE = $VERBOSE, nil + require "parser/ruby33" + require "prism/translation/parser33" +rescue LoadError + # In CRuby's CI, we're not going to test against the parser gem because we + # don't want to have to install it. So in this case we'll just skip this test. + return +ensure + $VERBOSE = verbose +end + +# First, opt in to every AST feature. +Parser::Builders::Default.modernize + +# Modify the source map == check so that it doesn't check against the node +# itself so we don't get into a recursive loop. +Parser::Source::Map.prepend( + Module.new { + def ==(other) + self.class == other.class && + (instance_variables - %i[@node]).map do |ivar| + instance_variable_get(ivar) == other.instance_variable_get(ivar) + end.reduce(:&) + end + } +) + +# Next, ensure that we're comparing the nodes and also comparing the source +# ranges so that we're getting all of the necessary information. +Parser::AST::Node.prepend( + Module.new { + def ==(other) + super && (location == other.location) + end + } +) + +module Prism + class ParserTest < TestCase + # These files contain code that is being parsed incorrectly by the parser + # gem, and therefore we don't want to compare against our translation. + skip_incorrect = [ + # https://github.com/whitequark/parser/issues/1017 + "spanning_heredoc.txt", + "spanning_heredoc_newlines.txt", + + # https://github.com/whitequark/parser/issues/1021 + "seattlerb/heredoc_nested.txt", + + # https://github.com/whitequark/parser/issues/1016 + "whitequark/unary_num_pow_precedence.txt" + ] + + # These files are either failing to parse or failing to translate, so we'll + # skip them for now. + skip_all = skip_incorrect | [ + "regex.txt", + "unescaping.txt", + "seattlerb/bug190.txt", + "seattlerb/heredoc_with_extra_carriage_returns_windows.txt", + "seattlerb/heredoc_with_only_carriage_returns_windows.txt", + "seattlerb/heredoc_with_only_carriage_returns.txt", + "seattlerb/parse_line_heredoc_hardnewline.txt", + "seattlerb/pctW_lineno.txt", + "seattlerb/regexp_esc_C_slash.txt", + "unparser/corpus/literal/literal.txt", + "unparser/corpus/semantic/dstr.txt", + "whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt", + "whitequark/parser_slash_slash_n_escaping_in_literals.txt", + "whitequark/ruby_bug_11989.txt" + ] + + # Not sure why these files are failing on JRuby, but skipping them for now. + if RUBY_ENGINE == "jruby" + skip_all.push("emoji_method_calls.txt", "symbols.txt") + end + + # These files are failing to translate their lexer output into the lexer + # output expected by the parser gem, so we'll skip them for now. + skip_tokens = [ + "comments.txt", + "dash_heredocs.txt", + "dos_endings.txt", + "embdoc_no_newline_at_end.txt", + "heredoc_with_comment.txt", + "heredocs_with_ignored_newlines.txt", + "indented_file_end.txt", + "methods.txt", + "strings.txt", + "tilde_heredocs.txt", + "xstring_with_backslash.txt", + "seattlerb/backticks_interpolation_line.txt", + "seattlerb/bug169.txt", + "seattlerb/case_in.txt", + "seattlerb/class_comments.txt", + "seattlerb/difficult4__leading_dots2.txt", + "seattlerb/difficult6__7.txt", + "seattlerb/difficult6__8.txt", + "seattlerb/dsym_esc_to_sym.txt", + "seattlerb/heredoc__backslash_dos_format.txt", + "seattlerb/heredoc_backslash_nl.txt", + "seattlerb/heredoc_comma_arg.txt", + "seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt", + "seattlerb/heredoc_squiggly_blank_lines.txt", + "seattlerb/heredoc_squiggly_interp.txt", + "seattlerb/heredoc_squiggly_tabs_extra.txt", + "seattlerb/heredoc_squiggly_tabs.txt", + "seattlerb/heredoc_squiggly_visually_blank_lines.txt", + "seattlerb/heredoc_squiggly.txt", + "seattlerb/heredoc_unicode.txt", + "seattlerb/heredoc_with_carriage_return_escapes_windows.txt", + "seattlerb/heredoc_with_carriage_return_escapes.txt", + "seattlerb/heredoc_with_interpolation_and_carriage_return_escapes_windows.txt", + "seattlerb/heredoc_with_interpolation_and_carriage_return_escapes.txt", + "seattlerb/interpolated_symbol_array_line_breaks.txt", + "seattlerb/interpolated_word_array_line_breaks.txt", + "seattlerb/label_vs_string.txt", + "seattlerb/module_comments.txt", + "seattlerb/non_interpolated_symbol_array_line_breaks.txt", + "seattlerb/non_interpolated_word_array_line_breaks.txt", + "seattlerb/parse_line_block_inline_comment_leading_newlines.txt", + "seattlerb/parse_line_block_inline_comment.txt", + "seattlerb/parse_line_block_inline_multiline_comment.txt", + "seattlerb/parse_line_dstr_escaped_newline.txt", + "seattlerb/parse_line_heredoc.txt", + "seattlerb/parse_line_multiline_str_literal_n.txt", + "seattlerb/parse_line_str_with_newline_escape.txt", + "seattlerb/pct_w_heredoc_interp_nested.txt", + "seattlerb/qsymbols_empty_space.txt", + "seattlerb/qw_escape_term.txt", + "seattlerb/qWords_space.txt", + "seattlerb/read_escape_unicode_curlies.txt", + "seattlerb/read_escape_unicode_h4.txt", + "seattlerb/required_kwarg_no_value.txt", + "seattlerb/slashy_newlines_within_string.txt", + "seattlerb/str_double_escaped_newline.txt", + "seattlerb/str_double_newline.txt", + "seattlerb/str_evstr_escape.txt", + "seattlerb/str_newline_hash_line_number.txt", + "seattlerb/str_single_newline.txt", + "seattlerb/symbols_empty_space.txt", + "seattlerb/TestRubyParserShared.txt", + "unparser/corpus/literal/assignment.txt", + "unparser/corpus/literal/dstr.txt", + "unparser/corpus/semantic/opasgn.txt", + "whitequark/args.txt", + "whitequark/beginless_erange_after_newline.txt", + "whitequark/beginless_irange_after_newline.txt", + "whitequark/bug_ascii_8bit_in_literal.txt", + "whitequark/bug_def_no_paren_eql_begin.txt", + "whitequark/dedenting_heredoc.txt", + "whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt", + "whitequark/forward_arg_with_open_args.txt", + "whitequark/interp_digit_var.txt", + "whitequark/lbrace_arg_after_command_args.txt", + "whitequark/multiple_pattern_matches.txt", + "whitequark/newline_in_hash_argument.txt", + "whitequark/parser_bug_640.txt", + "whitequark/parser_drops_truncated_parts_of_squiggly_heredoc.txt", + "whitequark/ruby_bug_11990.txt", + "whitequark/ruby_bug_14690.txt", + "whitequark/ruby_bug_9669.txt", + "whitequark/slash_newline_in_heredocs.txt", + "whitequark/space_args_arg_block.txt", + "whitequark/space_args_block.txt" + ] + + Fixture.each do |fixture| + define_method(fixture.test_name) do + assert_equal_parses( + fixture, + compare_asts: !skip_all.include?(fixture.path), + compare_tokens: !skip_tokens.include?(fixture.path), + compare_comments: fixture.path != "embdoc_no_newline_at_end.txt" + ) + end + end + + private + + def assert_equal_parses(fixture, compare_asts: true, compare_tokens: true, compare_comments: true) + buffer = Parser::Source::Buffer.new(fixture.path, 1) + buffer.source = fixture.read + + parser = Parser::Ruby33.new + parser.diagnostics.consumer = ->(*) {} + parser.diagnostics.all_errors_are_fatal = true + + expected_ast, expected_comments, expected_tokens = + begin + ignore_warnings { parser.tokenize(buffer) } + rescue ArgumentError, Parser::SyntaxError + return + end + + actual_ast, actual_comments, actual_tokens = + ignore_warnings { Prism::Translation::Parser33.new.tokenize(buffer) } + + if expected_ast == actual_ast + if !compare_asts + puts "#{fixture.path} is now passing" + end + + assert_equal expected_ast, actual_ast, -> { assert_equal_asts_message(expected_ast, actual_ast) } + + begin + assert_equal_tokens(expected_tokens, actual_tokens) + rescue Test::Unit::AssertionFailedError + raise if compare_tokens + else + puts "#{fixture.path} is now passing" if !compare_tokens + end + + assert_equal_comments(expected_comments, actual_comments) if compare_comments + elsif compare_asts + assert_equal expected_ast, actual_ast, -> { assert_equal_asts_message(expected_ast, actual_ast) } + end + end + + def assert_equal_asts_message(expected_ast, actual_ast) + queue = [[expected_ast, actual_ast]] + + while (left, right = queue.shift) + if left.type != right.type + return "expected: #{left.type}\nactual: #{right.type}" + end + + if left.location != right.location + return "expected:\n#{left.inspect}\n#{left.location.inspect}\nactual:\n#{right.inspect}\n#{right.location.inspect}" + end + + if left.type == :str && left.children[0] != right.children[0] + return "expected: #{left.inspect}\nactual: #{right.inspect}" + end + + left.children.zip(right.children).each do |left_child, right_child| + queue << [left_child, right_child] if left_child.is_a?(Parser::AST::Node) + end + end + + "expected: #{expected_ast.inspect}\nactual: #{actual_ast.inspect}" + end + + def assert_equal_tokens(expected_tokens, actual_tokens) + if expected_tokens != actual_tokens + expected_index = 0 + actual_index = 0 + + while expected_index < expected_tokens.length + expected_token = expected_tokens[expected_index] + actual_token = actual_tokens.fetch(actual_index, []) + + expected_index += 1 + actual_index += 1 + + # The parser gem always has a space before a string end in list + # literals, but we don't. So we'll skip over the space. + if expected_token[0] == :tSPACE && actual_token[0] == :tSTRING_END + expected_index += 1 + next + end + + # There are a lot of tokens that have very specific meaning according + # to the context of the parser. We don't expose that information in + # prism, so we need to normalize these tokens a bit. + if expected_token[0] == :kDO_BLOCK && actual_token[0] == :kDO + actual_token[0] = expected_token[0] + end + + # Now we can assert that the tokens are actually equal. + assert_equal expected_token, actual_token, -> { + "expected: #{expected_token.inspect}\n" \ + "actual: #{actual_token.inspect}" + } + end + end + end + + def assert_equal_comments(expected_comments, actual_comments) + assert_equal expected_comments, actual_comments, -> { + "expected: #{expected_comments.inspect}\n" \ + "actual: #{actual_comments.inspect}" + } + end + end +end diff --git a/test/prism/pattern_test.rb b/test/prism/ruby/pattern_test.rb similarity index 98% rename from test/prism/pattern_test.rb rename to test/prism/ruby/pattern_test.rb index e0aa079cb9c..23f512fc1c0 100644 --- a/test/prism/pattern_test.rb +++ b/test/prism/ruby/pattern_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "test_helper" +require_relative "../test_helper" module Prism class PatternTest < TestCase diff --git a/test/prism/reflection_test.rb b/test/prism/ruby/reflection_test.rb similarity index 93% rename from test/prism/reflection_test.rb rename to test/prism/ruby/reflection_test.rb index 869b68b1f8f..3ac462e1ac8 100644 --- a/test/prism/reflection_test.rb +++ b/test/prism/ruby/reflection_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "test_helper" +require_relative "../test_helper" module Prism class ReflectionTest < TestCase diff --git a/test/prism/ripper_test.rb b/test/prism/ruby/ripper_test.rb similarity index 66% rename from test/prism/ripper_test.rb rename to test/prism/ruby/ripper_test.rb index 07238fc3d54..8db47da3d35 100644 --- a/test/prism/ripper_test.rb +++ b/test/prism/ruby/ripper_test.rb @@ -2,13 +2,11 @@ return if RUBY_VERSION < "3.3" -require_relative "test_helper" +require_relative "../test_helper" module Prism class RipperTest < TestCase - base = File.join(__dir__, "fixtures") - relatives = ENV["FOCUS"] ? [ENV["FOCUS"]] : Dir["**/*.txt", base: base] - + # Skip these tests that Ripper is reporting the wrong results for. incorrect = [ # Ripper incorrectly attributes the block to the keyword. "seattlerb/block_break.txt", @@ -31,6 +29,7 @@ class RipperTest < TestCase "spanning_heredoc.txt" ] + # Skip these tests that we haven't implemented yet. omitted = [ "dos_endings.txt", "heredocs_with_ignored_newlines.txt", @@ -50,30 +49,8 @@ class RipperTest < TestCase "whitequark/slash_newline_in_heredocs.txt" ] - relatives.each do |relative| - # Skip the tests that Ripper is reporting the wrong results for. - next if incorrect.include?(relative) - - # Skip the tests we haven't implemented yet. - next if omitted.include?(relative) - - filepath = File.join(__dir__, "fixtures", relative) - - define_method "test_ripper_#{relative}" do - source = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8) - - case relative - when /break|next|redo|if|unless|rescue|control|keywords|retry/ - source = "-> do\nrescue\n#{source}\nend" - end - - case source - when /^ *yield/ - source = "def __invalid_yield__\n#{source}\nend" - end - - assert_ripper(source) - end + Fixture.each(except: incorrect | omitted) do |fixture| + define_method(fixture.test_name) { assert_ripper(fixture.read) } end private diff --git a/test/prism/ruby/ruby_parser_test.rb b/test/prism/ruby/ruby_parser_test.rb new file mode 100644 index 00000000000..a13daeeb849 --- /dev/null +++ b/test/prism/ruby/ruby_parser_test.rb @@ -0,0 +1,127 @@ +# frozen_string_literal: true + +return if RUBY_ENGINE == "jruby" + +require_relative "../test_helper" + +begin + require "ruby_parser" +rescue LoadError + # In CRuby's CI, we're not going to test against the ruby_parser gem because + # we don't want to have to install it. So in this case we'll just skip this + # test. + return +end + +# We want to also compare lines and files to make sure we're setting them +# correctly. +Sexp.prepend( + Module.new do + def ==(other) + super && line == other.line && file == other.file # && line_max == other.line_max + end + end +) + +module Prism + class RubyParserTest < TestCase + todos = [ + "newline_terminated.txt", + "regex_char_width.txt", + "seattlerb/bug169.txt", + "seattlerb/masgn_colon3.txt", + "seattlerb/messy_op_asgn_lineno.txt", + "seattlerb/op_asgn_primary_colon_const_command_call.txt", + "seattlerb/regexp_esc_C_slash.txt", + "seattlerb/str_lit_concat_bad_encodings.txt", + "unescaping.txt", + "unparser/corpus/literal/kwbegin.txt", + "unparser/corpus/literal/send.txt", + "whitequark/masgn_const.txt", + "whitequark/ruby_bug_12402.txt", + "whitequark/ruby_bug_14690.txt", + "whitequark/space_args_block.txt" + ] + + # https://github.com/seattlerb/ruby_parser/issues/344 + failures = [ + "alias.txt", + "dos_endings.txt", + "heredocs_with_ignored_newlines.txt", + "method_calls.txt", + "methods.txt", + "multi_write.txt", + "not.txt", + "patterns.txt", + "regex.txt", + "seattlerb/and_multi.txt", + "seattlerb/heredoc__backslash_dos_format.txt", + "seattlerb/heredoc_bad_hex_escape.txt", + "seattlerb/heredoc_bad_oct_escape.txt", + "seattlerb/heredoc_with_extra_carriage_horrible_mix.txt", + "seattlerb/heredoc_with_extra_carriage_returns_windows.txt", + "seattlerb/heredoc_with_only_carriage_returns_windows.txt", + "seattlerb/heredoc_with_only_carriage_returns.txt", + "spanning_heredoc_newlines.txt", + "spanning_heredoc.txt", + "tilde_heredocs.txt", + "unparser/corpus/literal/literal.txt", + "while.txt", + "whitequark/cond_eflipflop.txt", + "whitequark/cond_iflipflop.txt", + "whitequark/cond_match_current_line.txt", + "whitequark/dedenting_heredoc.txt", + "whitequark/lvar_injecting_match.txt", + "whitequark/not.txt", + "whitequark/numparam_ruby_bug_19025.txt", + "whitequark/op_asgn_cmd.txt", + "whitequark/parser_bug_640.txt", + "whitequark/parser_slash_slash_n_escaping_in_literals.txt", + "whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt", + "whitequark/pattern_matching_single_line.txt", + "whitequark/ruby_bug_11989.txt", + "whitequark/slash_newline_in_heredocs.txt" + ] + + Fixture.each(except: failures) do |fixture| + define_method(fixture.test_name) do + assert_ruby_parser(fixture, todos.include?(fixture.path)) + end + end + + private + + def assert_ruby_parser(fixture, allowed_failure) + source = fixture.read + expected = ignore_warnings { ::RubyParser.new.parse(source, fixture.path) } + actual = Prism::Translation::RubyParser.new.parse(source, fixture.path) + + if !allowed_failure + assert_equal(expected, actual, -> { message(expected, actual) }) + elsif expected == actual + puts "#{name} now passes" + end + end + + def message(expected, actual) + if expected == actual + nil + elsif expected.is_a?(Sexp) && actual.is_a?(Sexp) + if expected.line != actual.line + "expected: (#{expected.inspect} line=#{expected.line}), actual: (#{actual.inspect} line=#{actual.line})" + elsif expected.file != actual.file + "expected: (#{expected.inspect} file=#{expected.file}), actual: (#{actual.inspect} file=#{actual.file})" + elsif expected.length != actual.length + "expected: (#{expected.inspect} length=#{expected.length}), actual: (#{actual.inspect} length=#{actual.length})" + else + expected.zip(actual).find do |expected_field, actual_field| + result = message(expected_field, actual_field) + break result if result + end + end + else + "expected: #{expected.inspect}, actual: #{actual.inspect}" + end + end + end +end diff --git a/test/prism/ruby/string_query_test.rb b/test/prism/ruby/string_query_test.rb new file mode 100644 index 00000000000..aa50c10ff32 --- /dev/null +++ b/test/prism/ruby/string_query_test.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class StringQueryTest < TestCase + def test_local? + assert_predicate StringQuery.new("a"), :local? + assert_predicate StringQuery.new("a1"), :local? + assert_predicate StringQuery.new("self"), :local? + + assert_predicate StringQuery.new("_a"), :local? + assert_predicate StringQuery.new("_1"), :local? + + assert_predicate StringQuery.new("😀"), :local? + assert_predicate StringQuery.new("ア".encode("Windows-31J")), :local? + + refute_predicate StringQuery.new("1"), :local? + refute_predicate StringQuery.new("A"), :local? + end + + def test_constant? + assert_predicate StringQuery.new("A"), :constant? + assert_predicate StringQuery.new("A1"), :constant? + assert_predicate StringQuery.new("A_B"), :constant? + assert_predicate StringQuery.new("BEGIN"), :constant? + + assert_predicate StringQuery.new("À"), :constant? + assert_predicate StringQuery.new("A".encode("US-ASCII")), :constant? + + refute_predicate StringQuery.new("a"), :constant? + refute_predicate StringQuery.new("1"), :constant? + end + + def test_method_name? + assert_predicate StringQuery.new("a"), :method_name? + assert_predicate StringQuery.new("A"), :method_name? + assert_predicate StringQuery.new("__FILE__"), :method_name? + + assert_predicate StringQuery.new("a?"), :method_name? + assert_predicate StringQuery.new("a!"), :method_name? + assert_predicate StringQuery.new("a="), :method_name? + + assert_predicate StringQuery.new("+"), :method_name? + assert_predicate StringQuery.new("<<"), :method_name? + assert_predicate StringQuery.new("==="), :method_name? + + assert_predicate StringQuery.new("_0"), :method_name? + + refute_predicate StringQuery.new("1"), :method_name? + refute_predicate StringQuery.new("_1"), :method_name? + end + + def test_invalid_encoding + assert_raise ArgumentError do + StringQuery.new("A".encode("UTF-16LE")).local? + end + end + end +end diff --git a/test/prism/ruby/tunnel_test.rb b/test/prism/ruby/tunnel_test.rb new file mode 100644 index 00000000000..0214681604a --- /dev/null +++ b/test/prism/ruby/tunnel_test.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class TunnelTest < TestCase + def test_tunnel + program = Prism.parse("foo(1) +\n bar(2, 3) +\n baz(3, 4, 5)").value + + tunnel = program.tunnel(1, 4).last + assert_kind_of IntegerNode, tunnel + assert_equal 1, tunnel.value + + tunnel = program.tunnel(2, 6).last + assert_kind_of IntegerNode, tunnel + assert_equal 2, tunnel.value + + tunnel = program.tunnel(3, 9).last + assert_kind_of IntegerNode, tunnel + assert_equal 4, tunnel.value + + tunnel = program.tunnel(3, 8) + assert_equal [ProgramNode, StatementsNode, CallNode, ArgumentsNode, CallNode, ArgumentsNode], tunnel.map(&:class) + end + end +end diff --git a/test/prism/ruby_api_test.rb b/test/prism/ruby_api_test.rb deleted file mode 100644 index a1e2592d3d4..00000000000 --- a/test/prism/ruby_api_test.rb +++ /dev/null @@ -1,307 +0,0 @@ -# frozen_string_literal: true - -require_relative "test_helper" - -module Prism - class RubyAPITest < TestCase - if !ENV["PRISM_BUILD_MINIMAL"] - def test_ruby_api - filepath = __FILE__ - source = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8) - - assert_equal Prism.lex(source, filepath: filepath).value, Prism.lex_file(filepath).value - assert_equal Prism.dump(source, filepath: filepath), Prism.dump_file(filepath) - - serialized = Prism.dump(source, filepath: filepath) - ast1 = Prism.load(source, serialized).value - ast2 = Prism.parse(source, filepath: filepath).value - ast3 = Prism.parse_file(filepath).value - - assert_equal_nodes ast1, ast2 - assert_equal_nodes ast2, ast3 - end - end - - def test_parse_success? - assert Prism.parse_success?("1") - refute Prism.parse_success?("<>") - end - - def test_parse_file_success? - assert Prism.parse_file_success?(__FILE__) - end - - def test_options - assert_equal "", Prism.parse("__FILE__").value.statements.body[0].filepath - assert_equal "foo.rb", Prism.parse("__FILE__", filepath: "foo.rb").value.statements.body[0].filepath - - assert_equal 1, Prism.parse("foo").value.statements.body[0].location.start_line - assert_equal 10, Prism.parse("foo", line: 10).value.statements.body[0].location.start_line - - refute Prism.parse("\"foo\"").value.statements.body[0].frozen? - assert Prism.parse("\"foo\"", frozen_string_literal: true).value.statements.body[0].frozen? - refute Prism.parse("\"foo\"", frozen_string_literal: false).value.statements.body[0].frozen? - - assert_kind_of Prism::CallNode, Prism.parse("foo").value.statements.body[0] - assert_kind_of Prism::LocalVariableReadNode, Prism.parse("foo", scopes: [[:foo]]).value.statements.body[0] - assert_equal 1, Prism.parse("foo", scopes: [[:foo], []]).value.statements.body[0].depth - - assert_equal [:foo], Prism.parse("foo", scopes: [[:foo]]).value.locals - end - - def test_literal_value_method - assert_equal 123, parse_expression("123").value - assert_equal 3.14, parse_expression("3.14").value - assert_equal 42i, parse_expression("42i").value - assert_equal 42.1ri, parse_expression("42.1ri").value - assert_equal 3.14i, parse_expression("3.14i").value - assert_equal 42r, parse_expression("42r").value - assert_equal 0.5r, parse_expression("0.5r").value - assert_equal 42ri, parse_expression("42ri").value - assert_equal 0.5ri, parse_expression("0.5ri").value - assert_equal 0xFFr, parse_expression("0xFFr").value - assert_equal 0xFFri, parse_expression("0xFFri").value - end - - def test_location_join - recv, args_node, _ = parse_expression("1234 + 567").child_nodes - arg = args_node.arguments[0] - - joined = recv.location.join(arg.location) - assert_equal 0, joined.start_offset - assert_equal 10, joined.length - - assert_raise RuntimeError, "Incompatible locations" do - arg.location.join(recv.location) - end - - other_arg = parse_expression("1234 + 567").arguments.arguments[0] - - assert_raise RuntimeError, "Incompatible sources" do - other_arg.location.join(recv.location) - end - - assert_raise RuntimeError, "Incompatible sources" do - recv.location.join(other_arg.location) - end - end - - def test_location_character_offsets - program = Prism.parse("😀 + 😀\n😍 ||= 😍").value - - # first 😀 - location = program.statements.body.first.receiver.location - assert_equal 0, location.start_character_offset - assert_equal 1, location.end_character_offset - assert_equal 0, location.start_character_column - assert_equal 1, location.end_character_column - - # second 😀 - location = program.statements.body.first.arguments.arguments.first.location - assert_equal 4, location.start_character_offset - assert_equal 5, location.end_character_offset - assert_equal 4, location.start_character_column - assert_equal 5, location.end_character_column - - # first 😍 - location = program.statements.body.last.name_loc - assert_equal 6, location.start_character_offset - assert_equal 7, location.end_character_offset - assert_equal 0, location.start_character_column - assert_equal 1, location.end_character_column - - # second 😍 - location = program.statements.body.last.value.location - assert_equal 12, location.start_character_offset - assert_equal 13, location.end_character_offset - assert_equal 6, location.start_character_column - assert_equal 7, location.end_character_column - end - - def test_location_code_units - program = Prism.parse("😀 + 😀\n😍 ||= 😍").value - - # first 😀 - location = program.statements.body.first.receiver.location - - assert_equal 0, location.start_code_units_offset(Encoding::UTF_8) - assert_equal 0, location.start_code_units_offset(Encoding::UTF_16LE) - assert_equal 0, location.start_code_units_offset(Encoding::UTF_32LE) - - assert_equal 1, location.end_code_units_offset(Encoding::UTF_8) - assert_equal 2, location.end_code_units_offset(Encoding::UTF_16LE) - assert_equal 1, location.end_code_units_offset(Encoding::UTF_32LE) - - assert_equal 0, location.start_code_units_column(Encoding::UTF_8) - assert_equal 0, location.start_code_units_column(Encoding::UTF_16LE) - assert_equal 0, location.start_code_units_column(Encoding::UTF_32LE) - - assert_equal 1, location.end_code_units_column(Encoding::UTF_8) - assert_equal 2, location.end_code_units_column(Encoding::UTF_16LE) - assert_equal 1, location.end_code_units_column(Encoding::UTF_32LE) - - # second 😀 - location = program.statements.body.first.arguments.arguments.first.location - - assert_equal 4, location.start_code_units_offset(Encoding::UTF_8) - assert_equal 5, location.start_code_units_offset(Encoding::UTF_16LE) - assert_equal 4, location.start_code_units_offset(Encoding::UTF_32LE) - - assert_equal 5, location.end_code_units_offset(Encoding::UTF_8) - assert_equal 7, location.end_code_units_offset(Encoding::UTF_16LE) - assert_equal 5, location.end_code_units_offset(Encoding::UTF_32LE) - - assert_equal 4, location.start_code_units_column(Encoding::UTF_8) - assert_equal 5, location.start_code_units_column(Encoding::UTF_16LE) - assert_equal 4, location.start_code_units_column(Encoding::UTF_32LE) - - assert_equal 5, location.end_code_units_column(Encoding::UTF_8) - assert_equal 7, location.end_code_units_column(Encoding::UTF_16LE) - assert_equal 5, location.end_code_units_column(Encoding::UTF_32LE) - - # first 😍 - location = program.statements.body.last.name_loc - - assert_equal 6, location.start_code_units_offset(Encoding::UTF_8) - assert_equal 8, location.start_code_units_offset(Encoding::UTF_16LE) - assert_equal 6, location.start_code_units_offset(Encoding::UTF_32LE) - - assert_equal 7, location.end_code_units_offset(Encoding::UTF_8) - assert_equal 10, location.end_code_units_offset(Encoding::UTF_16LE) - assert_equal 7, location.end_code_units_offset(Encoding::UTF_32LE) - - assert_equal 0, location.start_code_units_column(Encoding::UTF_8) - assert_equal 0, location.start_code_units_column(Encoding::UTF_16LE) - assert_equal 0, location.start_code_units_column(Encoding::UTF_32LE) - - assert_equal 1, location.end_code_units_column(Encoding::UTF_8) - assert_equal 2, location.end_code_units_column(Encoding::UTF_16LE) - assert_equal 1, location.end_code_units_column(Encoding::UTF_32LE) - - # second 😍 - location = program.statements.body.last.value.location - - assert_equal 12, location.start_code_units_offset(Encoding::UTF_8) - assert_equal 15, location.start_code_units_offset(Encoding::UTF_16LE) - assert_equal 12, location.start_code_units_offset(Encoding::UTF_32LE) - - assert_equal 13, location.end_code_units_offset(Encoding::UTF_8) - assert_equal 17, location.end_code_units_offset(Encoding::UTF_16LE) - assert_equal 13, location.end_code_units_offset(Encoding::UTF_32LE) - - assert_equal 6, location.start_code_units_column(Encoding::UTF_8) - assert_equal 7, location.start_code_units_column(Encoding::UTF_16LE) - assert_equal 6, location.start_code_units_column(Encoding::UTF_32LE) - - assert_equal 7, location.end_code_units_column(Encoding::UTF_8) - assert_equal 9, location.end_code_units_column(Encoding::UTF_16LE) - assert_equal 7, location.end_code_units_column(Encoding::UTF_32LE) - end - - def test_location_chop - location = Prism.parse("foo").value.location - - assert_equal "fo", location.chop.slice - assert_equal "", location.chop.chop.chop.slice - - # Check that we don't go negative. - 10.times { location = location.chop } - assert_equal "", location.slice - end - - def test_location_slice_lines - result = Prism.parse("\nprivate def foo\nend\n") - method = result.value.statements.body.first.arguments.arguments.first - - assert_equal "private def foo\nend\n", method.slice_lines - end - - def test_heredoc? - refute parse_expression("\"foo\"").heredoc? - refute parse_expression("\"foo \#{1}\"").heredoc? - refute parse_expression("`foo`").heredoc? - refute parse_expression("`foo \#{1}`").heredoc? - - assert parse_expression("<<~HERE\nfoo\nHERE\n").heredoc? - assert parse_expression("<<~HERE\nfoo \#{1}\nHERE\n").heredoc? - assert parse_expression("<<~`HERE`\nfoo\nHERE\n").heredoc? - assert parse_expression("<<~`HERE`\nfoo \#{1}\nHERE\n").heredoc? - end - - # Through some bit hackery, we want to allow consumers to use the integer - # base flags as the base itself. It has a nice property that the current - # alignment provides them in the correct order. So here we test that our - # assumption holds so that it doesn't change out from under us. - # - # In C, this would look something like: - # - # ((flags & ~DECIMAL) << 1) || 10 - # - # We have to do some other work in Ruby because 0 is truthy and ~ on an - # integer doesn't have a fixed width. - def test_integer_base_flags - base = -> (node) do - value = (node.send(:flags) & (0b1111 - IntegerBaseFlags::DECIMAL)) << 1 - value == 0 ? 10 : value - end - - assert_equal 2, base[parse_expression("0b1")] - assert_equal 8, base[parse_expression("0o1")] - assert_equal 10, base[parse_expression("0d1")] - assert_equal 16, base[parse_expression("0x1")] - end - - def test_node_equality - assert_operator parse_expression("1"), :===, parse_expression("1") - assert_operator Prism.parse("1").value, :===, Prism.parse("1").value - - complex_source = "class Something; @var = something.else { _1 }; end" - assert_operator parse_expression(complex_source), :===, parse_expression(complex_source) - - refute_operator parse_expression("1"), :===, parse_expression("2") - refute_operator parse_expression("1"), :===, parse_expression("0x1") - - complex_source_1 = "class Something; @var = something.else { _1 }; end" - complex_source_2 = "class Something; @var = something.else { _2 }; end" - refute_operator parse_expression(complex_source_1), :===, parse_expression(complex_source_2) - end - - def test_node_tunnel - program = Prism.parse("foo(1) +\n bar(2, 3) +\n baz(3, 4, 5)").value - - tunnel = program.tunnel(1, 4).last - assert_kind_of IntegerNode, tunnel - assert_equal 1, tunnel.value - - tunnel = program.tunnel(2, 6).last - assert_kind_of IntegerNode, tunnel - assert_equal 2, tunnel.value - - tunnel = program.tunnel(3, 9).last - assert_kind_of IntegerNode, tunnel - assert_equal 4, tunnel.value - - tunnel = program.tunnel(3, 8) - assert_equal [ProgramNode, StatementsNode, CallNode, ArgumentsNode, CallNode, ArgumentsNode], tunnel.map(&:class) - end - - def test_location_adjoin - program = Prism.parse("foo.bar = 1").value - - location = program.statements.body.first.message_loc - adjoined = location.adjoin("=") - - assert_kind_of Location, adjoined - refute_equal location, adjoined - - assert_equal 4, adjoined.start_offset - assert_equal 9, adjoined.end_offset - end - - private - - def parse_expression(source) - Prism.parse(source).value.statements.body.first - end - end -end diff --git a/test/prism/ruby_parser_test.rb b/test/prism/ruby_parser_test.rb deleted file mode 100644 index 8edeac4b4f8..00000000000 --- a/test/prism/ruby_parser_test.rb +++ /dev/null @@ -1,144 +0,0 @@ -# frozen_string_literal: true - -return if RUBY_ENGINE == "jruby" - -require_relative "test_helper" - -begin - require "ruby_parser" -rescue LoadError - # In CRuby's CI, we're not going to test against the ruby_parser gem because - # we don't want to have to install it. So in this case we'll just skip this - # test. - return -end - -# We want to also compare lines and files to make sure we're setting them -# correctly. -Sexp.prepend( - Module.new do - def ==(other) - super && line == other.line && line_max == other.line_max && file == other.file - end - end -) - -module Prism - class RubyParserTest < TestCase - base = File.join(__dir__, "fixtures") - - todos = %w[ - heredocs_nested.txt - newline_terminated.txt - regex_char_width.txt - seattlerb/bug169.txt - seattlerb/dstr_evstr.txt - seattlerb/heredoc_squiggly_interp.txt - seattlerb/masgn_colon3.txt - seattlerb/messy_op_asgn_lineno.txt - seattlerb/op_asgn_primary_colon_const_command_call.txt - seattlerb/parse_line_evstr_after_break.txt - seattlerb/regexp_esc_C_slash.txt - seattlerb/str_lit_concat_bad_encodings.txt - seattlerb/str_pct_nested_nested.txt - unescaping.txt - unparser/corpus/literal/kwbegin.txt - unparser/corpus/literal/send.txt - unparser/corpus/semantic/dstr.txt - whitequark/masgn_const.txt - whitequark/ruby_bug_12402.txt - whitequark/ruby_bug_14690.txt - whitequark/space_args_block.txt - whitequark/string_concat.txt - ] - - # https://github.com/seattlerb/ruby_parser/issues/344 - failures = %w[ - alias.txt - dos_endings.txt - heredocs_with_ignored_newlines.txt - method_calls.txt - methods.txt - multi_write.txt - not.txt - patterns.txt - regex.txt - seattlerb/and_multi.txt - seattlerb/heredoc__backslash_dos_format.txt - seattlerb/heredoc_bad_hex_escape.txt - seattlerb/heredoc_bad_oct_escape.txt - seattlerb/heredoc_with_extra_carriage_horrible_mix.txt - seattlerb/heredoc_with_extra_carriage_returns_windows.txt - seattlerb/heredoc_with_only_carriage_returns_windows.txt - seattlerb/heredoc_with_only_carriage_returns.txt - spanning_heredoc_newlines.txt - spanning_heredoc.txt - tilde_heredocs.txt - unparser/corpus/literal/literal.txt - while.txt - whitequark/class_definition_in_while_cond.txt - whitequark/cond_eflipflop.txt - whitequark/cond_iflipflop.txt - whitequark/cond_match_current_line.txt - whitequark/dedenting_heredoc.txt - whitequark/if_while_after_class__since_32.txt - whitequark/lvar_injecting_match.txt - whitequark/not.txt - whitequark/numparam_ruby_bug_19025.txt - whitequark/op_asgn_cmd.txt - whitequark/parser_bug_640.txt - whitequark/parser_slash_slash_n_escaping_in_literals.txt - whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt - whitequark/pattern_matching_single_line.txt - whitequark/ruby_bug_11989.txt - whitequark/slash_newline_in_heredocs.txt - ] - - Dir["**/*.txt", base: base].each do |name| - next if failures.include?(name) - - define_method("test_#{name}") do - begin - # Parsing with ruby parser tends to be noisy with warnings, so we're - # turning those off. - previous_verbose, $VERBOSE = $VERBOSE, nil - assert_parse_file(base, name, todos.include?(name)) - ensure - $VERBOSE = previous_verbose - end - end - end - - private - - def assert_parse_file(base, name, allowed_failure) - filepath = File.join(base, name) - expected = ::RubyParser.new.parse(File.read(filepath), filepath) - actual = Prism::Translation::RubyParser.parse_file(filepath) - - if !allowed_failure - assert_equal_nodes expected, actual - elsif expected == actual - puts "#{name} now passes" - end - end - - def assert_equal_nodes(left, right) - return if left == right - - if left.is_a?(Sexp) && right.is_a?(Sexp) - if left.line != right.line - assert_equal "(#{left.inspect} line=#{left.line})", "(#{right.inspect} line=#{right.line})" - elsif left.file != right.file - assert_equal "(#{left.inspect} file=#{left.file})", "(#{right.inspect} file=#{right.file})" - elsif left.length != right.length - assert_equal "(#{left.inspect} length=#{left.length})", "(#{right.inspect} length=#{right.length})" - else - left.zip(right).each { |l, r| assert_equal_nodes(l, r) } - end - else - assert_equal left, right - end - end - end -end diff --git a/test/prism/snapshots/alias.txt b/test/prism/snapshots/alias.txt index a952e96f677..0d52c14f1a8 100644 --- a/test/prism/snapshots/alias.txt +++ b/test/prism/snapshots/alias.txt @@ -1,192 +1,213 @@ @ ProgramNode (location: (1,0)-(23,11)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(23,11)) + ├── flags: ∅ └── body: (length: 12) ├── @ AliasMethodNode (location: (1,0)-(1,15)) + │ ├── flags: newline │ ├── new_name: │ │ @ SymbolNode (location: (1,6)-(1,10)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,6)-(1,7) = ":" │ │ ├── value_loc: (1,7)-(1,10) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ ├── old_name: │ │ @ SymbolNode (location: (1,11)-(1,15)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,11)-(1,12) = ":" │ │ ├── value_loc: (1,12)-(1,15) = "bar" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "bar" │ └── keyword_loc: (1,0)-(1,5) = "alias" ├── @ AliasMethodNode (location: (3,0)-(3,21)) + │ ├── flags: newline │ ├── new_name: │ │ @ SymbolNode (location: (3,6)-(3,13)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,6)-(3,9) = "%s[" │ │ ├── value_loc: (3,9)-(3,12) = "abc" │ │ ├── closing_loc: (3,12)-(3,13) = "]" │ │ └── unescaped: "abc" │ ├── old_name: │ │ @ SymbolNode (location: (3,14)-(3,21)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,14)-(3,17) = "%s[" │ │ ├── value_loc: (3,17)-(3,20) = "def" │ │ ├── closing_loc: (3,20)-(3,21) = "]" │ │ └── unescaped: "def" │ └── keyword_loc: (3,0)-(3,5) = "alias" ├── @ AliasMethodNode (location: (5,0)-(5,19)) + │ ├── flags: newline │ ├── new_name: │ │ @ SymbolNode (location: (5,6)-(5,12)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (5,6)-(5,8) = ":'" │ │ ├── value_loc: (5,8)-(5,11) = "abc" │ │ ├── closing_loc: (5,11)-(5,12) = "'" │ │ └── unescaped: "abc" │ ├── old_name: │ │ @ SymbolNode (location: (5,13)-(5,19)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (5,13)-(5,15) = ":'" │ │ ├── value_loc: (5,15)-(5,18) = "def" │ │ ├── closing_loc: (5,18)-(5,19) = "'" │ │ └── unescaped: "def" │ └── keyword_loc: (5,0)-(5,5) = "alias" ├── @ AliasMethodNode (location: (7,0)-(7,23)) + │ ├── flags: newline │ ├── new_name: │ │ @ InterpolatedSymbolNode (location: (7,6)-(7,16)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (7,6)-(7,8) = ":\"" │ │ ├── parts: (length: 2) │ │ │ ├── @ StringNode (location: (7,8)-(7,11)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (7,8)-(7,11) = "abc" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "abc" │ │ │ └── @ EmbeddedStatementsNode (location: (7,11)-(7,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (7,11)-(7,13) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (7,13)-(7,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (7,13)-(7,14)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (7,14)-(7,15) = "}" │ │ └── closing_loc: (7,15)-(7,16) = "\"" │ ├── old_name: │ │ @ SymbolNode (location: (7,17)-(7,23)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (7,17)-(7,19) = ":'" │ │ ├── value_loc: (7,19)-(7,22) = "def" │ │ ├── closing_loc: (7,22)-(7,23) = "'" │ │ └── unescaped: "def" │ └── keyword_loc: (7,0)-(7,5) = "alias" ├── @ AliasGlobalVariableNode (location: (9,0)-(9,11)) + │ ├── flags: newline │ ├── new_name: │ │ @ GlobalVariableReadNode (location: (9,6)-(9,8)) + │ │ ├── flags: ∅ │ │ └── name: :$a │ ├── old_name: │ │ @ BackReferenceReadNode (location: (9,9)-(9,11)) + │ │ ├── flags: ∅ │ │ └── name: :$' │ └── keyword_loc: (9,0)-(9,5) = "alias" ├── @ AliasMethodNode (location: (11,0)-(11,13)) + │ ├── flags: newline │ ├── new_name: │ │ @ SymbolNode (location: (11,6)-(11,9)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (11,6)-(11,9) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ ├── old_name: │ │ @ SymbolNode (location: (11,10)-(11,13)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (11,10)-(11,13) = "bar" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "bar" │ └── keyword_loc: (11,0)-(11,5) = "alias" ├── @ AliasGlobalVariableNode (location: (13,0)-(13,15)) + │ ├── flags: newline │ ├── new_name: │ │ @ GlobalVariableReadNode (location: (13,6)-(13,10)) + │ │ ├── flags: ∅ │ │ └── name: :$foo │ ├── old_name: │ │ @ GlobalVariableReadNode (location: (13,11)-(13,15)) + │ │ ├── flags: ∅ │ │ └── name: :$bar │ └── keyword_loc: (13,0)-(13,5) = "alias" ├── @ AliasMethodNode (location: (15,0)-(15,12)) + │ ├── flags: newline │ ├── new_name: │ │ @ SymbolNode (location: (15,6)-(15,9)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (15,6)-(15,9) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ ├── old_name: │ │ @ SymbolNode (location: (15,10)-(15,12)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (15,10)-(15,12) = "if" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "if" │ └── keyword_loc: (15,0)-(15,5) = "alias" ├── @ AliasMethodNode (location: (17,0)-(17,13)) + │ ├── flags: newline │ ├── new_name: │ │ @ SymbolNode (location: (17,6)-(17,9)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (17,6)-(17,9) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ ├── old_name: │ │ @ SymbolNode (location: (17,10)-(17,13)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (17,10)-(17,13) = "<=>" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "<=>" │ └── keyword_loc: (17,0)-(17,5) = "alias" ├── @ AliasMethodNode (location: (19,0)-(19,15)) + │ ├── flags: newline │ ├── new_name: │ │ @ SymbolNode (location: (19,6)-(19,9)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (19,6)-(19,7) = ":" │ │ ├── value_loc: (19,7)-(19,9) = "==" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "==" │ ├── old_name: │ │ @ SymbolNode (location: (19,10)-(19,15)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (19,10)-(19,11) = ":" │ │ ├── value_loc: (19,11)-(19,15) = "eql?" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "eql?" │ └── keyword_loc: (19,0)-(19,5) = "alias" ├── @ AliasMethodNode (location: (21,0)-(21,9)) + │ ├── flags: newline │ ├── new_name: │ │ @ SymbolNode (location: (21,6)-(21,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (21,6)-(21,7) = "A" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "A" │ ├── old_name: │ │ @ SymbolNode (location: (21,8)-(21,9)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (21,8)-(21,9) = "B" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "B" │ └── keyword_loc: (21,0)-(21,5) = "alias" └── @ AliasMethodNode (location: (23,0)-(23,11)) + ├── flags: newline ├── new_name: │ @ SymbolNode (location: (23,6)-(23,8)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (23,6)-(23,7) = ":" │ ├── value_loc: (23,7)-(23,8) = "A" │ ├── closing_loc: ∅ │ └── unescaped: "A" ├── old_name: │ @ SymbolNode (location: (23,9)-(23,11)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (23,9)-(23,10) = ":" │ ├── value_loc: (23,10)-(23,11) = "B" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/arithmetic.txt b/test/prism/snapshots/arithmetic.txt index c8a31c3d70e..963080e0d96 100644 --- a/test/prism/snapshots/arithmetic.txt +++ b/test/prism/snapshots/arithmetic.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(13,8)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(13,8)) + ├── flags: ∅ └── body: (length: 7) ├── @ CallNode (location: (1,0)-(1,8)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -37,7 +39,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (3,0)-(3,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (3,0)-(3,4)) │ │ ├── flags: ∅ @@ -80,7 +82,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (5,0)-(5,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (5,0)-(5,4)) │ │ ├── flags: ∅ @@ -123,7 +125,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (7,0)-(7,8)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -156,7 +158,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (9,0)-(9,17)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (9,0)-(9,10)) │ │ ├── flags: ∅ @@ -212,13 +214,13 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (11,0)-(11,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (11,1)-(11,5)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (11,1)-(11,2)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :** @@ -229,7 +231,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (11,4)-(11,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ @@ -241,10 +243,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ └── @ CallNode (location: (13,0)-(13,8)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (13,0)-(13,2)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: -1 ├── call_operator_loc: (13,2)-(13,3) = "." ├── name: :zero? diff --git a/test/prism/snapshots/arrays.txt b/test/prism/snapshots/arrays.txt index e8e53aacb95..f34ee1395c4 100644 --- a/test/prism/snapshots/arrays.txt +++ b/test/prism/snapshots/arrays.txt @@ -1,12 +1,15 @@ @ ProgramNode (location: (1,0)-(122,32)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(122,32)) + ├── flags: ∅ └── body: (length: 50) ├── @ ArrayNode (location: (1,0)-(1,4)) - │ ├── flags: contains_splat + │ ├── flags: newline, contains_splat │ ├── elements: (length: 1) │ │ └── @ SplatNode (location: (1,1)-(1,3)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (1,1)-(1,2) = "*" │ │ └── expression: │ │ @ CallNode (location: (1,2)-(1,3)) @@ -22,7 +25,7 @@ │ ├── opening_loc: (1,0)-(1,1) = "[" │ └── closing_loc: (1,3)-(1,4) = "]" ├── @ CallNode (location: (3,0)-(3,23)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ CallNode (location: (3,0)-(3,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -63,47 +66,48 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ ArrayNode (location: (3,16)-(3,23)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── elements: (length: 3) │ │ │ ├── @ IntegerNode (location: (3,16)-(3,17)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── @ IntegerNode (location: (3,19)-(3,20)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ └── @ IntegerNode (location: (3,22)-(3,23)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ ├── opening_loc: ∅ │ │ └── closing_loc: ∅ │ ├── closing_loc: (3,12)-(3,13) = "]" │ └── block: ∅ ├── @ ArrayNode (location: (5,0)-(5,13)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 1) │ │ └── @ KeywordHashNode (location: (5,1)-(5,12)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (5,1)-(5,12)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ SymbolNode (location: (5,1)-(5,3)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (5,1)-(5,2) = "a" │ │ │ ├── closing_loc: (5,2)-(5,3) = ":" │ │ │ └── unescaped: "a" │ │ ├── value: │ │ │ @ ArrayNode (location: (5,4)-(5,12)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: static_literal │ │ │ ├── elements: (length: 2) │ │ │ │ ├── @ SymbolNode (location: (5,5)-(5,7)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (5,5)-(5,6) = ":" │ │ │ │ │ ├── value_loc: (5,6)-(5,7) = "b" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "b" │ │ │ │ └── @ SymbolNode (location: (5,9)-(5,11)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (5,9)-(5,10) = ":" │ │ │ │ ├── value_loc: (5,10)-(5,11) = "c" │ │ │ │ ├── closing_loc: ∅ @@ -114,31 +118,31 @@ │ ├── opening_loc: (5,0)-(5,1) = "[" │ └── closing_loc: (5,12)-(5,13) = "]" ├── @ ArrayNode (location: (9,0)-(15,1)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 5) │ │ ├── @ SymbolNode (location: (9,1)-(9,3)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (9,1)-(9,2) = ":" │ │ │ ├── value_loc: (9,2)-(9,3) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ ├── @ SymbolNode (location: (9,5)-(9,7)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (9,5)-(9,6) = ":" │ │ │ ├── value_loc: (9,6)-(9,7) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" │ │ ├── @ SymbolNode (location: (10,0)-(10,2)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (10,0)-(10,1) = ":" │ │ │ ├── value_loc: (10,1)-(10,2) = "c" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "c" │ │ ├── @ IntegerNode (location: (10,3)-(10,4)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ SymbolNode (location: (14,0)-(14,2)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (14,0)-(14,1) = ":" │ │ ├── value_loc: (14,1)-(14,2) = "d" │ │ ├── closing_loc: ∅ @@ -146,31 +150,31 @@ │ ├── opening_loc: (9,0)-(9,1) = "[" │ └── closing_loc: (15,0)-(15,1) = "]" ├── @ ArrayNode (location: (18,0)-(26,1)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 5) │ │ ├── @ SymbolNode (location: (18,1)-(18,3)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (18,1)-(18,2) = ":" │ │ │ ├── value_loc: (18,2)-(18,3) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ ├── @ SymbolNode (location: (18,5)-(18,7)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (18,5)-(18,6) = ":" │ │ │ ├── value_loc: (18,6)-(18,7) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" │ │ ├── @ SymbolNode (location: (19,0)-(19,2)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (19,0)-(19,1) = ":" │ │ │ ├── value_loc: (19,1)-(19,2) = "c" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "c" │ │ ├── @ IntegerNode (location: (19,3)-(19,4)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ SymbolNode (location: (23,0)-(23,2)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (23,0)-(23,1) = ":" │ │ ├── value_loc: (23,1)-(23,2) = "d" │ │ ├── closing_loc: ∅ @@ -178,12 +182,13 @@ │ ├── opening_loc: (18,0)-(18,1) = "[" │ └── closing_loc: (26,0)-(26,1) = "]" ├── @ ArrayNode (location: (28,0)-(28,12)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 1) │ │ └── @ KeywordHashNode (location: (28,1)-(28,11)) │ │ ├── flags: ∅ │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (28,1)-(28,11)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ CallNode (location: (28,1)-(28,4)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -210,7 +215,7 @@ │ ├── opening_loc: (28,0)-(28,1) = "[" │ └── closing_loc: (28,11)-(28,12) = "]" ├── @ CallNode (location: (30,0)-(30,19)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ CallNode (location: (30,0)-(30,8)) │ │ ├── flags: ∅ @@ -276,7 +281,7 @@ │ ├── closing_loc: (30,12)-(30,13) = "]" │ └── block: ∅ ├── @ CallNode (location: (32,0)-(32,13)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (32,0)-(32,8)) │ │ ├── flags: ∅ @@ -332,12 +337,12 @@ │ ├── closing_loc: (32,12)-(32,13) = "]" │ └── block: ∅ ├── @ ArrayNode (location: (34,0)-(35,1)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 0) │ ├── opening_loc: (34,0)-(34,1) = "[" │ └── closing_loc: (35,0)-(35,1) = "]" ├── @ CallNode (location: (37,0)-(37,13)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (37,0)-(37,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -380,7 +385,7 @@ │ ├── closing_loc: (37,12)-(37,13) = "]" │ └── block: ∅ ├── @ CallNode (location: (39,0)-(39,19)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ CallNode (location: (39,0)-(39,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -433,6 +438,7 @@ │ ├── closing_loc: (39,12)-(39,13) = "]" │ └── block: ∅ ├── @ MultiWriteNode (location: (41,0)-(41,21)) + │ ├── flags: newline │ ├── lefts: (length: 2) │ │ ├── @ IndexTargetNode (location: (41,0)-(41,6)) │ │ │ ├── flags: attribute_write @@ -453,7 +459,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (41,4)-(41,5)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 0 │ │ │ ├── closing_loc: (41,5)-(41,6) = "]" │ │ │ └── block: ∅ @@ -476,7 +482,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (41,12)-(41,13)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 0 │ │ ├── closing_loc: (41,13)-(41,14) = "]" │ │ └── block: ∅ @@ -487,18 +493,18 @@ │ ├── operator_loc: (41,15)-(41,16) = "=" │ └── value: │ @ ArrayNode (location: (41,17)-(41,21)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (41,17)-(41,18)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (41,20)-(41,21)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: ∅ │ └── closing_loc: ∅ ├── @ CallNode (location: (43,0)-(43,19)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (43,0)-(43,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -564,7 +570,7 @@ │ ├── closing_loc: (43,18)-(43,19) = "]" │ └── block: ∅ ├── @ CallNode (location: (45,0)-(45,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (45,0)-(45,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -597,7 +603,7 @@ │ ├── closing_loc: (45,7)-(45,8) = "]" │ └── block: ∅ ├── @ CallNode (location: (47,0)-(47,14)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ CallNode (location: (47,0)-(47,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -640,14 +646,16 @@ │ ├── closing_loc: (47,7)-(47,8) = "]" │ └── block: ∅ ├── @ ArrayNode (location: (49,0)-(49,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 1) │ │ └── @ KeywordHashNode (location: (49,1)-(49,5)) │ │ ├── flags: ∅ │ │ └── elements: (length: 1) │ │ └── @ AssocSplatNode (location: (49,1)-(49,5)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ HashNode (location: (49,3)-(49,5)) + │ │ │ ├── flags: static_literal │ │ │ ├── opening_loc: (49,3)-(49,4) = "{" │ │ │ ├── elements: (length: 0) │ │ │ └── closing_loc: (49,4)-(49,5) = "}" @@ -655,12 +663,13 @@ │ ├── opening_loc: (49,0)-(49,1) = "[" │ └── closing_loc: (49,5)-(49,6) = "]" ├── @ ArrayNode (location: (51,0)-(51,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 1) │ │ └── @ KeywordHashNode (location: (51,1)-(51,5)) │ │ ├── flags: ∅ │ │ └── elements: (length: 1) │ │ └── @ AssocSplatNode (location: (51,1)-(51,5)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ CallNode (location: (51,3)-(51,5)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -676,15 +685,16 @@ │ ├── opening_loc: (51,0)-(51,1) = "[" │ └── closing_loc: (51,5)-(51,6) = "]" ├── @ ArrayNode (location: (53,0)-(53,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (53,1)-(53,2)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ KeywordHashNode (location: (53,4)-(53,8)) │ │ ├── flags: ∅ │ │ └── elements: (length: 1) │ │ └── @ AssocSplatNode (location: (53,4)-(53,8)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ CallNode (location: (53,6)-(53,8)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -700,15 +710,16 @@ │ ├── opening_loc: (53,0)-(53,1) = "[" │ └── closing_loc: (53,8)-(53,9) = "]" ├── @ ArrayNode (location: (55,0)-(55,21)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (55,1)-(55,2)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ KeywordHashNode (location: (55,4)-(55,20)) │ │ ├── flags: ∅ │ │ └── elements: (length: 3) │ │ ├── @ AssocSplatNode (location: (55,4)-(55,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── value: │ │ │ │ @ CallNode (location: (55,6)-(55,8)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -722,13 +733,16 @@ │ │ │ │ └── block: ∅ │ │ │ └── operator_loc: (55,4)-(55,6) = "**" │ │ ├── @ AssocSplatNode (location: (55,10)-(55,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── value: │ │ │ │ @ HashNode (location: (55,12)-(55,14)) + │ │ │ │ ├── flags: static_literal │ │ │ │ ├── opening_loc: (55,12)-(55,13) = "{" │ │ │ │ ├── elements: (length: 0) │ │ │ │ └── closing_loc: (55,13)-(55,14) = "}" │ │ │ └── operator_loc: (55,10)-(55,12) = "**" │ │ └── @ AssocSplatNode (location: (55,16)-(55,20)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ CallNode (location: (55,18)-(55,20)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -744,12 +758,13 @@ │ ├── opening_loc: (55,0)-(55,1) = "[" │ └── closing_loc: (55,20)-(55,21) = "]" ├── @ ArrayNode (location: (57,0)-(59,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 1) │ │ └── @ KeywordHashNode (location: (58,2)-(58,12)) │ │ ├── flags: ∅ │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (58,2)-(58,12)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ CallNode (location: (58,2)-(58,5)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -776,22 +791,22 @@ │ ├── opening_loc: (57,0)-(57,1) = "[" │ └── closing_loc: (59,0)-(59,1) = "]" ├── @ ArrayNode (location: (62,0)-(62,17)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 3) │ │ ├── @ SymbolNode (location: (62,3)-(62,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (62,3)-(62,6) = "one" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "one" │ │ ├── @ SymbolNode (location: (62,7)-(62,10)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (62,7)-(62,10) = "two" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "two" │ │ └── @ SymbolNode (location: (62,11)-(62,16)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (62,11)-(62,16) = "three" │ │ ├── closing_loc: ∅ @@ -799,7 +814,7 @@ │ ├── opening_loc: (62,0)-(62,3) = "%i#" │ └── closing_loc: (62,16)-(62,17) = "#" ├── @ ArrayNode (location: (64,0)-(64,17)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 3) │ │ ├── @ StringNode (location: (64,3)-(64,6)) │ │ │ ├── flags: ∅ @@ -822,28 +837,28 @@ │ ├── opening_loc: (64,0)-(64,3) = "%w#" │ └── closing_loc: (64,16)-(64,17) = "#" ├── @ XStringNode (location: (66,0)-(66,17)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (66,0)-(66,3) = "%x#" │ ├── content_loc: (66,3)-(66,16) = "one two three" │ ├── closing_loc: (66,16)-(66,17) = "#" │ └── unescaped: "one two three" ├── @ ArrayNode (location: (69,0)-(69,17)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 3) │ │ ├── @ SymbolNode (location: (69,3)-(69,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (69,3)-(69,6) = "one" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "one" │ │ ├── @ SymbolNode (location: (69,7)-(69,10)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (69,7)-(69,10) = "two" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "two" │ │ └── @ SymbolNode (location: (69,11)-(69,16)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (69,11)-(69,16) = "three" │ │ ├── closing_loc: ∅ @@ -851,7 +866,7 @@ │ ├── opening_loc: (69,0)-(69,3) = "%i@" │ └── closing_loc: (69,16)-(69,17) = "@" ├── @ ArrayNode (location: (71,0)-(71,17)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 3) │ │ ├── @ StringNode (location: (71,3)-(71,6)) │ │ │ ├── flags: ∅ @@ -874,28 +889,28 @@ │ ├── opening_loc: (71,0)-(71,3) = "%w@" │ └── closing_loc: (71,16)-(71,17) = "@" ├── @ XStringNode (location: (73,0)-(73,17)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (73,0)-(73,3) = "%x@" │ ├── content_loc: (73,3)-(73,16) = "one two three" │ ├── closing_loc: (73,16)-(73,17) = "@" │ └── unescaped: "one two three" ├── @ ArrayNode (location: (76,0)-(76,17)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 3) │ │ ├── @ SymbolNode (location: (76,3)-(76,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (76,3)-(76,6) = "one" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "one" │ │ ├── @ SymbolNode (location: (76,7)-(76,10)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (76,7)-(76,10) = "two" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "two" │ │ └── @ SymbolNode (location: (76,11)-(76,16)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (76,11)-(76,16) = "three" │ │ ├── closing_loc: ∅ @@ -903,7 +918,7 @@ │ ├── opening_loc: (76,0)-(76,3) = "%i{" │ └── closing_loc: (76,16)-(76,17) = "}" ├── @ ArrayNode (location: (78,0)-(78,17)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 3) │ │ ├── @ StringNode (location: (78,3)-(78,6)) │ │ │ ├── flags: ∅ @@ -926,13 +941,13 @@ │ ├── opening_loc: (78,0)-(78,3) = "%w{" │ └── closing_loc: (78,16)-(78,17) = "}" ├── @ XStringNode (location: (80,0)-(80,17)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (80,0)-(80,3) = "%x{" │ ├── content_loc: (80,3)-(80,16) = "one two three" │ ├── closing_loc: (80,16)-(80,17) = "}" │ └── unescaped: "one two three" ├── @ ArrayNode (location: (82,0)-(82,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 1) │ │ └── @ StringNode (location: (82,3)-(82,6)) │ │ ├── flags: ∅ @@ -943,7 +958,7 @@ │ ├── opening_loc: (82,0)-(82,3) = "%w[" │ └── closing_loc: (82,6)-(82,7) = "]" ├── @ IndexOperatorWriteNode (location: (84,0)-(84,10)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (84,0)-(84,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -960,14 +975,14 @@ │ ├── arguments: ∅ │ ├── closing_loc: (84,4)-(84,5) = "]" │ ├── block: ∅ - │ ├── operator: :+ - │ ├── operator_loc: (84,6)-(84,8) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (84,6)-(84,8) = "+=" │ └── value: │ @ IntegerNode (location: (84,9)-(84,10)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ IndexOrWriteNode (location: (86,0)-(86,11)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (86,0)-(86,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -987,10 +1002,10 @@ │ ├── operator_loc: (86,6)-(86,9) = "||=" │ └── value: │ @ IntegerNode (location: (86,10)-(86,11)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ IndexAndWriteNode (location: (88,0)-(88,11)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (88,0)-(88,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1010,10 +1025,10 @@ │ ├── operator_loc: (88,6)-(88,9) = "&&=" │ └── value: │ @ IntegerNode (location: (88,10)-(88,11)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ IndexOperatorWriteNode (location: (90,0)-(90,14)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (90,0)-(90,7)) │ │ ├── flags: ∅ @@ -1040,14 +1055,14 @@ │ ├── arguments: ∅ │ ├── closing_loc: (90,8)-(90,9) = "]" │ ├── block: ∅ - │ ├── operator: :+ - │ ├── operator_loc: (90,10)-(90,12) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (90,10)-(90,12) = "+=" │ └── value: │ @ IntegerNode (location: (90,13)-(90,14)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ IndexOrWriteNode (location: (92,0)-(92,15)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (92,0)-(92,7)) │ │ ├── flags: ∅ @@ -1077,10 +1092,10 @@ │ ├── operator_loc: (92,10)-(92,13) = "||=" │ └── value: │ @ IntegerNode (location: (92,14)-(92,15)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ IndexAndWriteNode (location: (94,0)-(94,15)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (94,0)-(94,7)) │ │ ├── flags: ∅ @@ -1110,10 +1125,10 @@ │ ├── operator_loc: (94,10)-(94,13) = "&&=" │ └── value: │ @ IntegerNode (location: (94,14)-(94,15)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ IndexOperatorWriteNode (location: (96,0)-(96,13)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (96,0)-(96,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1143,14 +1158,14 @@ │ │ └── block: ∅ │ ├── closing_loc: (96,7)-(96,8) = "]" │ ├── block: ∅ - │ ├── operator: :+ - │ ├── operator_loc: (96,9)-(96,11) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (96,9)-(96,11) = "+=" │ └── value: │ @ IntegerNode (location: (96,12)-(96,13)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ IndexOrWriteNode (location: (98,0)-(98,14)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (98,0)-(98,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1183,10 +1198,10 @@ │ ├── operator_loc: (98,9)-(98,12) = "||=" │ └── value: │ @ IntegerNode (location: (98,13)-(98,14)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ IndexAndWriteNode (location: (100,0)-(100,14)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (100,0)-(100,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1219,10 +1234,10 @@ │ ├── operator_loc: (100,9)-(100,12) = "&&=" │ └── value: │ @ IntegerNode (location: (100,13)-(100,14)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ IndexOperatorWriteNode (location: (102,0)-(102,17)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (102,0)-(102,7)) │ │ ├── flags: ∅ @@ -1262,14 +1277,14 @@ │ │ └── block: ∅ │ ├── closing_loc: (102,11)-(102,12) = "]" │ ├── block: ∅ - │ ├── operator: :+ - │ ├── operator_loc: (102,13)-(102,15) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (102,13)-(102,15) = "+=" │ └── value: │ @ IntegerNode (location: (102,16)-(102,17)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ IndexOrWriteNode (location: (104,0)-(104,18)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (104,0)-(104,7)) │ │ ├── flags: ∅ @@ -1312,10 +1327,10 @@ │ ├── operator_loc: (104,13)-(104,16) = "||=" │ └── value: │ @ IntegerNode (location: (104,17)-(104,18)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ IndexAndWriteNode (location: (106,0)-(106,18)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (106,0)-(106,7)) │ │ ├── flags: ∅ @@ -1358,14 +1373,16 @@ │ ├── operator_loc: (106,13)-(106,16) = "&&=" │ └── value: │ @ IntegerNode (location: (106,17)-(106,18)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ DefNode (location: (108,0)-(108,19)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (108,4)-(108,5) = "f" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (108,6)-(108,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: @@ -1380,9 +1397,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (108,10)-(108,14)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (108,10)-(108,14)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ CallNode (location: (108,10)-(108,11)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -1400,9 +1418,10 @@ │ │ ├── opening_loc: (108,11)-(108,12) = "[" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (108,12)-(108,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_splat │ │ │ └── arguments: (length: 1) │ │ │ └── @ SplatNode (location: (108,12)-(108,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (108,12)-(108,13) = "*" │ │ │ └── expression: ∅ │ │ ├── closing_loc: (108,13)-(108,14) = "]" @@ -1415,11 +1434,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (108,16)-(108,19) = "end" ├── @ DefNode (location: (110,0)-(110,22)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (110,4)-(110,5) = "f" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (110,6)-(110,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: @@ -1434,9 +1455,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (110,10)-(110,17)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (110,10)-(110,17)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ CallNode (location: (110,10)-(110,11)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -1454,12 +1476,13 @@ │ │ ├── opening_loc: (110,11)-(110,12) = "[" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (110,12)-(110,16)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_splat │ │ │ └── arguments: (length: 2) │ │ │ ├── @ IntegerNode (location: (110,12)-(110,13)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── @ SplatNode (location: (110,15)-(110,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (110,15)-(110,16) = "*" │ │ │ └── expression: ∅ │ │ ├── closing_loc: (110,16)-(110,17) = "]" @@ -1472,11 +1495,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (110,19)-(110,22) = "end" ├── @ DefNode (location: (112,0)-(112,23)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (112,4)-(112,5) = "f" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (112,6)-(112,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: @@ -1491,9 +1516,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (112,10)-(112,18)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (112,10)-(112,18)) - │ │ ├── flags: attribute_write + │ │ ├── flags: newline, attribute_write │ │ ├── receiver: │ │ │ @ CallNode (location: (112,10)-(112,11)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -1511,13 +1537,14 @@ │ │ ├── opening_loc: (112,11)-(112,12) = "[" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (112,12)-(112,18)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_splat │ │ │ └── arguments: (length: 2) │ │ │ ├── @ SplatNode (location: (112,12)-(112,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (112,12)-(112,13) = "*" │ │ │ │ └── expression: ∅ │ │ │ └── @ IntegerNode (location: (112,17)-(112,18)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: (112,13)-(112,14) = "]" │ │ └── block: ∅ @@ -1529,11 +1556,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (112,20)-(112,23) = "end" ├── @ DefNode (location: (114,0)-(114,26)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (114,4)-(114,5) = "f" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (114,6)-(114,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: @@ -1548,9 +1577,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (114,10)-(114,21)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (114,10)-(114,21)) - │ │ ├── flags: attribute_write + │ │ ├── flags: newline, attribute_write │ │ ├── receiver: │ │ │ @ CallNode (location: (114,10)-(114,11)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -1568,16 +1598,17 @@ │ │ ├── opening_loc: (114,11)-(114,12) = "[" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (114,12)-(114,21)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_splat │ │ │ └── arguments: (length: 3) │ │ │ ├── @ IntegerNode (location: (114,12)-(114,13)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── @ SplatNode (location: (114,15)-(114,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (114,15)-(114,16) = "*" │ │ │ │ └── expression: ∅ │ │ │ └── @ IntegerNode (location: (114,20)-(114,21)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: (114,16)-(114,17) = "]" │ │ └── block: ∅ @@ -1589,11 +1620,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (114,23)-(114,26) = "end" ├── @ DefNode (location: (116,0)-(116,24)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (116,4)-(116,5) = "f" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (116,6)-(116,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: @@ -1608,9 +1641,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (116,10)-(116,19)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IndexOperatorWriteNode (location: (116,10)-(116,19)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ CallNode (location: (116,10)-(116,11)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -1626,18 +1660,19 @@ │ │ ├── opening_loc: (116,11)-(116,12) = "[" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (116,12)-(116,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_splat │ │ │ └── arguments: (length: 1) │ │ │ └── @ SplatNode (location: (116,12)-(116,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (116,12)-(116,13) = "*" │ │ │ └── expression: ∅ │ │ ├── closing_loc: (116,13)-(116,14) = "]" │ │ ├── block: ∅ - │ │ ├── operator: :+ - │ │ ├── operator_loc: (116,15)-(116,17) = "+=" + │ │ ├── binary_operator: :+ + │ │ ├── binary_operator_loc: (116,15)-(116,17) = "+=" │ │ └── value: │ │ @ IntegerNode (location: (116,18)-(116,19)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── locals: [] │ ├── def_keyword_loc: (116,0)-(116,3) = "def" @@ -1647,11 +1682,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (116,21)-(116,24) = "end" ├── @ DefNode (location: (118,0)-(118,28)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (118,4)-(118,5) = "f" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (118,6)-(118,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: @@ -1666,9 +1703,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (118,10)-(118,23)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IndexAndWriteNode (location: (118,10)-(118,23)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ CallNode (location: (118,10)-(118,11)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -1684,12 +1722,13 @@ │ │ ├── opening_loc: (118,11)-(118,12) = "[" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (118,12)-(118,16)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_splat │ │ │ └── arguments: (length: 2) │ │ │ ├── @ IntegerNode (location: (118,12)-(118,13)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── @ SplatNode (location: (118,15)-(118,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (118,15)-(118,16) = "*" │ │ │ └── expression: ∅ │ │ ├── closing_loc: (118,16)-(118,17) = "]" @@ -1697,7 +1736,7 @@ │ │ ├── operator_loc: (118,18)-(118,21) = "&&=" │ │ └── value: │ │ @ IntegerNode (location: (118,22)-(118,23)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── locals: [] │ ├── def_keyword_loc: (118,0)-(118,3) = "def" @@ -1707,11 +1746,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (118,25)-(118,28) = "end" ├── @ DefNode (location: (120,0)-(120,29)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (120,4)-(120,5) = "f" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (120,6)-(120,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: @@ -1726,10 +1767,12 @@ │ │ └── block: ∅ │ ├── body: │ │ @ BeginNode (location: (120,0)-(120,29)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (120,10)-(120,24)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (120,10)-(120,16) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: (120,17)-(120,19) = "=>" @@ -1750,15 +1793,16 @@ │ │ │ │ ├── opening_loc: (120,21)-(120,22) = "[" │ │ │ │ ├── arguments: │ │ │ │ │ @ ArgumentsNode (location: (120,22)-(120,23)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: contains_splat │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ └── @ SplatNode (location: (120,22)-(120,23)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── operator_loc: (120,22)-(120,23) = "*" │ │ │ │ │ └── expression: ∅ │ │ │ │ ├── closing_loc: (120,23)-(120,24) = "]" │ │ │ │ └── block: ∅ │ │ │ ├── statements: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (120,26)-(120,29) = "end" @@ -1770,11 +1814,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (120,26)-(120,29) = "end" └── @ DefNode (location: (122,0)-(122,32)) + ├── flags: newline ├── name: :f ├── name_loc: (122,4)-(122,5) = "f" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (122,6)-(122,7)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: @@ -1789,10 +1835,12 @@ │ └── block: ∅ ├── body: │ @ BeginNode (location: (122,0)-(122,32)) + │ ├── flags: ∅ │ ├── begin_keyword_loc: ∅ │ ├── statements: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (122,10)-(122,27)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (122,10)-(122,16) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: (122,17)-(122,19) = "=>" @@ -1813,18 +1861,19 @@ │ │ │ ├── opening_loc: (122,21)-(122,22) = "[" │ │ │ ├── arguments: │ │ │ │ @ ArgumentsNode (location: (122,22)-(122,26)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: contains_splat │ │ │ │ └── arguments: (length: 2) │ │ │ │ ├── @ IntegerNode (location: (122,22)-(122,23)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ └── @ SplatNode (location: (122,25)-(122,26)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (122,25)-(122,26) = "*" │ │ │ │ └── expression: ∅ │ │ │ ├── closing_loc: (122,26)-(122,27) = "]" │ │ │ └── block: ∅ │ │ ├── statements: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (122,29)-(122,32) = "end" diff --git a/test/prism/snapshots/begin_ensure.txt b/test/prism/snapshots/begin_ensure.txt index 9af9b9e5736..2f127cd11f8 100644 --- a/test/prism/snapshots/begin_ensure.txt +++ b/test/prism/snapshots/begin_ensure.txt @@ -1,15 +1,19 @@ @ ProgramNode (location: (1,0)-(21,15)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(21,15)) + ├── flags: ∅ └── body: (length: 5) ├── @ BeginNode (location: (1,0)-(5,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (1,0)-(1,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (2,0)-(2,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (2,0)-(2,1)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -22,12 +26,14 @@ │ ├── else_clause: ∅ │ ├── ensure_clause: │ │ @ EnsureNode (location: (3,0)-(5,3)) + │ │ ├── flags: ∅ │ │ ├── ensure_keyword_loc: (3,0)-(3,6) = "ensure" │ │ ├── statements: │ │ │ @ StatementsNode (location: (4,0)-(4,1)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (4,0)-(4,1)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -39,12 +45,14 @@ │ │ └── end_keyword_loc: (5,0)-(5,3) = "end" │ └── end_keyword_loc: (5,0)-(5,3) = "end" ├── @ BeginNode (location: (7,0)-(7,24)) + │ ├── flags: newline │ ├── begin_keyword_loc: (7,0)-(7,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (7,7)-(7,8)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (7,7)-(7,8)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -57,12 +65,14 @@ │ ├── else_clause: ∅ │ ├── ensure_clause: │ │ @ EnsureNode (location: (7,10)-(7,24)) + │ │ ├── flags: ∅ │ │ ├── ensure_keyword_loc: (7,10)-(7,16) = "ensure" │ │ ├── statements: │ │ │ @ StatementsNode (location: (7,18)-(7,19)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (7,18)-(7,19)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -74,12 +84,14 @@ │ │ └── end_keyword_loc: (7,21)-(7,24) = "end" │ └── end_keyword_loc: (7,21)-(7,24) = "end" ├── @ BeginNode (location: (9,0)-(11,4)) + │ ├── flags: newline │ ├── begin_keyword_loc: (9,0)-(9,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (9,6)-(9,7)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (9,6)-(9,7)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -92,12 +104,14 @@ │ ├── else_clause: ∅ │ ├── ensure_clause: │ │ @ EnsureNode (location: (10,1)-(11,4)) + │ │ ├── flags: ∅ │ │ ├── ensure_keyword_loc: (10,1)-(10,7) = "ensure" │ │ ├── statements: │ │ │ @ StatementsNode (location: (10,8)-(10,9)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (10,8)-(10,9)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -109,12 +123,14 @@ │ │ └── end_keyword_loc: (11,1)-(11,4) = "end" │ └── end_keyword_loc: (11,1)-(11,4) = "end" ├── @ BeginNode (location: (13,0)-(13,22)) + │ ├── flags: newline │ ├── begin_keyword_loc: (13,0)-(13,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (13,6)-(13,7)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (13,6)-(13,7)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -127,12 +143,14 @@ │ ├── else_clause: ∅ │ ├── ensure_clause: │ │ @ EnsureNode (location: (13,9)-(13,22)) + │ │ ├── flags: ∅ │ │ ├── ensure_keyword_loc: (13,9)-(13,15) = "ensure" │ │ ├── statements: │ │ │ @ StatementsNode (location: (13,16)-(13,17)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (13,16)-(13,17)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -144,20 +162,24 @@ │ │ └── end_keyword_loc: (13,19)-(13,22) = "end" │ └── end_keyword_loc: (13,19)-(13,22) = "end" └── @ BeginNode (location: (15,0)-(21,15)) + ├── flags: newline ├── begin_keyword_loc: (15,0)-(15,5) = "begin" ├── statements: │ @ StatementsNode (location: (15,6)-(21,11)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ BeginNode (location: (15,6)-(21,11)) + │ ├── flags: newline │ ├── begin_keyword_loc: (15,6)-(15,11) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (15,11)-(21,7)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (15,11)-(21,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ SymbolNode (location: (15,11)-(15,13)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (15,11)-(15,12) = ":" │ │ │ ├── value_loc: (15,12)-(15,13) = "s" │ │ │ ├── closing_loc: ∅ @@ -171,20 +193,24 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ BeginNode (location: (15,16)-(21,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── begin_keyword_loc: (15,16)-(15,21) = "begin" │ │ │ ├── statements: ∅ │ │ │ ├── rescue_clause: ∅ │ │ │ ├── else_clause: ∅ │ │ │ ├── ensure_clause: │ │ │ │ @ EnsureNode (location: (15,22)-(21,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── ensure_keyword_loc: (15,22)-(15,28) = "ensure" │ │ │ │ ├── statements: │ │ │ │ │ @ StatementsNode (location: (15,29)-(21,3)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ CallNode (location: (15,29)-(21,3)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: newline │ │ │ │ │ ├── receiver: │ │ │ │ │ │ @ ConstantReadNode (location: (15,29)-(15,35)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :Module │ │ │ │ │ ├── call_operator_loc: (15,35)-(15,36) = "." │ │ │ │ │ ├── name: :new @@ -194,31 +220,39 @@ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: │ │ │ │ │ @ BlockNode (location: (15,40)-(21,3)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── locals: [] │ │ │ │ │ ├── parameters: ∅ │ │ │ │ │ ├── body: │ │ │ │ │ │ @ StatementsNode (location: (16,2)-(20,5)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ │ └── @ BeginNode (location: (16,2)-(20,5)) + │ │ │ │ │ │ ├── flags: newline │ │ │ │ │ │ ├── begin_keyword_loc: (16,2)-(16,7) = "begin" │ │ │ │ │ │ ├── statements: │ │ │ │ │ │ │ @ StatementsNode (location: (17,4)-(17,9)) + │ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ │ │ └── @ BreakNode (location: (17,4)-(17,9)) + │ │ │ │ │ │ │ ├── flags: newline │ │ │ │ │ │ │ ├── arguments: ∅ │ │ │ │ │ │ │ └── keyword_loc: (17,4)-(17,9) = "break" │ │ │ │ │ │ ├── rescue_clause: ∅ │ │ │ │ │ │ ├── else_clause: ∅ │ │ │ │ │ │ ├── ensure_clause: │ │ │ │ │ │ │ @ EnsureNode (location: (18,4)-(20,5)) + │ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ │ ├── ensure_keyword_loc: (18,4)-(18,10) = "ensure" │ │ │ │ │ │ │ ├── statements: │ │ │ │ │ │ │ │ @ StatementsNode (location: (18,11)-(19,7)) + │ │ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ │ │ │ └── @ CallNode (location: (18,11)-(19,7)) - │ │ │ │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ │ │ │ ├── flags: newline │ │ │ │ │ │ │ │ ├── receiver: │ │ │ │ │ │ │ │ │ @ ConstantReadNode (location: (18,11)-(18,17)) + │ │ │ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ │ │ │ └── name: :Module │ │ │ │ │ │ │ │ ├── call_operator_loc: (18,17)-(18,18) = "." │ │ │ │ │ │ │ │ ├── name: :new @@ -228,6 +262,7 @@ │ │ │ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ │ │ │ └── block: │ │ │ │ │ │ │ │ @ BlockNode (location: (18,22)-(19,7)) + │ │ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ │ │ ├── locals: [] │ │ │ │ │ │ │ │ ├── parameters: ∅ │ │ │ │ │ │ │ │ ├── body: ∅ diff --git a/test/prism/snapshots/begin_rescue.txt b/test/prism/snapshots/begin_rescue.txt index f624f85c072..a3f78ec5f74 100644 --- a/test/prism/snapshots/begin_rescue.txt +++ b/test/prism/snapshots/begin_rescue.txt @@ -1,15 +1,19 @@ @ ProgramNode (location: (1,0)-(78,3)) +├── flags: ∅ ├── locals: [:ex] └── statements: @ StatementsNode (location: (1,0)-(78,3)) + ├── flags: ∅ └── body: (length: 17) ├── @ BeginNode (location: (1,0)-(1,33)) + │ ├── flags: newline │ ├── begin_keyword_loc: (1,0)-(1,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (1,7)-(1,8)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (1,7)-(1,8)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -20,15 +24,17 @@ │ │ └── block: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (1,10)-(1,19)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (1,10)-(1,16) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (1,18)-(1,19)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (1,18)-(1,19)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -37,15 +43,17 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: │ │ @ ElseNode (location: (1,21)-(1,33)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (1,21)-(1,25) = "else" │ │ ├── statements: │ │ │ @ StatementsNode (location: (1,27)-(1,28)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (1,27)-(1,28)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :c @@ -58,12 +66,14 @@ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (1,30)-(1,33) = "end" ├── @ BeginNode (location: (3,0)-(3,44)) + │ ├── flags: newline │ ├── begin_keyword_loc: (3,0)-(3,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (3,7)-(3,8)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (3,7)-(3,8)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -74,15 +84,17 @@ │ │ └── block: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (3,10)-(3,19)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (3,10)-(3,16) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (3,18)-(3,19)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (3,18)-(3,19)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -91,15 +103,17 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: │ │ @ ElseNode (location: (3,21)-(3,36)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (3,21)-(3,25) = "else" │ │ ├── statements: │ │ │ @ StatementsNode (location: (3,27)-(3,28)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (3,27)-(3,28)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :c @@ -111,12 +125,14 @@ │ │ └── end_keyword_loc: (3,30)-(3,36) = "ensure" │ ├── ensure_clause: │ │ @ EnsureNode (location: (3,30)-(3,44)) + │ │ ├── flags: ∅ │ │ ├── ensure_keyword_loc: (3,30)-(3,36) = "ensure" │ │ ├── statements: │ │ │ @ StatementsNode (location: (3,38)-(3,39)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (3,38)-(3,39)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :d @@ -128,12 +144,14 @@ │ │ └── end_keyword_loc: (3,41)-(3,44) = "end" │ └── end_keyword_loc: (3,41)-(3,44) = "end" ├── @ BeginNode (location: (5,0)-(7,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (5,0)-(5,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (6,0)-(6,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (6,0)-(6,1)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -147,12 +165,14 @@ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (7,0)-(7,3) = "end" ├── @ BeginNode (location: (9,0)-(9,13)) + │ ├── flags: newline │ ├── begin_keyword_loc: (9,0)-(9,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (9,7)-(9,8)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (9,7)-(9,8)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -166,12 +186,14 @@ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (9,10)-(9,13) = "end" ├── @ BeginNode (location: (11,0)-(12,4)) + │ ├── flags: newline │ ├── begin_keyword_loc: (11,0)-(11,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (11,6)-(11,7)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (11,6)-(11,7)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -185,12 +207,14 @@ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (12,1)-(12,4) = "end" ├── @ BeginNode (location: (14,0)-(14,12)) + │ ├── flags: newline │ ├── begin_keyword_loc: (14,0)-(14,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (14,6)-(14,7)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (14,6)-(14,7)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -204,12 +228,14 @@ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (14,9)-(14,12) = "end" ├── @ BeginNode (location: (16,0)-(24,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (16,0)-(16,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (17,0)-(17,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (17,0)-(17,1)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -220,15 +246,17 @@ │ │ └── block: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (18,0)-(23,1)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (18,0)-(18,6) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (19,0)-(19,1)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (19,0)-(19,1)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -237,17 +265,19 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: + │ │ └── subsequent: │ │ @ RescueNode (location: (20,0)-(23,1)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (20,0)-(20,6) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (21,0)-(21,1)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (21,0)-(21,1)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :c @@ -256,17 +286,19 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: + │ │ └── subsequent: │ │ @ RescueNode (location: (22,0)-(23,1)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (22,0)-(22,6) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (23,0)-(23,1)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (23,0)-(23,1)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :d @@ -275,17 +307,19 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (24,0)-(24,3) = "end" ├── @ BeginNode (location: (26,0)-(32,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (26,0)-(26,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (27,2)-(27,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (27,2)-(27,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -296,20 +330,24 @@ │ │ └── block: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (28,0)-(31,3)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (28,0)-(28,6) = "rescue" │ │ ├── exceptions: (length: 1) │ │ │ └── @ ConstantReadNode (location: (28,7)-(28,16)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Exception │ │ ├── operator_loc: (28,17)-(28,19) = "=>" │ │ ├── reference: │ │ │ @ LocalVariableTargetNode (location: (28,20)-(28,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :ex │ │ │ └── depth: 0 │ │ ├── statements: │ │ │ @ StatementsNode (location: (29,2)-(29,3)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (29,2)-(29,3)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -318,24 +356,29 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: + │ │ └── subsequent: │ │ @ RescueNode (location: (30,0)-(31,3)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (30,0)-(30,6) = "rescue" │ │ ├── exceptions: (length: 2) │ │ │ ├── @ ConstantReadNode (location: (30,7)-(30,23)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :AnotherException │ │ │ └── @ ConstantReadNode (location: (30,25)-(30,41)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :OneMoreException │ │ ├── operator_loc: (30,42)-(30,44) = "=>" │ │ ├── reference: │ │ │ @ LocalVariableTargetNode (location: (30,45)-(30,47)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :ex │ │ │ └── depth: 0 │ │ ├── statements: │ │ │ @ StatementsNode (location: (31,2)-(31,3)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (31,2)-(31,3)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :c @@ -344,17 +387,19 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (32,0)-(32,3) = "end" ├── @ BeginNode (location: (34,0)-(40,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (34,0)-(34,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (35,2)-(35,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (35,2)-(35,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -365,20 +410,24 @@ │ │ └── block: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (36,0)-(37,3)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (36,0)-(36,6) = "rescue" │ │ ├── exceptions: (length: 1) │ │ │ └── @ ConstantReadNode (location: (36,7)-(36,16)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Exception │ │ ├── operator_loc: (36,17)-(36,19) = "=>" │ │ ├── reference: │ │ │ @ LocalVariableTargetNode (location: (36,20)-(36,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :ex │ │ │ └── depth: 0 │ │ ├── statements: │ │ │ @ StatementsNode (location: (37,2)-(37,3)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (37,2)-(37,3)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -387,16 +436,18 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: │ │ @ EnsureNode (location: (38,0)-(40,3)) + │ │ ├── flags: ∅ │ │ ├── ensure_keyword_loc: (38,0)-(38,6) = "ensure" │ │ ├── statements: │ │ │ @ StatementsNode (location: (39,2)-(39,3)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (39,2)-(39,3)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -408,18 +459,20 @@ │ │ └── end_keyword_loc: (40,0)-(40,3) = "end" │ └── end_keyword_loc: (40,0)-(40,3) = "end" ├── @ StringNode (location: (42,0)-(42,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (42,0)-(42,2) = "%!" │ ├── content_loc: (42,2)-(42,5) = "abc" │ ├── closing_loc: (42,5)-(42,6) = "!" │ └── unescaped: "abc" ├── @ BeginNode (location: (44,0)-(48,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (44,0)-(44,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (45,0)-(45,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (45,0)-(45,1)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -430,15 +483,17 @@ │ │ └── block: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (46,0)-(47,1)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (46,0)-(46,6) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (47,0)-(47,1)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (47,0)-(47,1)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -447,17 +502,19 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (48,0)-(48,3) = "end" ├── @ BeginNode (location: (50,0)-(50,20)) + │ ├── flags: newline │ ├── begin_keyword_loc: (50,0)-(50,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (50,6)-(50,7)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (50,6)-(50,7)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -468,15 +525,17 @@ │ │ └── block: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (50,8)-(50,16)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (50,8)-(50,14) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (50,15)-(50,16)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (50,15)-(50,16)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -485,17 +544,19 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (50,17)-(50,20) = "end" ├── @ BeginNode (location: (52,0)-(54,5)) + │ ├── flags: newline │ ├── begin_keyword_loc: (52,0)-(52,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (53,0)-(53,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (53,0)-(53,1)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -506,15 +567,17 @@ │ │ └── block: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (53,2)-(54,1)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (53,2)-(53,8) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (54,0)-(54,1)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (54,0)-(54,1)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -523,17 +586,19 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (54,2)-(54,5) = "end" ├── @ BeginNode (location: (56,0)-(60,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (56,0)-(56,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (57,0)-(57,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (57,0)-(57,1)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -544,17 +609,20 @@ │ │ └── block: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (58,0)-(59,1)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (58,0)-(58,6) = "rescue" │ │ ├── exceptions: (length: 1) │ │ │ └── @ ConstantReadNode (location: (58,7)-(58,16)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Exception │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (59,0)-(59,1)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (59,0)-(59,1)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -563,17 +631,19 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (60,0)-(60,3) = "end" ├── @ BeginNode (location: (62,0)-(66,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (62,0)-(62,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (63,0)-(63,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (63,0)-(63,1)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -584,19 +654,23 @@ │ │ └── block: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (64,0)-(65,1)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (64,0)-(64,6) = "rescue" │ │ ├── exceptions: (length: 2) │ │ │ ├── @ ConstantReadNode (location: (64,7)-(64,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :Exception │ │ │ └── @ ConstantReadNode (location: (64,18)-(64,33)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :CustomException │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (65,0)-(65,1)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (65,0)-(65,1)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -605,17 +679,19 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (66,0)-(66,3) = "end" ├── @ BeginNode (location: (68,0)-(72,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (68,0)-(68,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (69,2)-(69,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (69,2)-(69,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -626,22 +702,27 @@ │ │ └── block: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (70,0)-(71,3)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (70,0)-(70,6) = "rescue" │ │ ├── exceptions: (length: 2) │ │ │ ├── @ ConstantReadNode (location: (70,7)-(70,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :Exception │ │ │ └── @ ConstantReadNode (location: (70,18)-(70,33)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :CustomException │ │ ├── operator_loc: (70,34)-(70,36) = "=>" │ │ ├── reference: │ │ │ @ LocalVariableTargetNode (location: (70,37)-(70,39)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :ex │ │ │ └── depth: 0 │ │ ├── statements: │ │ │ @ StatementsNode (location: (71,2)-(71,3)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (71,2)-(71,3)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -650,17 +731,19 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (72,0)-(72,3) = "end" └── @ BeginNode (location: (74,0)-(78,3)) + ├── flags: newline ├── begin_keyword_loc: (74,0)-(74,5) = "begin" ├── statements: │ @ StatementsNode (location: (75,2)-(75,3)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (75,2)-(75,3)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a @@ -671,20 +754,24 @@ │ └── block: ∅ ├── rescue_clause: │ @ RescueNode (location: (76,0)-(77,3)) + │ ├── flags: ∅ │ ├── keyword_loc: (76,0)-(76,6) = "rescue" │ ├── exceptions: (length: 1) │ │ └── @ ConstantReadNode (location: (76,7)-(76,16)) + │ │ ├── flags: ∅ │ │ └── name: :Exception │ ├── operator_loc: (76,17)-(76,19) = "=>" │ ├── reference: │ │ @ LocalVariableTargetNode (location: (76,20)-(76,22)) + │ │ ├── flags: ∅ │ │ ├── name: :ex │ │ └── depth: 0 │ ├── statements: │ │ @ StatementsNode (location: (77,2)-(77,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (77,2)-(77,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :b @@ -693,7 +780,7 @@ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ └── consequent: ∅ + │ └── subsequent: ∅ ├── else_clause: ∅ ├── ensure_clause: ∅ └── end_keyword_loc: (78,0)-(78,3) = "end" diff --git a/test/prism/snapshots/blocks.txt b/test/prism/snapshots/blocks.txt index 0b1ec52e38b..761e3bb0515 100644 --- a/test/prism/snapshots/blocks.txt +++ b/test/prism/snapshots/blocks.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(54,17)) +├── flags: ∅ ├── locals: [:fork] └── statements: @ StatementsNode (location: (1,0)-(54,17)) + ├── flags: ∅ └── body: (length: 20) ├── @ CallNode (location: (1,0)-(1,16)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (1,0)-(1,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -37,13 +39,15 @@ │ ├── closing_loc: (1,7)-(1,8) = "]" │ └── block: │ @ BlockNode (location: (1,9)-(1,16)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,11)-(1,14)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (1,11)-(1,14)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :baz @@ -55,7 +59,7 @@ │ ├── opening_loc: (1,9)-(1,10) = "{" │ └── closing_loc: (1,15)-(1,16) = "}" ├── @ CallNode (location: (3,0)-(5,3)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (3,0)-(3,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -88,13 +92,15 @@ │ ├── closing_loc: (3,7)-(3,8) = "]" │ └── block: │ @ BlockNode (location: (3,9)-(5,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (4,0)-(4,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (4,0)-(4,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :baz @@ -106,7 +112,7 @@ │ ├── opening_loc: (3,9)-(3,11) = "do" │ └── closing_loc: (5,0)-(5,3) = "end" ├── @ CallNode (location: (7,0)-(7,35)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (7,0)-(7,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -127,16 +133,19 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (7,9)-(7,10)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 0 │ ├── closing_loc: (7,10)-(7,11) = ")" │ └── block: │ @ BlockNode (location: (7,12)-(7,35)) + │ ├── flags: ∅ │ ├── locals: [:x, :memo] │ ├── parameters: │ │ @ BlockParametersNode (location: (7,14)-(7,23)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (7,15)-(7,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (7,15)-(7,16)) │ │ │ │ │ ├── flags: ∅ @@ -155,21 +164,24 @@ │ │ └── closing_loc: (7,22)-(7,23) = "|" │ ├── body: │ │ @ StatementsNode (location: (7,24)-(7,33)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableOperatorWriteNode (location: (7,24)-(7,33)) + │ │ ├── flags: newline │ │ ├── name_loc: (7,24)-(7,28) = "memo" - │ │ ├── operator_loc: (7,29)-(7,31) = "+=" + │ │ ├── binary_operator_loc: (7,29)-(7,31) = "+=" │ │ ├── value: │ │ │ @ LocalVariableReadNode (location: (7,32)-(7,33)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :x │ │ │ └── depth: 0 │ │ ├── name: :memo - │ │ ├── operator: :+ + │ │ ├── binary_operator: :+ │ │ └── depth: 0 │ ├── opening_loc: (7,12)-(7,13) = "{" │ └── closing_loc: (7,34)-(7,35) = "}" ├── @ CallNode (location: (9,0)-(9,10)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -179,13 +191,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (9,4)-(9,10)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ │ ├── opening_loc: (9,4)-(9,6) = "do" │ └── closing_loc: (9,7)-(9,10) = "end" ├── @ CallNode (location: (11,0)-(11,21)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -206,11 +219,13 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ ParenthesesNode (location: (11,9)-(11,21)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (11,10)-(11,20)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (11,10)-(11,20)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz @@ -220,6 +235,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: │ │ │ @ BlockNode (location: (11,14)-(11,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── locals: [] │ │ │ ├── parameters: ∅ │ │ │ ├── body: ∅ @@ -230,7 +246,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (13,0)-(13,14)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -253,13 +269,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (13,8)-(13,14)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ │ ├── opening_loc: (13,8)-(13,10) = "do" │ └── closing_loc: (13,11)-(13,14) = "end" ├── @ CallNode (location: (15,0)-(15,18)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -295,13 +312,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (15,12)-(15,18)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ │ ├── opening_loc: (15,12)-(15,14) = "do" │ └── closing_loc: (15,15)-(15,18) = "end" ├── @ CallNode (location: (17,0)-(18,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -311,11 +329,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (17,4)-(18,3)) + │ ├── flags: ∅ │ ├── locals: [:a] │ ├── parameters: │ │ @ BlockParametersNode (location: (17,7)-(17,17)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (17,8)-(17,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (17,8)-(17,16)) @@ -346,7 +367,7 @@ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (17,14)-(17,15)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── closing_loc: (17,15)-(17,16) = "]" │ │ │ │ └── block: ∅ @@ -362,7 +383,7 @@ │ ├── opening_loc: (17,4)-(17,6) = "do" │ └── closing_loc: (18,0)-(18,3) = "end" ├── @ CallNode (location: (20,0)-(22,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -372,27 +393,30 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (20,4)-(22,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (20,4)-(22,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (21,0)-(21,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (21,0)-(21,6) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (22,0)-(22,3) = "end" │ ├── opening_loc: (20,4)-(20,6) = "do" │ └── closing_loc: (22,0)-(22,3) = "end" ├── @ CallNode (location: (24,0)-(29,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -402,13 +426,15 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (24,4)-(29,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (25,2)-(28,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (25,2)-(28,5)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -418,13 +444,15 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (25,6)-(28,5)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (26,4)-(27,7)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (26,4)-(27,7)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz @@ -434,6 +462,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: │ │ │ @ BlockNode (location: (26,8)-(27,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── locals: [] │ │ │ ├── parameters: ∅ │ │ │ ├── body: ∅ @@ -444,7 +473,7 @@ │ ├── opening_loc: (24,4)-(24,6) = "do" │ └── closing_loc: (29,0)-(29,3) = "end" ├── @ CallNode (location: (31,0)-(31,16)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (31,0)-(31,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -477,13 +506,15 @@ │ ├── closing_loc: (31,7)-(31,8) = "]" │ └── block: │ @ BlockNode (location: (31,9)-(31,16)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (31,11)-(31,14)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (31,11)-(31,14)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :baz @@ -495,7 +526,7 @@ │ ├── opening_loc: (31,9)-(31,10) = "{" │ └── closing_loc: (31,15)-(31,16) = "}" ├── @ CallNode (location: (33,0)-(33,24)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -505,11 +536,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (33,4)-(33,24)) + │ ├── flags: ∅ │ ├── locals: [:x, :y, :z] │ ├── parameters: │ │ @ BlockParametersNode (location: (33,6)-(33,20)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (33,7)-(33,19)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (33,7)-(33,8)) │ │ │ │ ├── flags: ∅ @@ -522,7 +556,7 @@ │ │ │ │ ├── operator_loc: (33,12)-(33,13) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (33,14)-(33,15)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ ├── rest: ∅ │ │ │ ├── posts: (length: 0) @@ -538,14 +572,16 @@ │ │ └── closing_loc: (33,19)-(33,20) = "|" │ ├── body: │ │ @ StatementsNode (location: (33,21)-(33,22)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (33,21)-(33,22)) + │ │ ├── flags: newline │ │ ├── name: :x │ │ └── depth: 0 │ ├── opening_loc: (33,4)-(33,5) = "{" │ └── closing_loc: (33,23)-(33,24) = "}" ├── @ CallNode (location: (35,0)-(35,11)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -555,11 +591,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (35,4)-(35,11)) + │ ├── flags: ∅ │ ├── locals: [:x] │ ├── parameters: │ │ @ BlockParametersNode (location: (35,6)-(35,9)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (35,7)-(35,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (35,7)-(35,8)) │ │ │ │ ├── flags: ∅ @@ -577,16 +616,17 @@ │ ├── opening_loc: (35,4)-(35,5) = "{" │ └── closing_loc: (35,10)-(35,11) = "}" ├── @ LocalVariableWriteNode (location: (37,0)-(37,8)) + │ ├── flags: newline │ ├── name: :fork │ ├── depth: 0 │ ├── name_loc: (37,0)-(37,4) = "fork" │ ├── value: │ │ @ IntegerNode (location: (37,7)-(37,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (37,5)-(37,6) = "=" ├── @ CallNode (location: (38,0)-(39,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :fork @@ -596,11 +636,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (38,5)-(39,3)) + │ ├── flags: ∅ │ ├── locals: [:a] │ ├── parameters: │ │ @ BlockParametersNode (location: (38,8)-(38,11)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (38,9)-(38,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (38,9)-(38,10)) │ │ │ │ ├── flags: ∅ @@ -618,7 +661,7 @@ │ ├── opening_loc: (38,5)-(38,7) = "do" │ └── closing_loc: (39,0)-(39,3) = "end" ├── @ CallNode (location: (41,0)-(41,12)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :fork @@ -628,11 +671,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (41,5)-(41,12)) + │ ├── flags: ∅ │ ├── locals: [:a] │ ├── parameters: │ │ @ BlockParametersNode (location: (41,7)-(41,10)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (41,8)-(41,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (41,8)-(41,9)) │ │ │ │ ├── flags: ∅ @@ -650,7 +696,7 @@ │ ├── opening_loc: (41,5)-(41,6) = "{" │ └── closing_loc: (41,11)-(41,12) = "}" ├── @ CallNode (location: (43,0)-(44,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :C @@ -660,13 +706,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (43,2)-(44,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ │ ├── opening_loc: (43,2)-(43,4) = "do" │ └── closing_loc: (44,0)-(44,3) = "end" ├── @ CallNode (location: (46,0)-(46,4)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :C @@ -676,13 +723,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (46,2)-(46,4)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ │ ├── opening_loc: (46,2)-(46,3) = "{" │ └── closing_loc: (46,3)-(46,4) = "}" ├── @ CallNode (location: (48,0)-(52,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -703,11 +751,14 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (48,11)-(52,1)) + │ │ ├── flags: ∅ │ │ ├── locals: [:a, :b] │ │ ├── parameters: │ │ │ @ BlockParametersNode (location: (48,13)-(51,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── parameters: │ │ │ │ @ ParametersNode (location: (49,2)-(50,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── requireds: (length: 0) │ │ │ │ ├── optionals: (length: 0) │ │ │ │ ├── rest: ∅ @@ -719,7 +770,7 @@ │ │ │ │ │ │ ├── name_loc: (49,2)-(49,4) = "a:" │ │ │ │ │ │ └── value: │ │ │ │ │ │ @ IntegerNode (location: (49,5)-(49,6)) - │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ │ └── value: 1 │ │ │ │ │ └── @ OptionalKeywordParameterNode (location: (50,2)-(50,6)) │ │ │ │ │ ├── flags: ∅ @@ -727,7 +778,7 @@ │ │ │ │ │ ├── name_loc: (50,2)-(50,4) = "b:" │ │ │ │ │ └── value: │ │ │ │ │ @ IntegerNode (location: (50,5)-(50,6)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 2 │ │ │ │ ├── keyword_rest: ∅ │ │ │ │ └── block: ∅ @@ -740,7 +791,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ └── @ CallNode (location: (54,0)-(54,17)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :foo @@ -750,11 +801,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (54,4)-(54,17)) + ├── flags: ∅ ├── locals: [:bar] ├── parameters: │ @ BlockParametersNode (location: (54,7)-(54,13)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (54,8)-(54,12)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (54,8)-(54,11)) │ │ │ ├── flags: ∅ @@ -762,6 +816,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ ImplicitRestNode (location: (54,11)-(54,12)) + │ │ │ └── flags: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/boolean_operators.txt b/test/prism/snapshots/boolean_operators.txt index ace8047e18d..bde70d65090 100644 --- a/test/prism/snapshots/boolean_operators.txt +++ b/test/prism/snapshots/boolean_operators.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(5,7)) +├── flags: ∅ ├── locals: [:a] └── statements: @ StatementsNode (location: (1,0)-(5,7)) + ├── flags: ∅ └── body: (length: 3) ├── @ LocalVariableAndWriteNode (location: (1,0)-(1,7)) + │ ├── flags: newline │ ├── name_loc: (1,0)-(1,1) = "a" │ ├── operator_loc: (1,2)-(1,5) = "&&=" │ ├── value: @@ -20,8 +23,9 @@ │ ├── name: :a │ └── depth: 0 ├── @ LocalVariableOperatorWriteNode (location: (3,0)-(3,6)) + │ ├── flags: newline │ ├── name_loc: (3,0)-(3,1) = "a" - │ ├── operator_loc: (3,2)-(3,4) = "+=" + │ ├── binary_operator_loc: (3,2)-(3,4) = "+=" │ ├── value: │ │ @ CallNode (location: (3,5)-(3,6)) │ │ ├── flags: variable_call, ignore_visibility @@ -34,9 +38,10 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── name: :a - │ ├── operator: :+ + │ ├── binary_operator: :+ │ └── depth: 0 └── @ LocalVariableOrWriteNode (location: (5,0)-(5,7)) + ├── flags: newline ├── name_loc: (5,0)-(5,1) = "a" ├── operator_loc: (5,2)-(5,5) = "||=" ├── value: diff --git a/test/prism/snapshots/booleans.txt b/test/prism/snapshots/booleans.txt index 47319662439..47ce80217a0 100644 --- a/test/prism/snapshots/booleans.txt +++ b/test/prism/snapshots/booleans.txt @@ -1,7 +1,11 @@ @ ProgramNode (location: (1,0)-(3,4)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,4)) + ├── flags: ∅ └── body: (length: 2) ├── @ FalseNode (location: (1,0)-(1,5)) + │ └── flags: newline, static_literal └── @ TrueNode (location: (3,0)-(3,4)) + └── flags: newline, static_literal diff --git a/test/prism/snapshots/break.txt b/test/prism/snapshots/break.txt index c15a9e4675f..469b603f849 100644 --- a/test/prism/snapshots/break.txt +++ b/test/prism/snapshots/break.txt @@ -1,10 +1,12 @@ -@ ProgramNode (location: (1,0)-(25,23)) +@ ProgramNode (location: (1,0)-(29,21)) +├── flags: ∅ ├── locals: [] └── statements: - @ StatementsNode (location: (1,0)-(25,23)) - └── body: (length: 11) + @ StatementsNode (location: (1,0)-(29,21)) + ├── flags: ∅ + └── body: (length: 13) ├── @ CallNode (location: (1,0)-(1,13)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -14,18 +16,21 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (1,4)-(1,13)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,6)-(1,11)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ BreakNode (location: (1,6)-(1,11)) + │ │ ├── flags: newline │ │ ├── arguments: ∅ │ │ └── keyword_loc: (1,6)-(1,11) = "break" │ ├── opening_loc: (1,4)-(1,5) = "{" │ └── closing_loc: (1,12)-(1,13) = "}" ├── @ CallNode (location: (3,0)-(3,27)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -35,40 +40,49 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (3,4)-(3,27)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (3,6)-(3,25)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ BreakNode (location: (3,6)-(3,25)) + │ │ ├── flags: newline │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (3,12)-(3,25)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 3) │ │ │ ├── @ ParenthesesNode (location: (3,12)-(3,15)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── body: │ │ │ │ │ @ StatementsNode (location: (3,13)-(3,14)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (3,13)-(3,14)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── opening_loc: (3,12)-(3,13) = "(" │ │ │ │ └── closing_loc: (3,14)-(3,15) = ")" │ │ │ ├── @ ParenthesesNode (location: (3,17)-(3,20)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── body: │ │ │ │ │ @ StatementsNode (location: (3,18)-(3,19)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (3,18)-(3,19)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ │ └── value: 2 │ │ │ │ ├── opening_loc: (3,17)-(3,18) = "(" │ │ │ │ └── closing_loc: (3,19)-(3,20) = ")" │ │ │ └── @ ParenthesesNode (location: (3,22)-(3,25)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (3,23)-(3,24)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (3,23)-(3,24)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ └── value: 3 │ │ │ ├── opening_loc: (3,22)-(3,23) = "(" │ │ │ └── closing_loc: (3,24)-(3,25) = ")" @@ -76,7 +90,7 @@ │ ├── opening_loc: (3,4)-(3,5) = "{" │ └── closing_loc: (3,26)-(3,27) = "}" ├── @ CallNode (location: (5,0)-(5,15)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -86,24 +100,27 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (5,4)-(5,15)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (5,6)-(5,13)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ BreakNode (location: (5,6)-(5,13)) + │ │ ├── flags: newline │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (5,12)-(5,13)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (5,12)-(5,13)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── keyword_loc: (5,6)-(5,11) = "break" │ ├── opening_loc: (5,4)-(5,5) = "{" │ └── closing_loc: (5,14)-(5,15) = "}" ├── @ CallNode (location: (7,0)-(8,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -113,30 +130,33 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (7,4)-(8,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (7,6)-(8,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ BreakNode (location: (7,6)-(8,1)) + │ │ ├── flags: newline │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (7,12)-(8,1)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 3) │ │ │ ├── @ IntegerNode (location: (7,12)-(7,13)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── @ IntegerNode (location: (7,15)-(7,16)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ └── @ IntegerNode (location: (8,0)-(8,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ └── keyword_loc: (7,6)-(7,11) = "break" │ ├── opening_loc: (7,4)-(7,5) = "{" │ └── closing_loc: (8,2)-(8,3) = "}" ├── @ CallNode (location: (10,0)-(10,21)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -146,30 +166,33 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (10,4)-(10,21)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (10,6)-(10,19)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ BreakNode (location: (10,6)-(10,19)) + │ │ ├── flags: newline │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (10,12)-(10,19)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 3) │ │ │ ├── @ IntegerNode (location: (10,12)-(10,13)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── @ IntegerNode (location: (10,15)-(10,16)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ └── @ IntegerNode (location: (10,18)-(10,19)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ └── keyword_loc: (10,6)-(10,11) = "break" │ ├── opening_loc: (10,4)-(10,5) = "{" │ └── closing_loc: (10,20)-(10,21) = "}" ├── @ CallNode (location: (12,0)-(12,23)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -179,27 +202,30 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (12,4)-(12,23)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (12,6)-(12,21)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ BreakNode (location: (12,6)-(12,21)) + │ │ ├── flags: newline │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (12,12)-(12,21)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ ArrayNode (location: (12,12)-(12,21)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: static_literal │ │ │ ├── elements: (length: 3) │ │ │ │ ├── @ IntegerNode (location: (12,13)-(12,14)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── @ IntegerNode (location: (12,16)-(12,17)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 2 │ │ │ │ └── @ IntegerNode (location: (12,19)-(12,20)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 3 │ │ │ ├── opening_loc: (12,12)-(12,13) = "[" │ │ │ └── closing_loc: (12,20)-(12,21) = "]" @@ -207,7 +233,7 @@ │ ├── opening_loc: (12,4)-(12,5) = "{" │ └── closing_loc: (12,22)-(12,23) = "}" ├── @ CallNode (location: (14,0)-(17,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -217,25 +243,30 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (14,4)-(17,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (14,6)-(17,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ BreakNode (location: (14,6)-(17,1)) + │ │ ├── flags: newline │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (14,11)-(17,1)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ ParenthesesNode (location: (14,11)-(17,1)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (15,2)-(16,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 2) │ │ │ │ ├── @ IntegerNode (location: (15,2)-(15,3)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ └── @ IntegerNode (location: (16,2)-(16,3)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ └── value: 2 │ │ │ ├── opening_loc: (14,11)-(14,12) = "(" │ │ │ └── closing_loc: (17,0)-(17,1) = ")" @@ -243,7 +274,7 @@ │ ├── opening_loc: (14,4)-(14,5) = "{" │ └── closing_loc: (17,2)-(17,3) = "}" ├── @ CallNode (location: (19,0)-(19,15)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -253,17 +284,21 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (19,4)-(19,15)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (19,6)-(19,13)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ BreakNode (location: (19,6)-(19,13)) + │ │ ├── flags: newline │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (19,11)-(19,13)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ ParenthesesNode (location: (19,11)-(19,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: ∅ │ │ │ ├── opening_loc: (19,11)-(19,12) = "(" │ │ │ └── closing_loc: (19,12)-(19,13) = ")" @@ -271,7 +306,7 @@ │ ├── opening_loc: (19,4)-(19,5) = "{" │ └── closing_loc: (19,14)-(19,15) = "}" ├── @ CallNode (location: (21,0)-(21,16)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -281,22 +316,27 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (21,4)-(21,16)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (21,6)-(21,14)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ BreakNode (location: (21,6)-(21,14)) + │ │ ├── flags: newline │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (21,11)-(21,14)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ ParenthesesNode (location: (21,11)-(21,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (21,12)-(21,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (21,12)-(21,13)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── opening_loc: (21,11)-(21,12) = "(" │ │ │ └── closing_loc: (21,13)-(21,14) = ")" @@ -304,7 +344,7 @@ │ ├── opening_loc: (21,4)-(21,5) = "{" │ └── closing_loc: (21,15)-(21,16) = "}" ├── @ CallNode (location: (23,0)-(23,22)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (23,0)-(23,16)) │ │ ├── flags: ignore_visibility @@ -317,18 +357,21 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (23,4)-(23,16)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (23,6)-(23,14)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ BreakNode (location: (23,6)-(23,14)) + │ │ │ ├── flags: newline │ │ │ ├── arguments: │ │ │ │ @ ArgumentsNode (location: (23,12)-(23,14)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (23,12)-(23,14)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 42 │ │ │ └── keyword_loc: (23,6)-(23,11) = "break" │ │ ├── opening_loc: (23,4)-(23,5) = "{" @@ -342,60 +385,115 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (23,20)-(23,22)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal + │ │ └── value: 42 + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (25,0)-(25,23)) + │ ├── flags: newline + │ ├── receiver: + │ │ @ CallNode (location: (25,0)-(25,17)) + │ │ ├── flags: ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :foo + │ │ ├── message_loc: (25,0)-(25,3) = "foo" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: + │ │ @ BlockNode (location: (25,4)-(25,17)) + │ │ ├── flags: ∅ + │ │ ├── locals: [:a] + │ │ ├── parameters: + │ │ │ @ BlockParametersNode (location: (25,6)-(25,9)) + │ │ │ ├── flags: ∅ + │ │ │ ├── parameters: + │ │ │ │ @ ParametersNode (location: (25,7)-(25,8)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── requireds: (length: 1) + │ │ │ │ │ └── @ RequiredParameterNode (location: (25,7)-(25,8)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ └── name: :a + │ │ │ │ ├── optionals: (length: 0) + │ │ │ │ ├── rest: ∅ + │ │ │ │ ├── posts: (length: 0) + │ │ │ │ ├── keywords: (length: 0) + │ │ │ │ ├── keyword_rest: ∅ + │ │ │ │ └── block: ∅ + │ │ │ ├── locals: (length: 0) + │ │ │ ├── opening_loc: (25,6)-(25,7) = "|" + │ │ │ └── closing_loc: (25,8)-(25,9) = "|" + │ │ ├── body: + │ │ │ @ StatementsNode (location: (25,10)-(25,15)) + │ │ │ ├── flags: ∅ + │ │ │ └── body: (length: 1) + │ │ │ └── @ BreakNode (location: (25,10)-(25,15)) + │ │ │ ├── flags: newline + │ │ │ ├── arguments: ∅ + │ │ │ └── keyword_loc: (25,10)-(25,15) = "break" + │ │ ├── opening_loc: (25,4)-(25,5) = "{" + │ │ └── closing_loc: (25,16)-(25,17) = "}" + │ ├── call_operator_loc: ∅ + │ ├── name: :== + │ ├── message_loc: (25,18)-(25,20) = "==" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (25,21)-(25,23)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ IntegerNode (location: (25,21)-(25,23)) + │ │ ├── flags: static_literal, decimal │ │ └── value: 42 │ ├── closing_loc: ∅ │ └── block: ∅ - └── @ CallNode (location: (25,0)-(25,23)) - ├── flags: ∅ - ├── receiver: - │ @ CallNode (location: (25,0)-(25,17)) - │ ├── flags: ignore_visibility - │ ├── receiver: ∅ - │ ├── call_operator_loc: ∅ - │ ├── name: :foo - │ ├── message_loc: (25,0)-(25,3) = "foo" - │ ├── opening_loc: ∅ - │ ├── arguments: ∅ - │ ├── closing_loc: ∅ - │ └── block: - │ @ BlockNode (location: (25,4)-(25,17)) - │ ├── locals: [:a] - │ ├── parameters: - │ │ @ BlockParametersNode (location: (25,6)-(25,9)) - │ │ ├── parameters: - │ │ │ @ ParametersNode (location: (25,7)-(25,8)) - │ │ │ ├── requireds: (length: 1) - │ │ │ │ └── @ RequiredParameterNode (location: (25,7)-(25,8)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ └── name: :a - │ │ │ ├── optionals: (length: 0) - │ │ │ ├── rest: ∅ - │ │ │ ├── posts: (length: 0) - │ │ │ ├── keywords: (length: 0) - │ │ │ ├── keyword_rest: ∅ - │ │ │ └── block: ∅ - │ │ ├── locals: (length: 0) - │ │ ├── opening_loc: (25,6)-(25,7) = "|" - │ │ └── closing_loc: (25,8)-(25,9) = "|" - │ ├── body: - │ │ @ StatementsNode (location: (25,10)-(25,15)) - │ │ └── body: (length: 1) - │ │ └── @ BreakNode (location: (25,10)-(25,15)) - │ │ ├── arguments: ∅ - │ │ └── keyword_loc: (25,10)-(25,15) = "break" - │ ├── opening_loc: (25,4)-(25,5) = "{" - │ └── closing_loc: (25,16)-(25,17) = "}" - ├── call_operator_loc: ∅ - ├── name: :== - ├── message_loc: (25,18)-(25,20) = "==" - ├── opening_loc: ∅ - ├── arguments: - │ @ ArgumentsNode (location: (25,21)-(25,23)) + ├── @ WhileNode (location: (27,0)-(27,21)) + │ ├── flags: newline + │ ├── keyword_loc: (27,0)-(27,5) = "while" + │ ├── closing_loc: (27,18)-(27,21) = "end" + │ ├── predicate: + │ │ @ AndNode (location: (27,6)-(27,16)) + │ │ ├── flags: ∅ + │ │ ├── left: + │ │ │ @ CallNode (location: (27,6)-(27,7)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :_ + │ │ │ ├── message_loc: (27,6)-(27,7) = "_" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── right: + │ │ │ @ BreakNode (location: (27,11)-(27,16)) + │ │ │ ├── flags: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ └── keyword_loc: (27,11)-(27,16) = "break" + │ │ └── operator_loc: (27,8)-(27,10) = "&&" + │ └── statements: ∅ + └── @ UntilNode (location: (29,0)-(29,21)) + ├── flags: newline + ├── keyword_loc: (29,0)-(29,5) = "until" + ├── closing_loc: (29,18)-(29,21) = "end" + ├── predicate: + │ @ AndNode (location: (29,6)-(29,16)) │ ├── flags: ∅ - │ └── arguments: (length: 1) - │ └── @ IntegerNode (location: (25,21)-(25,23)) - │ ├── flags: decimal - │ └── value: 42 - ├── closing_loc: ∅ - └── block: ∅ + │ ├── left: + │ │ @ CallNode (location: (29,6)-(29,7)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :_ + │ │ ├── message_loc: (29,6)-(29,7) = "_" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ ├── right: + │ │ @ BreakNode (location: (29,11)-(29,16)) + │ │ ├── flags: ∅ + │ │ ├── arguments: ∅ + │ │ └── keyword_loc: (29,11)-(29,16) = "break" + │ └── operator_loc: (29,8)-(29,10) = "&&" + └── statements: ∅ diff --git a/test/prism/snapshots/case.txt b/test/prism/snapshots/case.txt index 417bf9492a4..3afc25826c8 100644 --- a/test/prism/snapshots/case.txt +++ b/test/prism/snapshots/case.txt @@ -1,45 +1,54 @@ @ ProgramNode (location: (1,0)-(55,3)) +├── flags: ∅ ├── locals: [:b] └── statements: @ StatementsNode (location: (1,0)-(55,3)) + ├── flags: ∅ └── body: (length: 15) ├── @ CaseNode (location: (1,0)-(3,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (1,5)-(1,8)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,5)-(1,6) = ":" │ │ ├── value_loc: (1,6)-(1,8) = "hi" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "hi" │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (2,0)-(2,8)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (2,0)-(2,4) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ SymbolNode (location: (2,5)-(2,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (2,5)-(2,6) = ":" │ │ │ ├── value_loc: (2,6)-(2,8) = "hi" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "hi" │ │ ├── then_keyword_loc: ∅ │ │ └── statements: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (1,0)-(1,4) = "case" │ └── end_keyword_loc: (3,0)-(3,3) = "end" ├── @ CaseNode (location: (5,0)-(5,58)) + │ ├── flags: newline │ ├── predicate: │ │ @ TrueNode (location: (5,5)-(5,9)) + │ │ └── flags: static_literal │ ├── conditions: (length: 2) │ │ ├── @ WhenNode (location: (5,11)-(5,30)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (5,11)-(5,15) = "when" │ │ │ ├── conditions: (length: 1) │ │ │ │ └── @ TrueNode (location: (5,16)-(5,20)) + │ │ │ │ └── flags: static_literal │ │ │ ├── then_keyword_loc: ∅ │ │ │ └── statements: │ │ │ @ StatementsNode (location: (5,22)-(5,30)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (5,22)-(5,30)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :puts @@ -50,7 +59,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ SymbolNode (location: (5,27)-(5,30)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (5,27)-(5,28) = ":" │ │ │ │ ├── value_loc: (5,28)-(5,30) = "hi" │ │ │ │ ├── closing_loc: ∅ @@ -58,15 +67,18 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ WhenNode (location: (5,32)-(5,53)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (5,32)-(5,36) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ FalseNode (location: (5,37)-(5,42)) + │ │ │ └── flags: static_literal │ │ ├── then_keyword_loc: ∅ │ │ └── statements: │ │ @ StatementsNode (location: (5,44)-(5,53)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (5,44)-(5,53)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :puts @@ -77,23 +89,26 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ SymbolNode (location: (5,49)-(5,53)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (5,49)-(5,50) = ":" │ │ │ ├── value_loc: (5,50)-(5,53) = "bye" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "bye" │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (5,0)-(5,4) = "case" │ └── end_keyword_loc: (5,55)-(5,58) = "end" ├── @ CaseNode (location: (7,0)-(7,20)) + │ ├── flags: newline │ ├── predicate: ∅ │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (7,6)-(7,15)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (7,6)-(7,10) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ SplatNode (location: (7,11)-(7,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (7,11)-(7,12) = "*" │ │ │ └── expression: │ │ │ @ CallNode (location: (7,12)-(7,15)) @@ -108,37 +123,41 @@ │ │ │ └── block: ∅ │ │ ├── then_keyword_loc: ∅ │ │ └── statements: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (7,0)-(7,4) = "case" │ └── end_keyword_loc: (7,17)-(7,20) = "end" ├── @ CaseNode (location: (9,0)-(13,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (9,5)-(9,8)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (9,5)-(9,6) = ":" │ │ ├── value_loc: (9,6)-(9,8) = "hi" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "hi" │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (10,0)-(10,8)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (10,0)-(10,4) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ SymbolNode (location: (10,5)-(10,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (10,5)-(10,6) = ":" │ │ │ ├── value_loc: (10,6)-(10,8) = "hi" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "hi" │ │ ├── then_keyword_loc: ∅ │ │ └── statements: ∅ - │ ├── consequent: + │ ├── else_clause: │ │ @ ElseNode (location: (11,0)-(13,3)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (11,0)-(11,4) = "else" │ │ ├── statements: │ │ │ @ StatementsNode (location: (12,0)-(12,2)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (12,0)-(12,2)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (12,0)-(12,1) = ":" │ │ │ ├── value_loc: (12,1)-(12,2) = "b" │ │ │ ├── closing_loc: ∅ @@ -147,6 +166,7 @@ │ ├── case_keyword_loc: (9,0)-(9,4) = "case" │ └── end_keyword_loc: (13,0)-(13,3) = "end" ├── @ CaseNode (location: (15,0)-(15,36)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (15,5)-(15,9)) │ │ ├── flags: variable_call, ignore_visibility @@ -160,21 +180,26 @@ │ │ └── block: ∅ │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (15,11)-(15,31)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (15,11)-(15,15) = "when" │ │ ├── conditions: (length: 2) │ │ │ ├── @ ConstantReadNode (location: (15,16)-(15,22)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :FooBar │ │ │ └── @ ConstantReadNode (location: (15,24)-(15,31)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :BazBonk │ │ ├── then_keyword_loc: ∅ │ │ └── statements: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (15,0)-(15,4) = "case" │ └── end_keyword_loc: (15,33)-(15,36) = "end" ├── @ CaseNode (location: (17,0)-(19,3)) + │ ├── flags: newline │ ├── predicate: ∅ │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (18,0)-(18,15)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (18,0)-(18,4) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ CallNode (location: (18,5)-(18,15)) @@ -212,13 +237,15 @@ │ │ │ └── block: ∅ │ │ ├── then_keyword_loc: ∅ │ │ └── statements: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (17,0)-(17,4) = "case" │ └── end_keyword_loc: (19,0)-(19,3) = "end" ├── @ CaseNode (location: (21,0)-(25,3)) + │ ├── flags: newline │ ├── predicate: ∅ │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (22,0)-(22,6)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (22,0)-(22,4) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ CallNode (location: (22,5)-(22,6)) @@ -233,14 +260,16 @@ │ │ │ └── block: ∅ │ │ ├── then_keyword_loc: ∅ │ │ └── statements: ∅ - │ ├── consequent: + │ ├── else_clause: │ │ @ ElseNode (location: (23,0)-(25,3)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (23,0)-(23,4) = "else" │ │ ├── statements: ∅ │ │ └── end_keyword_loc: (25,0)-(25,3) = "end" │ ├── case_keyword_loc: (21,0)-(21,4) = "case" │ └── end_keyword_loc: (25,0)-(25,3) = "end" ├── @ CaseNode (location: (27,0)-(30,6)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (27,5)-(27,9)) │ │ ├── flags: variable_call, ignore_visibility @@ -254,134 +283,151 @@ │ │ └── block: ∅ │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (28,3)-(28,10)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (28,3)-(28,7) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ SymbolNode (location: (28,8)-(28,10)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (28,8)-(28,9) = ":" │ │ │ ├── value_loc: (28,9)-(28,10) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" │ │ ├── then_keyword_loc: ∅ │ │ └── statements: ∅ - │ ├── consequent: + │ ├── else_clause: │ │ @ ElseNode (location: (29,5)-(30,6)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (29,5)-(29,9) = "else" │ │ ├── statements: ∅ │ │ └── end_keyword_loc: (30,3)-(30,6) = "end" │ ├── case_keyword_loc: (27,0)-(27,4) = "case" │ └── end_keyword_loc: (30,3)-(30,6) = "end" ├── @ CaseNode (location: (32,0)-(32,25)) + │ ├── flags: newline │ ├── predicate: ∅ │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (32,14)-(32,20)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (32,14)-(32,18) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ IntegerNode (location: (32,19)-(32,20)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── then_keyword_loc: ∅ │ │ └── statements: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (32,0)-(32,4) = "case" │ └── end_keyword_loc: (32,22)-(32,25) = "end" ├── @ CaseNode (location: (34,0)-(36,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ MatchPredicateNode (location: (34,5)-(34,11)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ IntegerNode (location: (34,5)-(34,6)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── pattern: │ │ │ @ IntegerNode (location: (34,10)-(34,11)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: (34,7)-(34,9) = "in" │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (35,0)-(35,6)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (35,0)-(35,4) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ IntegerNode (location: (35,5)-(35,6)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ ├── then_keyword_loc: ∅ │ │ └── statements: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (34,0)-(34,4) = "case" │ └── end_keyword_loc: (36,0)-(36,3) = "end" ├── @ CaseNode (location: (38,0)-(38,24)) + │ ├── flags: newline │ ├── predicate: │ │ @ MatchPredicateNode (location: (38,5)-(38,11)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ IntegerNode (location: (38,5)-(38,6)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── pattern: │ │ │ @ IntegerNode (location: (38,10)-(38,11)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: (38,7)-(38,9) = "in" │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (38,13)-(38,19)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (38,13)-(38,17) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ IntegerNode (location: (38,18)-(38,19)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ ├── then_keyword_loc: ∅ │ │ └── statements: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (38,0)-(38,4) = "case" │ └── end_keyword_loc: (38,21)-(38,24) = "end" ├── @ CaseMatchNode (location: (40,0)-(42,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ MatchPredicateNode (location: (40,5)-(40,11)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ IntegerNode (location: (40,5)-(40,6)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── pattern: │ │ │ @ IntegerNode (location: (40,10)-(40,11)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: (40,7)-(40,9) = "in" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (41,0)-(41,4)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ IntegerNode (location: (41,3)-(41,4)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ ├── statements: ∅ │ │ ├── in_loc: (41,0)-(41,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (40,0)-(40,4) = "case" │ └── end_keyword_loc: (42,0)-(42,3) = "end" ├── @ CaseMatchNode (location: (44,0)-(44,22)) + │ ├── flags: newline │ ├── predicate: │ │ @ MatchPredicateNode (location: (44,5)-(44,11)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ IntegerNode (location: (44,5)-(44,6)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── pattern: │ │ │ @ IntegerNode (location: (44,10)-(44,11)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: (44,7)-(44,9) = "in" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (44,13)-(44,17)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ IntegerNode (location: (44,16)-(44,17)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ ├── statements: ∅ │ │ ├── in_loc: (44,13)-(44,15) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (44,0)-(44,4) = "case" │ └── end_keyword_loc: (44,19)-(44,22) = "end" ├── @ CaseMatchNode (location: (46,0)-(49,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (46,5)-(46,6)) │ │ ├── flags: variable_call, ignore_visibility @@ -395,11 +441,14 @@ │ │ └── block: ∅ │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (47,0)-(48,3)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ IfNode (location: (47,3)-(47,15)) + │ │ │ ├── flags: newline │ │ │ ├── if_keyword_loc: (47,5)-(47,7) = "if" │ │ │ ├── predicate: │ │ │ │ @ AndNode (location: (47,8)-(47,15)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── left: │ │ │ │ │ @ CallNode (location: (47,8)-(47,9)) │ │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -426,17 +475,20 @@ │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (47,3)-(47,4)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ LocalVariableTargetNode (location: (47,3)-(47,4)) + │ │ │ │ ├── flags: newline │ │ │ │ ├── name: :b │ │ │ │ └── depth: 0 - │ │ │ ├── consequent: ∅ + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (48,2)-(48,3)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (48,2)-(48,3)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :e @@ -447,14 +499,14 @@ │ │ │ └── block: ∅ │ │ ├── in_loc: (47,0)-(47,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (46,0)-(46,4) = "case" │ └── end_keyword_loc: (49,0)-(49,3) = "end" └── @ CallNode (location: (51,0)-(55,3)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (51,0)-(51,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: (51,1)-(51,2) = "." ├── name: :then @@ -464,31 +516,38 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (51,7)-(55,3)) + ├── flags: ∅ ├── locals: [:_1] ├── parameters: │ @ NumberedParametersNode (location: (51,7)-(55,3)) + │ ├── flags: ∅ │ └── maximum: 1 ├── body: │ @ StatementsNode (location: (52,2)-(54,5)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CaseMatchNode (location: (52,2)-(54,5)) + │ ├── flags: newline │ ├── predicate: │ │ @ IntegerNode (location: (52,7)-(52,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (53,2)-(53,8)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ PinnedVariableNode (location: (53,5)-(53,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── variable: │ │ │ │ @ LocalVariableReadNode (location: (53,6)-(53,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :_1 │ │ │ │ └── depth: 0 │ │ │ └── operator_loc: (53,5)-(53,6) = "^" │ │ ├── statements: ∅ │ │ ├── in_loc: (53,2)-(53,4) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (52,2)-(52,6) = "case" │ └── end_keyword_loc: (54,2)-(54,5) = "end" ├── opening_loc: (51,7)-(51,9) = "do" diff --git a/test/prism/snapshots/classes.txt b/test/prism/snapshots/classes.txt index 4a36bd5cdc4..11ba921df5e 100644 --- a/test/prism/snapshots/classes.txt +++ b/test/prism/snapshots/classes.txt @@ -1,46 +1,56 @@ @ ProgramNode (location: (1,0)-(35,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(35,3)) + ├── flags: ∅ └── body: (length: 14) ├── @ ClassNode (location: (1,0)-(1,17)) + │ ├── flags: newline │ ├── locals: [:a] │ ├── class_keyword_loc: (1,0)-(1,5) = "class" │ ├── constant_path: │ │ @ ConstantReadNode (location: (1,6)-(1,7)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── inheritance_operator_loc: ∅ │ ├── superclass: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,8)-(1,13)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableWriteNode (location: (1,8)-(1,13)) + │ │ ├── flags: newline │ │ ├── name: :a │ │ ├── depth: 0 │ │ ├── name_loc: (1,8)-(1,9) = "a" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,12)-(1,13)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── operator_loc: (1,10)-(1,11) = "=" │ ├── end_keyword_loc: (1,14)-(1,17) = "end" │ └── name: :A ├── @ ClassNode (location: (3,0)-(3,20)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (3,0)-(3,5) = "class" │ ├── constant_path: │ │ @ ConstantReadNode (location: (3,6)-(3,7)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── inheritance_operator_loc: ∅ │ ├── superclass: ∅ │ ├── body: │ │ @ BeginNode (location: (3,0)-(3,20)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── rescue_clause: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: │ │ │ @ EnsureNode (location: (3,9)-(3,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── ensure_keyword_loc: (3,9)-(3,15) = "ensure" │ │ │ ├── statements: ∅ │ │ │ └── end_keyword_loc: (3,17)-(3,20) = "end" @@ -48,32 +58,38 @@ │ ├── end_keyword_loc: (3,17)-(3,20) = "end" │ └── name: :A ├── @ ClassNode (location: (5,0)-(5,34)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (5,0)-(5,5) = "class" │ ├── constant_path: │ │ @ ConstantReadNode (location: (5,6)-(5,7)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── inheritance_operator_loc: ∅ │ ├── superclass: ∅ │ ├── body: │ │ @ BeginNode (location: (5,0)-(5,34)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (5,9)-(5,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (5,9)-(5,15) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: │ │ │ @ ElseNode (location: (5,17)-(5,29)) + │ │ │ ├── flags: ∅ │ │ │ ├── else_keyword_loc: (5,17)-(5,21) = "else" │ │ │ ├── statements: ∅ │ │ │ └── end_keyword_loc: (5,23)-(5,29) = "ensure" │ │ ├── ensure_clause: │ │ │ @ EnsureNode (location: (5,23)-(5,34)) + │ │ │ ├── flags: ∅ │ │ │ ├── ensure_keyword_loc: (5,23)-(5,29) = "ensure" │ │ │ ├── statements: ∅ │ │ │ └── end_keyword_loc: (5,31)-(5,34) = "end" @@ -81,30 +97,36 @@ │ ├── end_keyword_loc: (5,31)-(5,34) = "end" │ └── name: :A ├── @ ClassNode (location: (7,0)-(9,3)) + │ ├── flags: newline │ ├── locals: [:a] │ ├── class_keyword_loc: (7,0)-(7,5) = "class" │ ├── constant_path: │ │ @ ConstantReadNode (location: (7,6)-(7,7)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── inheritance_operator_loc: (7,8)-(7,9) = "<" │ ├── superclass: │ │ @ ConstantReadNode (location: (7,10)-(7,11)) + │ │ ├── flags: ∅ │ │ └── name: :B │ ├── body: │ │ @ StatementsNode (location: (8,0)-(8,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableWriteNode (location: (8,0)-(8,5)) + │ │ ├── flags: newline │ │ ├── name: :a │ │ ├── depth: 0 │ │ ├── name_loc: (8,0)-(8,1) = "a" │ │ ├── value: │ │ │ @ IntegerNode (location: (8,4)-(8,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── operator_loc: (8,2)-(8,3) = "=" │ ├── end_keyword_loc: (9,0)-(9,3) = "end" │ └── name: :A ├── @ SingletonClassNode (location: (11,0)-(12,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (11,0)-(11,5) = "class" │ ├── operator_loc: (11,6)-(11,8) = "<<" @@ -132,30 +154,37 @@ │ ├── body: ∅ │ └── end_keyword_loc: (12,0)-(12,3) = "end" ├── @ ClassNode (location: (14,0)-(14,40)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (14,0)-(14,5) = "class" │ ├── constant_path: │ │ @ ConstantReadNode (location: (14,6)-(14,7)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── inheritance_operator_loc: ∅ │ ├── superclass: ∅ │ ├── body: │ │ @ StatementsNode (location: (14,9)-(14,35)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SingletonClassNode (location: (14,9)-(14,35)) + │ │ ├── flags: newline │ │ ├── locals: [] │ │ ├── class_keyword_loc: (14,9)-(14,14) = "class" │ │ ├── operator_loc: (14,15)-(14,17) = "<<" │ │ ├── expression: │ │ │ @ SelfNode (location: (14,18)-(14,22)) + │ │ │ └── flags: ∅ │ │ ├── body: │ │ │ @ BeginNode (location: (14,9)-(14,35)) + │ │ │ ├── flags: ∅ │ │ │ ├── begin_keyword_loc: ∅ │ │ │ ├── statements: ∅ │ │ │ ├── rescue_clause: ∅ │ │ │ ├── else_clause: ∅ │ │ │ ├── ensure_clause: │ │ │ │ @ EnsureNode (location: (14,24)-(14,35)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── ensure_keyword_loc: (14,24)-(14,30) = "ensure" │ │ │ │ ├── statements: ∅ │ │ │ │ └── end_keyword_loc: (14,32)-(14,35) = "end" @@ -164,41 +193,50 @@ │ ├── end_keyword_loc: (14,37)-(14,40) = "end" │ └── name: :A ├── @ ClassNode (location: (16,0)-(16,54)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (16,0)-(16,5) = "class" │ ├── constant_path: │ │ @ ConstantReadNode (location: (16,6)-(16,7)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── inheritance_operator_loc: ∅ │ ├── superclass: ∅ │ ├── body: │ │ @ StatementsNode (location: (16,9)-(16,49)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SingletonClassNode (location: (16,9)-(16,49)) + │ │ ├── flags: newline │ │ ├── locals: [] │ │ ├── class_keyword_loc: (16,9)-(16,14) = "class" │ │ ├── operator_loc: (16,15)-(16,17) = "<<" │ │ ├── expression: │ │ │ @ SelfNode (location: (16,18)-(16,22)) + │ │ │ └── flags: ∅ │ │ ├── body: │ │ │ @ BeginNode (location: (16,9)-(16,49)) + │ │ │ ├── flags: ∅ │ │ │ ├── begin_keyword_loc: ∅ │ │ │ ├── statements: ∅ │ │ │ ├── rescue_clause: │ │ │ │ @ RescueNode (location: (16,24)-(16,30)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── keyword_loc: (16,24)-(16,30) = "rescue" │ │ │ │ ├── exceptions: (length: 0) │ │ │ │ ├── operator_loc: ∅ │ │ │ │ ├── reference: ∅ │ │ │ │ ├── statements: ∅ - │ │ │ │ └── consequent: ∅ + │ │ │ │ └── subsequent: ∅ │ │ │ ├── else_clause: │ │ │ │ @ ElseNode (location: (16,32)-(16,44)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── else_keyword_loc: (16,32)-(16,36) = "else" │ │ │ │ ├── statements: ∅ │ │ │ │ └── end_keyword_loc: (16,38)-(16,44) = "ensure" │ │ │ ├── ensure_clause: │ │ │ │ @ EnsureNode (location: (16,38)-(16,49)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── ensure_keyword_loc: (16,38)-(16,44) = "ensure" │ │ │ │ ├── statements: ∅ │ │ │ │ └── end_keyword_loc: (16,46)-(16,49) = "end" @@ -207,6 +245,7 @@ │ ├── end_keyword_loc: (16,51)-(16,54) = "end" │ └── name: :A ├── @ SingletonClassNode (location: (18,0)-(19,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (18,0)-(18,5) = "class" │ ├── operator_loc: (18,6)-(18,8) = "<<" @@ -234,6 +273,7 @@ │ ├── body: ∅ │ └── end_keyword_loc: (19,0)-(19,3) = "end" ├── @ SingletonClassNode (location: (21,0)-(21,20)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (21,0)-(21,5) = "class" │ ├── operator_loc: (21,6)-(21,8) = "<<" @@ -261,35 +301,42 @@ │ ├── body: ∅ │ └── end_keyword_loc: (21,17)-(21,20) = "end" ├── @ SingletonClassNode (location: (23,0)-(24,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (23,0)-(23,5) = "class" │ ├── operator_loc: (23,6)-(23,8) = "<<" │ ├── expression: │ │ @ SelfNode (location: (23,9)-(23,13)) + │ │ └── flags: ∅ │ ├── body: ∅ │ └── end_keyword_loc: (24,0)-(24,3) = "end" ├── @ SingletonClassNode (location: (26,0)-(26,17)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (26,0)-(26,5) = "class" │ ├── operator_loc: (26,6)-(26,8) = "<<" │ ├── expression: │ │ @ SelfNode (location: (26,9)-(26,13)) + │ │ └── flags: ∅ │ ├── body: ∅ │ └── end_keyword_loc: (26,14)-(26,17) = "end" ├── @ SingletonClassNode (location: (28,0)-(30,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (28,0)-(28,5) = "class" │ ├── operator_loc: (28,6)-(28,8) = "<<" │ ├── expression: │ │ @ SelfNode (location: (28,9)-(28,13)) + │ │ └── flags: ∅ │ ├── body: │ │ @ StatementsNode (location: (29,0)-(29,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (29,0)-(29,5)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ IntegerNode (location: (29,0)-(29,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :+ @@ -300,25 +347,28 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (29,4)-(29,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ └── end_keyword_loc: (30,0)-(30,3) = "end" ├── @ SingletonClassNode (location: (32,0)-(32,23)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (32,0)-(32,5) = "class" │ ├── operator_loc: (32,6)-(32,8) = "<<" │ ├── expression: │ │ @ SelfNode (location: (32,9)-(32,13)) + │ │ └── flags: ∅ │ ├── body: │ │ @ StatementsNode (location: (32,14)-(32,19)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (32,14)-(32,19)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ IntegerNode (location: (32,14)-(32,15)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :+ @@ -329,16 +379,18 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (32,18)-(32,19)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ └── end_keyword_loc: (32,20)-(32,23) = "end" └── @ ClassNode (location: (34,0)-(35,3)) + ├── flags: newline ├── locals: [] ├── class_keyword_loc: (34,0)-(34,5) = "class" ├── constant_path: │ @ ConstantReadNode (location: (34,6)-(34,7)) + │ ├── flags: ∅ │ └── name: :A ├── inheritance_operator_loc: (34,8)-(34,9) = "<" ├── superclass: @@ -346,6 +398,7 @@ │ ├── flags: ∅ │ ├── receiver: │ │ @ ConstantReadNode (location: (34,10)-(34,11)) + │ │ ├── flags: ∅ │ │ └── name: :B │ ├── call_operator_loc: ∅ │ ├── name: :[] @@ -356,7 +409,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (34,12)-(34,13)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── closing_loc: (34,13)-(34,14) = "]" │ └── block: ∅ diff --git a/test/prism/snapshots/command_method_call.txt b/test/prism/snapshots/command_method_call.txt index 7fd6341304c..ab48ee480e2 100644 --- a/test/prism/snapshots/command_method_call.txt +++ b/test/prism/snapshots/command_method_call.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(41,10)) +├── flags: ∅ ├── locals: [:foo, :bar] └── statements: @ StatementsNode (location: (1,0)-(41,10)) + ├── flags: ∅ └── body: (length: 21) ├── @ CallNode (location: (1,0)-(1,5)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -15,12 +17,12 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (3,0)-(3,9)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -42,13 +44,14 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (3,8)-(3,9)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ IfNode (location: (5,0)-(5,14)) + │ ├── flags: newline │ ├── if_keyword_loc: (5,6)-(5,8) = "if" │ ├── predicate: │ │ @ CallNode (location: (5,9)-(5,14)) @@ -63,16 +66,17 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (5,13)-(5,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (5,0)-(5,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (5,0)-(5,5)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo @@ -83,13 +87,14 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (5,4)-(5,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: ∅ ├── @ UnlessNode (location: (7,0)-(7,18)) + │ ├── flags: newline │ ├── keyword_loc: (7,6)-(7,12) = "unless" │ ├── predicate: │ │ @ CallNode (location: (7,13)-(7,18)) @@ -104,16 +109,17 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (7,17)-(7,18)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (7,0)-(7,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (7,0)-(7,5)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo @@ -124,14 +130,14 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (7,4)-(7,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ └── end_keyword_loc: ∅ ├── @ WhileNode (location: (9,0)-(9,17)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (9,6)-(9,11) = "while" │ ├── closing_loc: ∅ │ ├── predicate: @@ -147,15 +153,16 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (9,16)-(9,17)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ └── statements: │ @ StatementsNode (location: (9,0)-(9,5)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (9,0)-(9,5)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -166,12 +173,12 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (9,4)-(9,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ UntilNode (location: (11,0)-(11,17)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (11,6)-(11,11) = "until" │ ├── closing_loc: ∅ │ ├── predicate: @@ -187,15 +194,16 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (11,16)-(11,17)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ └── statements: │ @ StatementsNode (location: (11,0)-(11,5)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (11,0)-(11,5)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -206,11 +214,12 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (11,4)-(11,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ RescueModifierNode (location: (13,0)-(13,18)) + │ ├── flags: newline │ ├── expression: │ │ @ CallNode (location: (13,0)-(13,5)) │ │ ├── flags: ignore_visibility @@ -224,7 +233,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (13,4)-(13,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ @@ -242,12 +251,12 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (13,17)-(13,18)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (15,0)-(15,10)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (15,0)-(15,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -279,13 +288,14 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (15,8)-(15,9)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── closing_loc: (15,9)-(15,10) = "]" │ └── block: ∅ ├── @ AndNode (location: (17,0)-(17,15)) + │ ├── flags: newline │ ├── left: │ │ @ CallNode (location: (17,0)-(17,5)) │ │ ├── flags: ignore_visibility @@ -299,7 +309,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (17,4)-(17,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ @@ -316,12 +326,13 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (17,14)-(17,15)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ └── operator_loc: (17,6)-(17,9) = "and" ├── @ OrNode (location: (19,0)-(19,14)) + │ ├── flags: newline │ ├── left: │ │ @ CallNode (location: (19,0)-(19,5)) │ │ ├── flags: ignore_visibility @@ -335,7 +346,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (19,4)-(19,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ @@ -352,13 +363,13 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (19,13)-(19,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ └── operator_loc: (19,6)-(19,8) = "or" ├── @ CallNode (location: (21,0)-(21,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (21,4)-(21,9)) │ │ ├── flags: ignore_visibility @@ -372,7 +383,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (21,8)-(21,9)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ @@ -384,11 +395,13 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ LocalVariableWriteNode (location: (23,0)-(23,17)) + │ ├── flags: newline │ ├── name: :foo │ ├── depth: 0 │ ├── name_loc: (23,0)-(23,3) = "foo" │ ├── value: │ │ @ LocalVariableWriteNode (location: (23,6)-(23,17)) + │ │ ├── flags: ∅ │ │ ├── name: :bar │ │ ├── depth: 0 │ │ ├── name_loc: (23,6)-(23,9) = "bar" @@ -405,19 +418,21 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (23,16)-(23,17)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── operator_loc: (23,10)-(23,11) = "=" │ └── operator_loc: (23,4)-(23,5) = "=" ├── @ DefNode (location: (25,0)-(25,15)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (25,4)-(25,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (25,10)-(25,15)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (25,10)-(25,15)) │ │ ├── flags: ignore_visibility @@ -431,7 +446,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (25,14)-(25,15)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ @@ -443,10 +458,10 @@ │ ├── equal_loc: (25,8)-(25,9) = "=" │ └── end_keyword_loc: ∅ ├── @ CallNode (location: (27,0)-(27,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ IntegerNode (location: (27,0)-(27,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── call_operator_loc: (27,1)-(27,2) = "." │ ├── name: :foo @@ -457,18 +472,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (27,6)-(27,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (29,0)-(29,11)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (29,0)-(29,5)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (29,0)-(29,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── call_operator_loc: (29,1)-(29,2) = "." │ │ ├── name: :foo @@ -486,12 +501,12 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (29,10)-(29,11)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (31,0)-(31,14)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (31,0)-(31,8)) │ │ ├── flags: ∅ @@ -500,7 +515,7 @@ │ │ │ ├── flags: ∅ │ │ │ ├── receiver: │ │ │ │ @ IntegerNode (location: (31,0)-(31,1)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── call_operator_loc: (31,1)-(31,2) = "." │ │ │ ├── name: :foo @@ -518,7 +533,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (31,6)-(31,7)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: (31,7)-(31,8) = "]" │ │ └── block: ∅ @@ -531,18 +546,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (31,13)-(31,14)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (33,0)-(33,14)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (33,0)-(33,8)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (33,0)-(33,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── call_operator_loc: (33,1)-(33,2) = "." │ │ ├── name: :foo @@ -553,7 +568,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (33,6)-(33,7)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: (33,7)-(33,8) = ")" │ │ └── block: ∅ @@ -566,18 +581,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (33,13)-(33,14)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (35,0)-(35,15)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (35,0)-(35,9)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (35,0)-(35,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── call_operator_loc: (35,1)-(35,2) = "." │ │ ├── name: :foo @@ -587,9 +602,10 @@ │ │ ├── closing_loc: (35,8)-(35,9) = ")" │ │ └── block: │ │ @ BlockArgumentNode (location: (35,6)-(35,8)) + │ │ ├── flags: ∅ │ │ ├── expression: │ │ │ @ IntegerNode (location: (35,7)-(35,8)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: (35,6)-(35,7) = "&" │ ├── call_operator_loc: (35,9)-(35,10) = "." @@ -601,11 +617,12 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (35,14)-(35,15)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ AndNode (location: (37,0)-(37,17)) + │ ├── flags: newline │ ├── left: │ │ @ CallNode (location: (37,0)-(37,6)) │ │ ├── flags: ∅ @@ -622,7 +639,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (37,5)-(37,6)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ @@ -649,7 +666,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (37,16)-(37,17)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ @@ -662,6 +679,7 @@ │ │ └── block: ∅ │ └── operator_loc: (37,7)-(37,10) = "and" ├── @ OrNode (location: (39,0)-(39,16)) + │ ├── flags: newline │ ├── left: │ │ @ CallNode (location: (39,0)-(39,6)) │ │ ├── flags: ∅ @@ -678,7 +696,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (39,5)-(39,6)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ @@ -705,7 +723,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (39,15)-(39,16)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ @@ -718,7 +736,7 @@ │ │ └── block: ∅ │ └── operator_loc: (39,7)-(39,9) = "or" └── @ CallNode (location: (41,0)-(41,10)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (41,4)-(41,10)) │ ├── flags: ∅ @@ -735,7 +753,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (41,9)-(41,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ diff --git a/test/prism/snapshots/comments.txt b/test/prism/snapshots/comments.txt index b7088adcd50..66869bc2a99 100644 --- a/test/prism/snapshots/comments.txt +++ b/test/prism/snapshots/comments.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(24,5)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(24,5)) + ├── flags: ∅ └── body: (length: 9) ├── @ CallNode (location: (1,0)-(1,1)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a @@ -14,7 +16,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (3,0)-(3,1)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :b @@ -24,7 +26,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (5,0)-(5,1)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :c @@ -34,7 +36,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (6,0)-(6,1)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :d @@ -44,7 +46,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (8,0)-(10,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (8,0)-(8,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -64,7 +66,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (12,0)-(14,2)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (12,0)-(12,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -84,7 +86,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (16,0)-(17,2)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (16,0)-(16,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -104,7 +106,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (19,0)-(20,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (19,0)-(19,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -124,7 +126,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ └── @ CallNode (location: (22,0)-(24,5)) - ├── flags: safe_navigation + ├── flags: newline, safe_navigation ├── receiver: │ @ CallNode (location: (22,0)-(22,1)) │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/constants.txt b/test/prism/snapshots/constants.txt index 12518336634..e1aada8e96f 100644 --- a/test/prism/snapshots/constants.txt +++ b/test/prism/snapshots/constants.txt @@ -1,20 +1,27 @@ @ ProgramNode (location: (1,0)-(184,10)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(184,10)) + ├── flags: ∅ └── body: (length: 90) ├── @ ConstantPathNode (location: (1,0)-(1,4)) + │ ├── flags: newline │ ├── parent: │ │ @ ConstantReadNode (location: (1,0)-(1,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── name: :B │ ├── delimiter_loc: (1,1)-(1,3) = "::" │ └── name_loc: (1,3)-(1,4) = "B" ├── @ ConstantPathNode (location: (3,0)-(3,7)) + │ ├── flags: newline │ ├── parent: │ │ @ ConstantPathNode (location: (3,0)-(3,4)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantReadNode (location: (3,0)-(3,1)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── name: :B │ │ ├── delimiter_loc: (3,1)-(3,3) = "::" @@ -23,6 +30,7 @@ │ ├── delimiter_loc: (3,4)-(3,6) = "::" │ └── name_loc: (3,6)-(3,7) = "C" ├── @ ConstantPathNode (location: (5,0)-(5,4)) + │ ├── flags: newline │ ├── parent: │ │ @ CallNode (location: (5,0)-(5,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -38,10 +46,13 @@ │ ├── delimiter_loc: (5,1)-(5,3) = "::" │ └── name_loc: (5,3)-(5,4) = "B" ├── @ ConstantPathWriteNode (location: (7,0)-(7,8)) + │ ├── flags: newline │ ├── target: │ │ @ ConstantPathNode (location: (7,0)-(7,4)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantReadNode (location: (7,0)-(7,1)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── name: :B │ │ ├── delimiter_loc: (7,1)-(7,3) = "::" @@ -49,20 +60,22 @@ │ ├── operator_loc: (7,5)-(7,6) = "=" │ └── value: │ @ IntegerNode (location: (7,7)-(7,8)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ ConstantWriteNode (location: (9,0)-(9,5)) + │ ├── flags: newline │ ├── name: :A │ ├── name_loc: (9,0)-(9,1) = "A" │ ├── value: │ │ @ IntegerNode (location: (9,4)-(9,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (9,2)-(9,3) = "=" ├── @ ConstantReadNode (location: (11,0)-(11,3)) + │ ├── flags: newline │ └── name: :ABC ├── @ CallNode (location: (13,0)-(13,5)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :Foo @@ -73,12 +86,12 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (13,4)-(13,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (15,0)-(15,8)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :Foo @@ -86,9 +99,10 @@ │ ├── opening_loc: ∅ │ ├── arguments: │ │ @ ArgumentsNode (location: (15,4)-(15,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat │ │ └── arguments: (length: 1) │ │ └── @ SplatNode (location: (15,4)-(15,8)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (15,4)-(15,5) = "*" │ │ └── expression: │ │ @ CallNode (location: (15,5)-(15,8)) @@ -104,7 +118,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (17,0)-(17,9)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :Foo @@ -118,6 +132,7 @@ │ │ ├── flags: ∅ │ │ └── elements: (length: 1) │ │ └── @ AssocSplatNode (location: (17,4)-(17,9)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ CallNode (location: (17,6)-(17,9)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -133,7 +148,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (19,0)-(19,8)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :Foo @@ -143,6 +158,7 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockArgumentNode (location: (19,4)-(19,8)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (19,5)-(19,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -156,9 +172,10 @@ │ │ └── block: ∅ │ └── operator_loc: (19,4)-(19,5) = "&" ├── @ CallNode (location: (21,0)-(21,13)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (21,0)-(21,3)) + │ │ ├── flags: ∅ │ │ └── name: :Foo │ ├── call_operator_loc: (21,3)-(21,5) = "::" │ ├── name: :Bar @@ -166,9 +183,10 @@ │ ├── opening_loc: ∅ │ ├── arguments: │ │ @ ArgumentsNode (location: (21,9)-(21,13)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat │ │ └── arguments: (length: 1) │ │ └── @ SplatNode (location: (21,9)-(21,13)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (21,9)-(21,10) = "*" │ │ └── expression: │ │ @ CallNode (location: (21,10)-(21,13)) @@ -184,9 +202,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (23,0)-(23,14)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (23,0)-(23,3)) + │ │ ├── flags: ∅ │ │ └── name: :Foo │ ├── call_operator_loc: (23,3)-(23,5) = "::" │ ├── name: :Bar @@ -200,6 +219,7 @@ │ │ ├── flags: ∅ │ │ └── elements: (length: 1) │ │ └── @ AssocSplatNode (location: (23,9)-(23,14)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ CallNode (location: (23,11)-(23,14)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -215,9 +235,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (25,0)-(25,13)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (25,0)-(25,3)) + │ │ ├── flags: ∅ │ │ └── name: :Foo │ ├── call_operator_loc: (25,3)-(25,5) = "::" │ ├── name: :Bar @@ -227,6 +248,7 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockArgumentNode (location: (25,9)-(25,13)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (25,10)-(25,13)) │ │ ├── flags: variable_call, ignore_visibility @@ -240,9 +262,10 @@ │ │ └── block: ∅ │ └── operator_loc: (25,9)-(25,10) = "&" ├── @ CallNode (location: (27,0)-(27,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantPathNode (location: (27,0)-(27,3)) + │ │ ├── flags: ∅ │ │ ├── parent: ∅ │ │ ├── name: :A │ │ ├── delimiter_loc: (27,0)-(27,2) = "::" @@ -255,8 +278,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ ConstantPathWriteNode (location: (29,0)-(29,7)) + │ ├── flags: newline │ ├── target: │ │ @ ConstantPathNode (location: (29,0)-(29,3)) + │ │ ├── flags: ∅ │ │ ├── parent: ∅ │ │ ├── name: :A │ │ ├── delimiter_loc: (29,0)-(29,2) = "::" @@ -264,13 +289,16 @@ │ ├── operator_loc: (29,4)-(29,5) = "=" │ └── value: │ @ IntegerNode (location: (29,6)-(29,7)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ ConstantPathWriteNode (location: (31,0)-(31,10)) + │ ├── flags: newline │ ├── target: │ │ @ ConstantPathNode (location: (31,0)-(31,6)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantPathNode (location: (31,0)-(31,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── parent: ∅ │ │ │ ├── name: :A │ │ │ ├── delimiter_loc: (31,0)-(31,2) = "::" @@ -281,11 +309,13 @@ │ ├── operator_loc: (31,7)-(31,8) = "=" │ └── value: │ @ IntegerNode (location: (31,9)-(31,10)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ ConstantPathNode (location: (33,0)-(33,6)) + │ ├── flags: newline │ ├── parent: │ │ @ ConstantPathNode (location: (33,0)-(33,3)) + │ │ ├── flags: ∅ │ │ ├── parent: ∅ │ │ ├── name: :A │ │ ├── delimiter_loc: (33,0)-(33,2) = "::" @@ -294,14 +324,16 @@ │ ├── delimiter_loc: (33,3)-(33,5) = "::" │ └── name_loc: (33,5)-(33,6) = "B" ├── @ ConstantPathNode (location: (35,0)-(35,3)) + │ ├── flags: newline │ ├── parent: ∅ │ ├── name: :A │ ├── delimiter_loc: (35,0)-(35,2) = "::" │ └── name_loc: (35,2)-(35,3) = "A" ├── @ CallNode (location: (37,0)-(37,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (37,0)-(37,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (37,1)-(37,3) = "::" │ ├── name: :false @@ -311,11 +343,13 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (39,0)-(39,10)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantPathNode (location: (39,0)-(39,4)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantReadNode (location: (39,0)-(39,1)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── name: :B │ │ ├── delimiter_loc: (39,1)-(39,3) = "::" @@ -328,9 +362,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (41,0)-(41,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (41,0)-(41,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (41,1)-(41,3) = "::" │ ├── name: :& @@ -340,9 +375,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (43,0)-(43,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (43,0)-(43,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (43,1)-(43,3) = "::" │ ├── name: :` @@ -352,9 +388,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (45,0)-(45,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (45,0)-(45,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (45,1)-(45,3) = "::" │ ├── name: :! @@ -364,9 +401,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (47,0)-(47,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (47,0)-(47,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (47,1)-(47,3) = "::" │ ├── name: :!= @@ -376,9 +414,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (49,0)-(49,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (49,0)-(49,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (49,1)-(49,3) = "::" │ ├── name: :^ @@ -388,9 +427,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (51,0)-(51,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (51,0)-(51,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (51,1)-(51,3) = "::" │ ├── name: :== @@ -400,9 +440,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (53,0)-(53,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (53,0)-(53,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (53,1)-(53,3) = "::" │ ├── name: :=== @@ -412,9 +453,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (55,0)-(55,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (55,0)-(55,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (55,1)-(55,3) = "::" │ ├── name: :=~ @@ -424,9 +466,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (57,0)-(57,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (57,0)-(57,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (57,1)-(57,3) = "::" │ ├── name: :> @@ -436,9 +479,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (59,0)-(59,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (59,0)-(59,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (59,1)-(59,3) = "::" │ ├── name: :>= @@ -448,9 +492,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (61,0)-(61,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (61,0)-(61,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (61,1)-(61,3) = "::" │ ├── name: :>> @@ -460,9 +505,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (63,0)-(63,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (63,0)-(63,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (63,1)-(63,3) = "::" │ ├── name: :<< @@ -472,16 +518,19 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ ConstantPathNode (location: (65,0)-(67,1)) + │ ├── flags: newline │ ├── parent: │ │ @ ConstantReadNode (location: (65,0)-(65,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── name: :C │ ├── delimiter_loc: (65,1)-(65,3) = "::" │ └── name_loc: (67,0)-(67,1) = "C" ├── @ CallNode (location: (69,0)-(69,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (69,0)-(69,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (69,1)-(69,3) = "::" │ ├── name: :alias @@ -491,9 +540,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (71,0)-(71,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (71,0)-(71,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (71,1)-(71,3) = "::" │ ├── name: :and @@ -503,9 +553,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (73,0)-(73,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (73,0)-(73,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (73,1)-(73,3) = "::" │ ├── name: :begin @@ -515,16 +566,19 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ ConstantPathNode (location: (75,0)-(75,8)) + │ ├── flags: newline │ ├── parent: │ │ @ ConstantReadNode (location: (75,0)-(75,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── name: :BEGIN │ ├── delimiter_loc: (75,1)-(75,3) = "::" │ └── name_loc: (75,3)-(75,8) = "BEGIN" ├── @ CallNode (location: (77,0)-(77,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (77,0)-(77,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (77,1)-(77,3) = "::" │ ├── name: :break @@ -534,9 +588,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (79,0)-(79,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (79,0)-(79,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (79,1)-(79,3) = "::" │ ├── name: :class @@ -546,9 +601,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (81,0)-(81,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (81,0)-(81,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (81,1)-(81,3) = "::" │ ├── name: :def @@ -558,9 +614,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (83,0)-(83,10)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (83,0)-(83,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (83,1)-(83,3) = "::" │ ├── name: :defined @@ -570,9 +627,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (85,0)-(85,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (85,0)-(85,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (85,1)-(85,3) = "::" │ ├── name: :do @@ -582,9 +640,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (87,0)-(87,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (87,0)-(87,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (87,1)-(87,3) = "::" │ ├── name: :else @@ -594,9 +653,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (89,0)-(89,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (89,0)-(89,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (89,1)-(89,3) = "::" │ ├── name: :elsif @@ -606,9 +666,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (91,0)-(91,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (91,0)-(91,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (91,1)-(91,3) = "::" │ ├── name: :end @@ -618,16 +679,19 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ ConstantPathNode (location: (93,0)-(93,6)) + │ ├── flags: newline │ ├── parent: │ │ @ ConstantReadNode (location: (93,0)-(93,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── name: :END │ ├── delimiter_loc: (93,1)-(93,3) = "::" │ └── name_loc: (93,3)-(93,6) = "END" ├── @ CallNode (location: (95,0)-(95,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (95,0)-(95,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (95,1)-(95,3) = "::" │ ├── name: :ensure @@ -637,9 +701,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (97,0)-(97,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (97,0)-(97,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (97,1)-(97,3) = "::" │ ├── name: :false @@ -649,9 +714,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (99,0)-(99,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (99,0)-(99,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (99,1)-(99,3) = "::" │ ├── name: :for @@ -661,9 +727,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (101,0)-(101,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (101,0)-(101,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (101,1)-(101,3) = "::" │ ├── name: :if @@ -673,9 +740,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (103,0)-(103,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (103,0)-(103,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (103,1)-(103,3) = "::" │ ├── name: :in @@ -685,9 +753,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (105,0)-(105,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (105,0)-(105,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (105,1)-(105,3) = "::" │ ├── name: :next @@ -697,9 +766,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (107,0)-(107,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (107,0)-(107,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (107,1)-(107,3) = "::" │ ├── name: :nil @@ -709,9 +779,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (109,0)-(109,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (109,0)-(109,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (109,1)-(109,3) = "::" │ ├── name: :not @@ -721,9 +792,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (111,0)-(111,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (111,0)-(111,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (111,1)-(111,3) = "::" │ ├── name: :or @@ -733,9 +805,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (113,0)-(113,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (113,0)-(113,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (113,1)-(113,3) = "::" │ ├── name: :redo @@ -745,9 +818,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (115,0)-(115,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (115,0)-(115,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (115,1)-(115,3) = "::" │ ├── name: :rescue @@ -757,9 +831,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (117,0)-(117,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (117,0)-(117,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (117,1)-(117,3) = "::" │ ├── name: :retry @@ -769,9 +844,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (119,0)-(119,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (119,0)-(119,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (119,1)-(119,3) = "::" │ ├── name: :return @@ -781,9 +857,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (121,0)-(121,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (121,0)-(121,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (121,1)-(121,3) = "::" │ ├── name: :self @@ -793,9 +870,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (123,0)-(123,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (123,0)-(123,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (123,1)-(123,3) = "::" │ ├── name: :super @@ -805,9 +883,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (125,0)-(125,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (125,0)-(125,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (125,1)-(125,3) = "::" │ ├── name: :then @@ -817,9 +896,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (127,0)-(127,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (127,0)-(127,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (127,1)-(127,3) = "::" │ ├── name: :true @@ -829,9 +909,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (129,0)-(129,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (129,0)-(129,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (129,1)-(129,3) = "::" │ ├── name: :undef @@ -841,9 +922,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (131,0)-(131,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (131,0)-(131,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (131,1)-(131,3) = "::" │ ├── name: :unless @@ -853,9 +935,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (133,0)-(133,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (133,0)-(133,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (133,1)-(133,3) = "::" │ ├── name: :until @@ -865,9 +948,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (135,0)-(135,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (135,0)-(135,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (135,1)-(135,3) = "::" │ ├── name: :when @@ -877,9 +961,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (137,0)-(137,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (137,0)-(137,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (137,1)-(137,3) = "::" │ ├── name: :while @@ -889,9 +974,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (139,0)-(139,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (139,0)-(139,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (139,1)-(139,3) = "::" │ ├── name: :yield @@ -901,9 +987,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (141,0)-(141,15)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (141,0)-(141,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (141,1)-(141,3) = "::" │ ├── name: :__ENCODING__ @@ -913,9 +1000,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (143,0)-(143,11)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (143,0)-(143,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (143,1)-(143,3) = "::" │ ├── name: :__FILE__ @@ -925,9 +1013,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (145,0)-(145,11)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (145,0)-(145,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (145,1)-(145,3) = "::" │ ├── name: :__LINE__ @@ -937,9 +1026,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (147,0)-(147,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (147,0)-(147,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (147,1)-(147,3) = "::" │ ├── name: :< @@ -949,9 +1039,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (149,0)-(149,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (149,0)-(149,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (149,1)-(149,3) = "::" │ ├── name: :<=> @@ -961,9 +1052,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (151,0)-(151,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (151,0)-(151,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (151,1)-(151,3) = "::" │ ├── name: :<< @@ -973,9 +1065,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (153,0)-(153,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (153,0)-(153,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (153,1)-(153,3) = "::" │ ├── name: :- @@ -985,9 +1078,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (155,0)-(155,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (155,0)-(155,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (155,1)-(155,3) = "::" │ ├── name: :% @@ -997,9 +1091,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (157,0)-(157,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (157,0)-(157,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (157,1)-(157,3) = "::" │ ├── name: :% @@ -1022,9 +1117,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (159,0)-(159,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (159,0)-(159,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (159,1)-(159,3) = "::" │ ├── name: :% @@ -1047,9 +1143,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (161,0)-(161,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (161,0)-(161,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (161,1)-(161,3) = "::" │ ├── name: :% @@ -1072,9 +1169,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (163,0)-(163,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (163,0)-(163,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (163,1)-(163,3) = "::" │ ├── name: :% @@ -1085,13 +1183,15 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ ConstantReadNode (location: (163,4)-(163,5)) + │ │ ├── flags: ∅ │ │ └── name: :I │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (165,0)-(165,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (165,0)-(165,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (165,1)-(165,3) = "::" │ ├── name: :% @@ -1102,13 +1202,15 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ ConstantReadNode (location: (165,4)-(165,5)) + │ │ ├── flags: ∅ │ │ └── name: :W │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (167,0)-(167,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (167,0)-(167,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (167,1)-(167,3) = "::" │ ├── name: :| @@ -1118,9 +1220,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (169,0)-(169,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (169,0)-(169,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (169,1)-(169,3) = "::" │ ├── name: :+ @@ -1130,9 +1233,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (171,0)-(171,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (171,0)-(171,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (171,1)-(171,3) = "::" │ ├── name: :/ @@ -1142,9 +1246,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (173,0)-(173,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (173,0)-(173,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (173,1)-(173,3) = "::" │ ├── name: :* @@ -1154,9 +1259,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (175,0)-(175,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (175,0)-(175,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (175,1)-(175,3) = "::" │ ├── name: :** @@ -1166,9 +1272,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (177,0)-(177,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (177,0)-(177,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (177,1)-(177,3) = "::" │ ├── name: :~ @@ -1178,11 +1285,13 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ ConstantPathNode (location: (179,0)-(180,1)) + │ ├── flags: newline │ ├── parent: │ │ @ CallNode (location: (179,0)-(179,4)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ ConstantReadNode (location: (179,0)-(179,1)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── call_operator_loc: (179,1)-(179,3) = "::" │ │ ├── name: :_ @@ -1195,12 +1304,13 @@ │ ├── delimiter_loc: (179,4)-(179,6) = "::" │ └── name_loc: (180,0)-(180,1) = "C" └── @ RangeNode (location: (182,0)-(184,10)) - ├── flags: ∅ + ├── flags: newline ├── left: │ @ CallNode (location: (182,0)-(182,4)) │ ├── flags: ∅ │ ├── receiver: │ │ @ ConstantReadNode (location: (182,0)-(182,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (182,1)-(182,3) = "::" │ ├── name: :_ @@ -1214,6 +1324,7 @@ │ ├── flags: ∅ │ ├── receiver: │ │ @ ConstantReadNode (location: (184,0)-(184,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (184,1)-(184,3) = "::" │ ├── name: :__END__ diff --git a/test/prism/snapshots/dash_heredocs.txt b/test/prism/snapshots/dash_heredocs.txt index bd2b05ea0d0..1ca8b4f73dc 100644 --- a/test/prism/snapshots/dash_heredocs.txt +++ b/test/prism/snapshots/dash_heredocs.txt @@ -1,16 +1,18 @@ @ ProgramNode (location: (1,0)-(57,11)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(57,11)) + ├── flags: ∅ └── body: (length: 13) ├── @ StringNode (location: (1,0)-(1,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (1,0)-(1,6) = "<<-EOF" │ ├── content_loc: (2,0)-(3,0) = " a\n" │ ├── closing_loc: (3,0)-(4,0) = "EOF\n" │ └── unescaped: " a\n" ├── @ CallNode (location: (5,0)-(5,20)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ StringNode (location: (5,0)-(5,8)) │ │ ├── flags: ∅ @@ -35,6 +37,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ InterpolatedXStringNode (location: (11,0)-(11,8)) + │ ├── flags: newline │ ├── opening_loc: (11,0)-(11,8) = "<<-`EOF`" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (12,0)-(13,0)) @@ -44,9 +47,11 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: " a\n" │ │ ├── @ EmbeddedStatementsNode (location: (13,0)-(13,4)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (13,0)-(13,2) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (13,2)-(13,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (13,2)-(13,3)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -67,31 +72,33 @@ │ │ └── unescaped: "\n" │ └── closing_loc: (14,0)-(15,0) = "EOF\n" ├── @ StringNode (location: (16,0)-(16,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (16,0)-(16,6) = "<<-EOF" │ ├── content_loc: (17,0)-(18,0) = " a\n" │ ├── closing_loc: (18,0)-(19,0) = "EOF\n" │ └── unescaped: " a\n" ├── @ StringNode (location: (20,0)-(20,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (20,0)-(20,6) = "<<-EOF" │ ├── content_loc: (21,0)-(23,0) = " a\n b\n" │ ├── closing_loc: (23,0)-(24,0) = " EOF\n" │ └── unescaped: " a\n b\n" ├── @ InterpolatedStringNode (location: (25,0)-(25,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (25,0)-(25,8) = "<<-\"EOF\"" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (26,0)-(27,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (26,0)-(27,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: " a\n" │ │ ├── @ EmbeddedStatementsNode (location: (27,0)-(27,4)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (27,0)-(27,2) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (27,2)-(27,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (27,2)-(27,3)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -105,26 +112,28 @@ │ │ │ │ └── block: ∅ │ │ │ └── closing_loc: (27,3)-(27,4) = "}" │ │ └── @ StringNode (location: (27,4)-(28,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (27,4)-(28,0) = "\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\n" │ └── closing_loc: (28,0)-(29,0) = "EOF\n" ├── @ InterpolatedStringNode (location: (30,0)-(30,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (30,0)-(30,6) = "<<-EOF" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (31,0)-(32,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (31,0)-(32,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: " a\n" │ │ ├── @ EmbeddedStatementsNode (location: (32,0)-(32,4)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (32,0)-(32,2) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (32,2)-(32,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (32,2)-(32,3)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -138,38 +147,38 @@ │ │ │ │ └── block: ∅ │ │ │ └── closing_loc: (32,3)-(32,4) = "}" │ │ └── @ StringNode (location: (32,4)-(33,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (32,4)-(33,0) = "\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\n" │ └── closing_loc: (33,0)-(34,0) = "EOF\n" ├── @ StringNode (location: (35,0)-(35,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (35,0)-(35,2) = "%#" │ ├── content_loc: (35,2)-(35,5) = "abc" │ ├── closing_loc: (35,5)-(35,6) = "#" │ └── unescaped: "abc" ├── @ StringNode (location: (37,0)-(37,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (37,0)-(37,6) = "<<-EOF" │ ├── content_loc: (38,0)-(40,0) = " a\n b\n" │ ├── closing_loc: (40,0)-(41,0) = "EOF\n" │ └── unescaped: " a\n b\n" ├── @ StringNode (location: (42,0)-(42,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (42,0)-(42,5) = "<<-''" │ ├── content_loc: (43,0)-(43,0) = "" │ ├── closing_loc: (43,0)-(44,0) = "\n" │ └── unescaped: "" ├── @ StringNode (location: (45,0)-(45,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (45,0)-(45,8) = "<<-'EOF'" │ ├── content_loc: (46,0)-(47,0) = " a \#{1}\n" │ ├── closing_loc: (47,0)-(48,0) = "EOF\n" │ └── unescaped: " a \#{1}\n" ├── @ CallNode (location: (49,0)-(49,11)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ StringNode (location: (49,0)-(49,4)) │ │ ├── flags: ∅ @@ -190,22 +199,24 @@ │ │ ├── opening_loc: (49,7)-(49,11) = "<<-B" │ │ ├── parts: (length: 3) │ │ │ ├── @ StringNode (location: (52,0)-(53,2)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (52,0)-(53,2) = " b\n " │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: " b\n " │ │ │ ├── @ EmbeddedStatementsNode (location: (53,2)-(54,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: (53,2)-(53,4) = "\#{" │ │ │ │ ├── statements: │ │ │ │ │ @ StatementsNode (location: (53,4)-(53,5)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (53,4)-(53,5)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 2 │ │ │ │ └── closing_loc: (54,2)-(54,3) = "}" │ │ │ └── @ StringNode (location: (54,3)-(55,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (54,3)-(55,0) = "\n" │ │ │ ├── closing_loc: ∅ @@ -214,7 +225,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ └── @ CallNode (location: (57,0)-(57,11)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ StringNode (location: (57,0)-(57,4)) │ ├── flags: ∅ @@ -235,22 +246,24 @@ │ ├── opening_loc: (57,7)-(57,11) = "<<-B" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (60,0)-(61,2)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (60,0)-(61,2) = " b\n " │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: " b\n " │ │ ├── @ EmbeddedStatementsNode (location: (61,2)-(62,4)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (61,2)-(61,4) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (62,2)-(62,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (62,2)-(62,3)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ └── closing_loc: (62,3)-(62,4) = "}" │ │ └── @ StringNode (location: (62,4)-(63,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (62,4)-(63,0) = "\n" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/defined.txt b/test/prism/snapshots/defined.txt index 53a5081811c..761c7b2ce79 100644 --- a/test/prism/snapshots/defined.txt +++ b/test/prism/snapshots/defined.txt @@ -1,47 +1,56 @@ @ ProgramNode (location: (1,0)-(10,1)) +├── flags: ∅ ├── locals: [:x] └── statements: @ StatementsNode (location: (1,0)-(10,1)) + ├── flags: ∅ └── body: (length: 5) ├── @ AndNode (location: (1,0)-(1,25)) + │ ├── flags: newline │ ├── left: │ │ @ DefinedNode (location: (1,0)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── lparen_loc: ∅ │ │ ├── value: │ │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── rparen_loc: ∅ │ │ └── keyword_loc: (1,0)-(1,8) = "defined?" │ ├── right: │ │ @ DefinedNode (location: (1,15)-(1,25)) + │ │ ├── flags: ∅ │ │ ├── lparen_loc: ∅ │ │ ├── value: │ │ │ @ IntegerNode (location: (1,24)-(1,25)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── rparen_loc: ∅ │ │ └── keyword_loc: (1,15)-(1,23) = "defined?" │ └── operator_loc: (1,11)-(1,14) = "and" ├── @ DefinedNode (location: (3,0)-(3,16)) + │ ├── flags: newline │ ├── lparen_loc: (3,8)-(3,9) = "(" │ ├── value: │ │ @ LocalVariableOperatorWriteNode (location: (3,9)-(3,15)) + │ │ ├── flags: ∅ │ │ ├── name_loc: (3,9)-(3,10) = "x" - │ │ ├── operator_loc: (3,11)-(3,13) = "%=" + │ │ ├── binary_operator_loc: (3,11)-(3,13) = "%=" │ │ ├── value: │ │ │ @ IntegerNode (location: (3,14)-(3,15)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── name: :x - │ │ ├── operator: :% + │ │ ├── binary_operator: :% │ │ └── depth: 0 │ ├── rparen_loc: (3,15)-(3,16) = ")" │ └── keyword_loc: (3,0)-(3,8) = "defined?" ├── @ DefinedNode (location: (5,0)-(5,21)) + │ ├── flags: newline │ ├── lparen_loc: (5,8)-(5,9) = "(" │ ├── value: │ │ @ AndNode (location: (5,9)-(5,20)) + │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ CallNode (location: (5,9)-(5,12)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -68,14 +77,16 @@ │ ├── rparen_loc: (5,20)-(5,21) = ")" │ └── keyword_loc: (5,0)-(5,8) = "defined?" ├── @ DefinedNode (location: (7,0)-(7,10)) + │ ├── flags: newline │ ├── lparen_loc: ∅ │ ├── value: │ │ @ IntegerNode (location: (7,9)-(7,10)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── rparen_loc: ∅ │ └── keyword_loc: (7,0)-(7,8) = "defined?" └── @ DefinedNode (location: (9,0)-(10,1)) + ├── flags: newline ├── lparen_loc: (9,8)-(9,9) = "(" ├── value: │ @ StringNode (location: (9,9)-(9,14)) diff --git a/test/prism/snapshots/dos_endings.txt b/test/prism/snapshots/dos_endings.txt index 1ae15e1e87c..69d6b7cd7e5 100644 --- a/test/prism/snapshots/dos_endings.txt +++ b/test/prism/snapshots/dos_endings.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(17,20)) +├── flags: ∅ ├── locals: [:x, :a] └── statements: @ StatementsNode (location: (1,0)-(17,20)) + ├── flags: ∅ └── body: (length: 5) ├── @ CallNode (location: (1,0)-(2,12)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :puts @@ -15,17 +17,17 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ InterpolatedStringNode (location: (1,5)-(2,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── opening_loc: ∅ │ │ ├── parts: (length: 2) │ │ │ ├── @ StringNode (location: (1,5)-(1,9)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: (1,5)-(1,6) = "\"" │ │ │ │ ├── content_loc: (1,6)-(1,8) = "hi" │ │ │ │ ├── closing_loc: (1,8)-(1,9) = "\"" │ │ │ │ └── unescaped: "hi" │ │ │ └── @ StringNode (location: (2,5)-(2,12)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: (2,5)-(2,6) = "\"" │ │ │ ├── content_loc: (2,6)-(2,11) = "there" │ │ │ ├── closing_loc: (2,11)-(2,12) = "\"" @@ -34,10 +36,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ ArrayNode (location: (4,0)-(5,2)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 1) │ │ └── @ SymbolNode (location: (4,3)-(5,1)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (4,3)-(5,1) = "a\\\r\nb" │ │ ├── closing_loc: ∅ @@ -45,12 +47,13 @@ │ ├── opening_loc: (4,0)-(4,3) = "%I{" │ └── closing_loc: (5,1)-(5,2) = "}" ├── @ StringNode (location: (7,0)-(7,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (7,0)-(7,4) = "<<-E" │ ├── content_loc: (8,0)-(11,0) = " 1 \\\r\n 2\r\n 3\r\n" │ ├── closing_loc: (11,0)-(12,0) = "E\r\n" │ └── unescaped: " 1 2\n 3\n" ├── @ LocalVariableWriteNode (location: (13,0)-(15,0)) + │ ├── flags: newline │ ├── name: :x │ ├── depth: 0 │ ├── name_loc: (13,0)-(13,1) = "x" @@ -63,6 +66,7 @@ │ │ └── unescaped: "" │ └── operator_loc: (13,2)-(13,3) = "=" └── @ LocalVariableWriteNode (location: (17,0)-(17,20)) + ├── flags: newline ├── name: :a ├── depth: 0 ├── name_loc: (17,0)-(17,1) = "a" @@ -82,17 +86,17 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ InterpolatedStringNode (location: (17,8)-(17,14)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: static_literal │ │ │ ├── opening_loc: (17,8)-(17,14) = "<<~EOF" │ │ │ ├── parts: (length: 2) │ │ │ │ ├── @ StringNode (location: (18,0)-(19,0)) - │ │ │ │ │ ├── flags: frozen + │ │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── content_loc: (18,0)-(19,0) = "\r\n" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "\n" │ │ │ │ └── @ StringNode (location: (19,0)-(20,0)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (19,0)-(20,0) = " baz\r\n" │ │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/dstring.txt b/test/prism/snapshots/dstring.txt index 3978a2f0879..b3ece405137 100644 --- a/test/prism/snapshots/dstring.txt +++ b/test/prism/snapshots/dstring.txt @@ -1,28 +1,32 @@ @ ProgramNode (location: (1,0)-(29,1)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(29,1)) + ├── flags: ∅ └── body: (length: 8) ├── @ StringNode (location: (1,0)-(2,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (1,0)-(1,1) = "\"" │ ├── content_loc: (1,1)-(2,5) = "foo\n bar" │ ├── closing_loc: (2,5)-(2,6) = "\"" │ └── unescaped: "foo\n bar" ├── @ InterpolatedStringNode (location: (4,0)-(5,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (4,0)-(4,1) = "\"" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (4,1)-(5,2)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (4,1)-(5,2) = "foo\n " │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "foo\n " │ │ └── @ EmbeddedStatementsNode (location: (5,2)-(5,8)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (5,2)-(5,4) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (5,4)-(5,7)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (5,4)-(5,7)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -37,48 +41,48 @@ │ │ └── closing_loc: (5,7)-(5,8) = "}" │ └── closing_loc: (5,8)-(5,9) = "\"" ├── @ InterpolatedStringNode (location: (7,0)-(9,2)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── opening_loc: ∅ │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (7,0)-(8,2)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: (7,0)-(7,1) = "\"" │ │ │ ├── content_loc: (7,1)-(8,1) = "fo\no" │ │ │ ├── closing_loc: (8,1)-(8,2) = "\"" │ │ │ └── unescaped: "fo\no" │ │ └── @ StringNode (location: (8,3)-(9,2)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: (8,3)-(8,4) = "\"" │ │ ├── content_loc: (8,4)-(9,1) = "ba\nr" │ │ ├── closing_loc: (9,1)-(9,2) = "\"" │ │ └── unescaped: "ba\nr" │ └── closing_loc: ∅ ├── @ StringNode (location: (11,0)-(13,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (11,0)-(11,1) = "\"" │ ├── content_loc: (11,1)-(13,0) = "\nfoo\\\n" │ ├── closing_loc: (13,0)-(13,1) = "\"" │ └── unescaped: "\nfoo" ├── @ StringNode (location: (15,0)-(17,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (15,0)-(15,1) = "\"" │ ├── content_loc: (15,1)-(17,0) = "\nfoo\\\\\n" │ ├── closing_loc: (17,0)-(17,1) = "\"" │ └── unescaped: "\nfoo\\\n" ├── @ StringNode (location: (19,0)-(21,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (19,0)-(19,1) = "\"" │ ├── content_loc: (19,1)-(21,0) = "\nfoo\\\\\\\n" │ ├── closing_loc: (21,0)-(21,1) = "\"" │ └── unescaped: "\nfoo\\" ├── @ StringNode (location: (23,0)-(25,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (23,0)-(23,1) = "\"" │ ├── content_loc: (23,1)-(25,0) = "\nfoo\\\\\\\\\n" │ ├── closing_loc: (25,0)-(25,1) = "\"" │ └── unescaped: "\nfoo\\\\\n" └── @ StringNode (location: (27,0)-(29,1)) - ├── flags: ∅ + ├── flags: newline ├── opening_loc: (27,0)-(27,1) = "\"" ├── content_loc: (27,1)-(29,0) = "\nfoo\\\\\\\\\\\n" ├── closing_loc: (29,0)-(29,1) = "\"" diff --git a/test/prism/snapshots/dsym_str.txt b/test/prism/snapshots/dsym_str.txt index 33a5e2da21c..835cbbdc8a7 100644 --- a/test/prism/snapshots/dsym_str.txt +++ b/test/prism/snapshots/dsym_str.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(2,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(2,6)) + ├── flags: ∅ └── body: (length: 1) └── @ SymbolNode (location: (1,0)-(2,6)) - ├── flags: forced_us_ascii_encoding + ├── flags: newline, static_literal, forced_us_ascii_encoding ├── opening_loc: (1,0)-(1,2) = ":\"" ├── value_loc: (1,2)-(2,5) = "foo\n bar" ├── closing_loc: (2,5)-(2,6) = "\"" diff --git a/test/prism/snapshots/embdoc_no_newline_at_end.txt b/test/prism/snapshots/embdoc_no_newline_at_end.txt index 3a21ce5559c..5756285aaf2 100644 --- a/test/prism/snapshots/embdoc_no_newline_at_end.txt +++ b/test/prism/snapshots/embdoc_no_newline_at_end.txt @@ -1,5 +1,7 @@ @ ProgramNode (location: (1,0)-(1,0)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,0)) + ├── flags: ∅ └── body: (length: 0) diff --git a/test/prism/snapshots/emoji_method_calls.txt b/test/prism/snapshots/emoji_method_calls.txt index 8f71181ac15..f6f1bc4162a 100644 --- a/test/prism/snapshots/emoji_method_calls.txt +++ b/test/prism/snapshots/emoji_method_calls.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,12)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,12)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,12)) - ├── flags: attribute_write + ├── flags: newline, attribute_write ├── receiver: │ @ CallNode (location: (1,0)-(1,3)) │ ├── flags: variable_call, ignore_visibility @@ -25,7 +27,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,11)-(1,12)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/endless_methods.txt b/test/prism/snapshots/endless_methods.txt index 6e20c0deec6..29f701ed173 100644 --- a/test/prism/snapshots/endless_methods.txt +++ b/test/prism/snapshots/endless_methods.txt @@ -1,18 +1,22 @@ @ ProgramNode (location: (1,0)-(5,22)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(5,22)) + ├── flags: ∅ └── body: (length: 3) ├── @ DefNode (location: (1,0)-(1,11)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (1,4)-(1,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,10)-(1,11)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── locals: [] │ ├── def_keyword_loc: (1,0)-(1,3) = "def" @@ -22,12 +26,14 @@ │ ├── equal_loc: (1,8)-(1,9) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (3,0)-(3,14)) + │ ├── flags: newline │ ├── name: :bar │ ├── name_loc: (3,4)-(3,7) = "bar" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (3,10)-(3,14)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (3,10)-(3,14)) │ │ ├── flags: ignore_visibility @@ -56,12 +62,14 @@ │ ├── equal_loc: (3,8)-(3,9) = "=" │ └── end_keyword_loc: ∅ └── @ DefNode (location: (5,0)-(5,22)) + ├── flags: newline ├── name: :method ├── name_loc: (5,4)-(5,10) = "method" ├── receiver: ∅ ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (5,13)-(5,22)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (5,13)-(5,22)) │ ├── flags: ∅ @@ -70,7 +78,7 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (5,13)-(5,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :+ @@ -81,7 +89,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (5,17)-(5,18)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ @@ -94,7 +102,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (5,21)-(5,22)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ ├── closing_loc: ∅ │ └── block: ∅ diff --git a/test/prism/snapshots/endless_range_in_conditional.txt b/test/prism/snapshots/endless_range_in_conditional.txt index 1802c4faed6..e3b0df74080 100644 --- a/test/prism/snapshots/endless_range_in_conditional.txt +++ b/test/prism/snapshots/endless_range_in_conditional.txt @@ -1,53 +1,58 @@ @ ProgramNode (location: (1,0)-(3,12)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,12)) + ├── flags: ∅ └── body: (length: 3) ├── @ IfNode (location: (1,0)-(1,13)) + │ ├── flags: newline │ ├── if_keyword_loc: (1,0)-(1,2) = "if" │ ├── predicate: │ │ @ FlipFlopNode (location: (1,3)-(1,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (1,3)-(1,4)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ IntegerNode (location: (1,6)-(1,7)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: (1,4)-(1,6) = ".." │ ├── then_keyword_loc: ∅ │ ├── statements: ∅ - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: (1,10)-(1,13) = "end" ├── @ IfNode (location: (2,0)-(2,12)) + │ ├── flags: newline │ ├── if_keyword_loc: (2,0)-(2,2) = "if" │ ├── predicate: │ │ @ FlipFlopNode (location: (2,3)-(2,6)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: ∅ │ │ ├── right: │ │ │ @ IntegerNode (location: (2,5)-(2,6)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── operator_loc: (2,3)-(2,5) = ".." │ ├── then_keyword_loc: ∅ │ ├── statements: ∅ - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: (2,9)-(2,12) = "end" └── @ IfNode (location: (3,0)-(3,12)) + ├── flags: newline ├── if_keyword_loc: (3,0)-(3,2) = "if" ├── predicate: │ @ FlipFlopNode (location: (3,3)-(3,6)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── left: │ │ @ IntegerNode (location: (3,3)-(3,4)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── right: ∅ │ └── operator_loc: (3,4)-(3,6) = ".." ├── then_keyword_loc: ∅ ├── statements: ∅ - ├── consequent: ∅ + ├── subsequent: ∅ └── end_keyword_loc: (3,9)-(3,12) = "end" diff --git a/test/prism/snapshots/for.txt b/test/prism/snapshots/for.txt index cc4bbc1166f..5558209826f 100644 --- a/test/prism/snapshots/for.txt +++ b/test/prism/snapshots/for.txt @@ -1,29 +1,35 @@ @ ProgramNode (location: (1,0)-(19,22)) +├── flags: ∅ ├── locals: [:i, :j, :k] └── statements: @ StatementsNode (location: (1,0)-(19,22)) + ├── flags: ∅ └── body: (length: 6) ├── @ ForNode (location: (1,0)-(3,3)) + │ ├── flags: newline │ ├── index: │ │ @ LocalVariableTargetNode (location: (1,4)-(1,5)) + │ │ ├── flags: ∅ │ │ ├── name: :i │ │ └── depth: 0 │ ├── collection: │ │ @ RangeNode (location: (1,9)-(1,14)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ IntegerNode (location: (1,12)-(1,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 10 │ │ └── operator_loc: (1,10)-(1,12) = ".." │ ├── statements: │ │ @ StatementsNode (location: (2,0)-(2,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (2,0)-(2,1)) + │ │ ├── flags: newline │ │ ├── name: :i │ │ └── depth: 0 │ ├── for_keyword_loc: (1,0)-(1,3) = "for" @@ -31,26 +37,30 @@ │ ├── do_keyword_loc: ∅ │ └── end_keyword_loc: (3,0)-(3,3) = "end" ├── @ ForNode (location: (5,0)-(5,22)) + │ ├── flags: newline │ ├── index: │ │ @ LocalVariableTargetNode (location: (5,4)-(5,5)) + │ │ ├── flags: ∅ │ │ ├── name: :i │ │ └── depth: 0 │ ├── collection: │ │ @ RangeNode (location: (5,9)-(5,14)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (5,9)-(5,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ IntegerNode (location: (5,12)-(5,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 10 │ │ └── operator_loc: (5,10)-(5,12) = ".." │ ├── statements: │ │ @ StatementsNode (location: (5,16)-(5,17)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (5,16)-(5,17)) + │ │ ├── flags: newline │ │ ├── name: :i │ │ └── depth: 0 │ ├── for_keyword_loc: (5,0)-(5,3) = "for" @@ -58,13 +68,17 @@ │ ├── do_keyword_loc: ∅ │ └── end_keyword_loc: (5,19)-(5,22) = "end" ├── @ ForNode (location: (7,0)-(9,3)) + │ ├── flags: newline │ ├── index: │ │ @ MultiTargetNode (location: (7,4)-(7,7)) + │ │ ├── flags: ∅ │ │ ├── lefts: (length: 2) │ │ │ ├── @ LocalVariableTargetNode (location: (7,4)-(7,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :i │ │ │ │ └── depth: 0 │ │ │ └── @ LocalVariableTargetNode (location: (7,6)-(7,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :j │ │ │ └── depth: 0 │ │ ├── rest: ∅ @@ -73,20 +87,22 @@ │ │ └── rparen_loc: ∅ │ ├── collection: │ │ @ RangeNode (location: (7,11)-(7,16)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (7,11)-(7,12)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ IntegerNode (location: (7,14)-(7,16)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 10 │ │ └── operator_loc: (7,12)-(7,14) = ".." │ ├── statements: │ │ @ StatementsNode (location: (8,0)-(8,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (8,0)-(8,1)) + │ │ ├── flags: newline │ │ ├── name: :i │ │ └── depth: 0 │ ├── for_keyword_loc: (7,0)-(7,3) = "for" @@ -94,16 +110,21 @@ │ ├── do_keyword_loc: ∅ │ └── end_keyword_loc: (9,0)-(9,3) = "end" ├── @ ForNode (location: (11,0)-(13,3)) + │ ├── flags: newline │ ├── index: │ │ @ MultiTargetNode (location: (11,4)-(11,9)) + │ │ ├── flags: ∅ │ │ ├── lefts: (length: 3) │ │ │ ├── @ LocalVariableTargetNode (location: (11,4)-(11,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :i │ │ │ │ └── depth: 0 │ │ │ ├── @ LocalVariableTargetNode (location: (11,6)-(11,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :j │ │ │ │ └── depth: 0 │ │ │ └── @ LocalVariableTargetNode (location: (11,8)-(11,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :k │ │ │ └── depth: 0 │ │ ├── rest: ∅ @@ -112,20 +133,22 @@ │ │ └── rparen_loc: ∅ │ ├── collection: │ │ @ RangeNode (location: (11,13)-(11,18)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (11,13)-(11,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ IntegerNode (location: (11,16)-(11,18)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 10 │ │ └── operator_loc: (11,14)-(11,16) = ".." │ ├── statements: │ │ @ StatementsNode (location: (12,0)-(12,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (12,0)-(12,1)) + │ │ ├── flags: newline │ │ ├── name: :i │ │ └── depth: 0 │ ├── for_keyword_loc: (11,0)-(11,3) = "for" @@ -133,26 +156,30 @@ │ ├── do_keyword_loc: ∅ │ └── end_keyword_loc: (13,0)-(13,3) = "end" ├── @ ForNode (location: (15,0)-(17,3)) + │ ├── flags: newline │ ├── index: │ │ @ LocalVariableTargetNode (location: (15,4)-(15,5)) + │ │ ├── flags: ∅ │ │ ├── name: :i │ │ └── depth: 0 │ ├── collection: │ │ @ RangeNode (location: (15,9)-(15,14)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (15,9)-(15,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ IntegerNode (location: (15,12)-(15,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 10 │ │ └── operator_loc: (15,10)-(15,12) = ".." │ ├── statements: │ │ @ StatementsNode (location: (16,0)-(16,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (16,0)-(16,1)) + │ │ ├── flags: newline │ │ ├── name: :i │ │ └── depth: 0 │ ├── for_keyword_loc: (15,0)-(15,3) = "for" @@ -160,26 +187,30 @@ │ ├── do_keyword_loc: (15,15)-(15,17) = "do" │ └── end_keyword_loc: (17,0)-(17,3) = "end" └── @ ForNode (location: (19,0)-(19,22)) + ├── flags: newline ├── index: │ @ LocalVariableTargetNode (location: (19,4)-(19,5)) + │ ├── flags: ∅ │ ├── name: :i │ └── depth: 0 ├── collection: │ @ RangeNode (location: (19,9)-(19,14)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── left: │ │ @ IntegerNode (location: (19,9)-(19,10)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (19,12)-(19,14)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 10 │ └── operator_loc: (19,10)-(19,12) = ".." ├── statements: │ @ StatementsNode (location: (19,16)-(19,17)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ LocalVariableReadNode (location: (19,16)-(19,17)) + │ ├── flags: newline │ ├── name: :i │ └── depth: 0 ├── for_keyword_loc: (19,0)-(19,3) = "for" diff --git a/test/prism/snapshots/global_variables.txt b/test/prism/snapshots/global_variables.txt index 9f775ed80d3..17b7728a32d 100644 --- a/test/prism/snapshots/global_variables.txt +++ b/test/prism/snapshots/global_variables.txt @@ -1,190 +1,216 @@ @ ProgramNode (location: (1,0)-(93,4)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(93,4)) + ├── flags: ∅ └── body: (length: 47) ├── @ GlobalVariableReadNode (location: (1,0)-(1,16)) + │ ├── flags: newline │ └── name: :$global_variable ├── @ GlobalVariableReadNode (location: (3,0)-(3,2)) + │ ├── flags: newline │ └── name: :$_ ├── @ GlobalVariableReadNode (location: (5,0)-(5,3)) + │ ├── flags: newline │ └── name: :$-w ├── @ GlobalVariableReadNode (location: (7,0)-(7,10)) + │ ├── flags: newline │ └── name: :$LOAD_PATH ├── @ GlobalVariableReadNode (location: (9,0)-(9,6)) + │ ├── flags: newline │ └── name: :$stdin ├── @ GlobalVariableReadNode (location: (11,0)-(11,7)) + │ ├── flags: newline │ └── name: :$stdout ├── @ GlobalVariableReadNode (location: (13,0)-(13,7)) + │ ├── flags: newline │ └── name: :$stderr ├── @ GlobalVariableReadNode (location: (15,0)-(15,2)) + │ ├── flags: newline │ └── name: :$! ├── @ GlobalVariableReadNode (location: (17,0)-(17,2)) + │ ├── flags: newline │ └── name: :$? ├── @ GlobalVariableReadNode (location: (19,0)-(19,2)) + │ ├── flags: newline │ └── name: :$~ ├── @ BackReferenceReadNode (location: (21,0)-(21,2)) + │ ├── flags: newline │ └── name: :$& ├── @ BackReferenceReadNode (location: (23,0)-(23,2)) + │ ├── flags: newline │ └── name: :$` ├── @ BackReferenceReadNode (location: (25,0)-(25,2)) + │ ├── flags: newline │ └── name: :$' ├── @ BackReferenceReadNode (location: (27,0)-(27,2)) + │ ├── flags: newline │ └── name: :$+ ├── @ GlobalVariableReadNode (location: (29,0)-(29,2)) + │ ├── flags: newline │ └── name: :$: ├── @ GlobalVariableReadNode (location: (31,0)-(31,2)) + │ ├── flags: newline │ └── name: :$; ├── @ GlobalVariableReadNode (location: (33,0)-(33,2)) + │ ├── flags: newline │ └── name: :$, ├── @ GlobalVariableReadNode (location: (35,0)-(35,6)) + │ ├── flags: newline │ └── name: :$DEBUG ├── @ GlobalVariableReadNode (location: (37,0)-(37,9)) + │ ├── flags: newline │ └── name: :$FILENAME ├── @ GlobalVariableReadNode (location: (39,0)-(39,2)) + │ ├── flags: newline │ └── name: :$0 ├── @ GlobalVariableReadNode (location: (41,0)-(41,3)) + │ ├── flags: newline │ └── name: :$-0 ├── @ GlobalVariableReadNode (location: (43,0)-(43,16)) + │ ├── flags: newline │ └── name: :$LOADED_FEATURES ├── @ GlobalVariableReadNode (location: (45,0)-(45,8)) + │ ├── flags: newline │ └── name: :$VERBOSE ├── @ GlobalVariableReadNode (location: (47,0)-(47,3)) + │ ├── flags: newline │ └── name: :$-K ├── @ SymbolNode (location: (49,0)-(49,17)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (49,0)-(49,1) = ":" │ ├── value_loc: (49,1)-(49,17) = "$global_variable" │ ├── closing_loc: ∅ │ └── unescaped: "$global_variable" ├── @ SymbolNode (location: (51,0)-(51,3)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (51,0)-(51,1) = ":" │ ├── value_loc: (51,1)-(51,3) = "$_" │ ├── closing_loc: ∅ │ └── unescaped: "$_" ├── @ SymbolNode (location: (53,0)-(53,4)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (53,0)-(53,1) = ":" │ ├── value_loc: (53,1)-(53,4) = "$-w" │ ├── closing_loc: ∅ │ └── unescaped: "$-w" ├── @ SymbolNode (location: (55,0)-(55,11)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (55,0)-(55,1) = ":" │ ├── value_loc: (55,1)-(55,11) = "$LOAD_PATH" │ ├── closing_loc: ∅ │ └── unescaped: "$LOAD_PATH" ├── @ SymbolNode (location: (57,0)-(57,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (57,0)-(57,1) = ":" │ ├── value_loc: (57,1)-(57,7) = "$stdin" │ ├── closing_loc: ∅ │ └── unescaped: "$stdin" ├── @ SymbolNode (location: (59,0)-(59,8)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (59,0)-(59,1) = ":" │ ├── value_loc: (59,1)-(59,8) = "$stdout" │ ├── closing_loc: ∅ │ └── unescaped: "$stdout" ├── @ SymbolNode (location: (61,0)-(61,8)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (61,0)-(61,1) = ":" │ ├── value_loc: (61,1)-(61,8) = "$stderr" │ ├── closing_loc: ∅ │ └── unescaped: "$stderr" ├── @ SymbolNode (location: (63,0)-(63,3)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (63,0)-(63,1) = ":" │ ├── value_loc: (63,1)-(63,3) = "$!" │ ├── closing_loc: ∅ │ └── unescaped: "$!" ├── @ SymbolNode (location: (65,0)-(65,3)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (65,0)-(65,1) = ":" │ ├── value_loc: (65,1)-(65,3) = "$?" │ ├── closing_loc: ∅ │ └── unescaped: "$?" ├── @ SymbolNode (location: (67,0)-(67,3)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (67,0)-(67,1) = ":" │ ├── value_loc: (67,1)-(67,3) = "$~" │ ├── closing_loc: ∅ │ └── unescaped: "$~" ├── @ SymbolNode (location: (69,0)-(69,3)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (69,0)-(69,1) = ":" │ ├── value_loc: (69,1)-(69,3) = "$&" │ ├── closing_loc: ∅ │ └── unescaped: "$&" ├── @ SymbolNode (location: (71,0)-(71,3)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (71,0)-(71,1) = ":" │ ├── value_loc: (71,1)-(71,3) = "$`" │ ├── closing_loc: ∅ │ └── unescaped: "$`" ├── @ SymbolNode (location: (73,0)-(73,3)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (73,0)-(73,1) = ":" │ ├── value_loc: (73,1)-(73,3) = "$'" │ ├── closing_loc: ∅ │ └── unescaped: "$'" ├── @ SymbolNode (location: (75,0)-(75,3)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (75,0)-(75,1) = ":" │ ├── value_loc: (75,1)-(75,3) = "$+" │ ├── closing_loc: ∅ │ └── unescaped: "$+" ├── @ SymbolNode (location: (77,0)-(77,3)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (77,0)-(77,1) = ":" │ ├── value_loc: (77,1)-(77,3) = "$:" │ ├── closing_loc: ∅ │ └── unescaped: "$:" ├── @ SymbolNode (location: (79,0)-(79,3)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (79,0)-(79,1) = ":" │ ├── value_loc: (79,1)-(79,3) = "$;" │ ├── closing_loc: ∅ │ └── unescaped: "$;" ├── @ SymbolNode (location: (81,0)-(81,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (81,0)-(81,1) = ":" │ ├── value_loc: (81,1)-(81,7) = "$DEBUG" │ ├── closing_loc: ∅ │ └── unescaped: "$DEBUG" ├── @ SymbolNode (location: (83,0)-(83,10)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (83,0)-(83,1) = ":" │ ├── value_loc: (83,1)-(83,10) = "$FILENAME" │ ├── closing_loc: ∅ │ └── unescaped: "$FILENAME" ├── @ SymbolNode (location: (85,0)-(85,3)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (85,0)-(85,1) = ":" │ ├── value_loc: (85,1)-(85,3) = "$0" │ ├── closing_loc: ∅ │ └── unescaped: "$0" ├── @ SymbolNode (location: (87,0)-(87,4)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (87,0)-(87,1) = ":" │ ├── value_loc: (87,1)-(87,4) = "$-0" │ ├── closing_loc: ∅ │ └── unescaped: "$-0" ├── @ SymbolNode (location: (89,0)-(89,17)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (89,0)-(89,1) = ":" │ ├── value_loc: (89,1)-(89,17) = "$LOADED_FEATURES" │ ├── closing_loc: ∅ │ └── unescaped: "$LOADED_FEATURES" ├── @ SymbolNode (location: (91,0)-(91,9)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (91,0)-(91,1) = ":" │ ├── value_loc: (91,1)-(91,9) = "$VERBOSE" │ ├── closing_loc: ∅ │ └── unescaped: "$VERBOSE" └── @ SymbolNode (location: (93,0)-(93,4)) - ├── flags: forced_us_ascii_encoding + ├── flags: newline, static_literal, forced_us_ascii_encoding ├── opening_loc: (93,0)-(93,1) = ":" ├── value_loc: (93,1)-(93,4) = "$-K" ├── closing_loc: ∅ diff --git a/test/prism/snapshots/hashes.txt b/test/prism/snapshots/hashes.txt index 7a3ac4b0eaa..8462c28994e 100644 --- a/test/prism/snapshots/hashes.txt +++ b/test/prism/snapshots/hashes.txt @@ -1,20 +1,26 @@ @ ProgramNode (location: (1,0)-(28,9)) +├── flags: ∅ ├── locals: [:a] └── statements: @ StatementsNode (location: (1,0)-(28,9)) + ├── flags: ∅ └── body: (length: 10) ├── @ HashNode (location: (1,0)-(1,2)) + │ ├── flags: newline, static_literal │ ├── opening_loc: (1,0)-(1,1) = "{" │ ├── elements: (length: 0) │ └── closing_loc: (1,1)-(1,2) = "}" ├── @ HashNode (location: (3,0)-(4,1)) + │ ├── flags: newline, static_literal │ ├── opening_loc: (3,0)-(3,1) = "{" │ ├── elements: (length: 0) │ └── closing_loc: (4,0)-(4,1) = "}" ├── @ HashNode (location: (6,0)-(6,18)) + │ ├── flags: newline │ ├── opening_loc: (6,0)-(6,1) = "{" │ ├── elements: (length: 2) │ │ ├── @ AssocNode (location: (6,2)-(6,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ CallNode (location: (6,2)-(6,3)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -39,6 +45,7 @@ │ │ │ │ └── block: ∅ │ │ │ └── operator_loc: (6,4)-(6,6) = "=>" │ │ └── @ AssocNode (location: (6,10)-(6,16)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ CallNode (location: (6,10)-(6,11)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -64,9 +71,11 @@ │ │ └── operator_loc: (6,12)-(6,14) = "=>" │ └── closing_loc: (6,17)-(6,18) = "}" ├── @ HashNode (location: (8,0)-(8,15)) + │ ├── flags: newline │ ├── opening_loc: (8,0)-(8,1) = "{" │ ├── elements: (length: 2) │ │ ├── @ AssocNode (location: (8,2)-(8,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ CallNode (location: (8,2)-(8,3)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -91,6 +100,7 @@ │ │ │ │ └── block: ∅ │ │ │ └── operator_loc: (8,4)-(8,6) = "=>" │ │ └── @ AssocSplatNode (location: (8,10)-(8,13)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ CallNode (location: (8,12)-(8,13)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -105,12 +115,14 @@ │ │ └── operator_loc: (8,10)-(8,12) = "**" │ └── closing_loc: (8,14)-(8,15) = "}" ├── @ HashNode (location: (10,0)-(16,5)) + │ ├── flags: newline │ ├── opening_loc: (10,0)-(10,1) = "{" │ ├── elements: (length: 2) │ │ ├── @ AssocNode (location: (11,6)-(11,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (11,6)-(11,8)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (11,6)-(11,7) = "a" │ │ │ │ ├── closing_loc: (11,7)-(11,8) = ":" @@ -128,9 +140,10 @@ │ │ │ │ └── block: ∅ │ │ │ └── operator_loc: ∅ │ │ └── @ AssocNode (location: (12,6)-(12,10)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ SymbolNode (location: (12,6)-(12,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (12,6)-(12,7) = "c" │ │ │ ├── closing_loc: (12,7)-(12,8) = ":" @@ -149,12 +162,14 @@ │ │ └── operator_loc: ∅ │ └── closing_loc: (16,4)-(16,5) = "}" ├── @ HashNode (location: (18,0)-(18,25)) + │ ├── flags: newline │ ├── opening_loc: (18,0)-(18,1) = "{" │ ├── elements: (length: 4) │ │ ├── @ AssocNode (location: (18,2)-(18,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (18,2)-(18,4)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (18,2)-(18,3) = "a" │ │ │ │ ├── closing_loc: (18,3)-(18,4) = ":" @@ -172,9 +187,10 @@ │ │ │ │ └── block: ∅ │ │ │ └── operator_loc: ∅ │ │ ├── @ AssocNode (location: (18,8)-(18,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (18,8)-(18,10)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (18,8)-(18,9) = "c" │ │ │ │ ├── closing_loc: (18,9)-(18,10) = ":" @@ -192,6 +208,7 @@ │ │ │ │ └── block: ∅ │ │ │ └── operator_loc: ∅ │ │ ├── @ AssocSplatNode (location: (18,14)-(18,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── value: │ │ │ │ @ CallNode (location: (18,16)-(18,17)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -205,9 +222,10 @@ │ │ │ │ └── block: ∅ │ │ │ └── operator_loc: (18,14)-(18,16) = "**" │ │ └── @ AssocNode (location: (18,19)-(18,23)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ SymbolNode (location: (18,19)-(18,21)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (18,19)-(18,20) = "f" │ │ │ ├── closing_loc: (18,20)-(18,21) = ":" @@ -226,12 +244,14 @@ │ │ └── operator_loc: ∅ │ └── closing_loc: (18,24)-(18,25) = "}" ├── @ HashNode (location: (20,0)-(20,12)) + │ ├── flags: newline │ ├── opening_loc: (20,0)-(20,1) = "{" │ ├── elements: (length: 1) │ │ └── @ AssocNode (location: (20,2)-(20,10)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ SymbolNode (location: (20,2)-(20,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (20,2)-(20,3) = "\"" │ │ │ ├── value_loc: (20,3)-(20,4) = "a" │ │ │ ├── closing_loc: (20,4)-(20,6) = "\":" @@ -260,16 +280,17 @@ │ │ └── operator_loc: ∅ │ └── closing_loc: (20,11)-(20,12) = "}" ├── @ LocalVariableWriteNode (location: (22,0)-(22,5)) + │ ├── flags: newline │ ├── name: :a │ ├── depth: 0 │ ├── name_loc: (22,0)-(22,1) = "a" │ ├── value: │ │ @ IntegerNode (location: (22,4)-(22,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (22,2)-(22,3) = "=" ├── @ CallNode (location: (23,0)-(26,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -279,63 +300,75 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (23,4)-(26,3)) + │ ├── flags: ∅ │ ├── locals: [:b] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (24,2)-(25,20)) + │ │ ├── flags: ∅ │ │ └── body: (length: 2) │ │ ├── @ LocalVariableWriteNode (location: (24,2)-(24,7)) + │ │ │ ├── flags: newline │ │ │ ├── name: :b │ │ │ ├── depth: 0 │ │ │ ├── name_loc: (24,2)-(24,3) = "b" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (24,6)-(24,7)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── operator_loc: (24,4)-(24,5) = "=" │ │ └── @ HashNode (location: (25,2)-(25,20)) + │ │ ├── flags: newline │ │ ├── opening_loc: (25,2)-(25,3) = "{" │ │ ├── elements: (length: 4) │ │ │ ├── @ AssocNode (location: (25,4)-(25,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (25,4)-(25,6)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (25,4)-(25,5) = "a" │ │ │ │ │ ├── closing_loc: (25,5)-(25,6) = ":" │ │ │ │ │ └── unescaped: "a" │ │ │ │ ├── value: │ │ │ │ │ @ ImplicitNode (location: (25,4)-(25,6)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── value: │ │ │ │ │ @ LocalVariableReadNode (location: (25,4)-(25,6)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :a │ │ │ │ │ └── depth: 1 │ │ │ │ └── operator_loc: ∅ │ │ │ ├── @ AssocNode (location: (25,8)-(25,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (25,8)-(25,10)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (25,8)-(25,9) = "b" │ │ │ │ │ ├── closing_loc: (25,9)-(25,10) = ":" │ │ │ │ │ └── unescaped: "b" │ │ │ │ ├── value: │ │ │ │ │ @ ImplicitNode (location: (25,8)-(25,10)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── value: │ │ │ │ │ @ LocalVariableReadNode (location: (25,8)-(25,10)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :b │ │ │ │ │ └── depth: 0 │ │ │ │ └── operator_loc: ∅ │ │ │ ├── @ AssocNode (location: (25,12)-(25,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (25,12)-(25,14)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (25,12)-(25,13) = "c" │ │ │ │ │ ├── closing_loc: (25,13)-(25,14) = ":" │ │ │ │ │ └── unescaped: "c" │ │ │ │ ├── value: │ │ │ │ │ @ ImplicitNode (location: (25,12)-(25,14)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── value: │ │ │ │ │ @ CallNode (location: (25,12)-(25,14)) │ │ │ │ │ ├── flags: ignore_visibility @@ -349,36 +382,41 @@ │ │ │ │ │ └── block: ∅ │ │ │ │ └── operator_loc: ∅ │ │ │ └── @ AssocNode (location: (25,16)-(25,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (25,16)-(25,18)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (25,16)-(25,17) = "D" │ │ │ │ ├── closing_loc: (25,17)-(25,18) = ":" │ │ │ │ └── unescaped: "D" │ │ │ ├── value: │ │ │ │ @ ImplicitNode (location: (25,16)-(25,18)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── value: │ │ │ │ @ ConstantReadNode (location: (25,16)-(25,18)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :D │ │ │ └── operator_loc: ∅ │ │ └── closing_loc: (25,19)-(25,20) = "}" │ ├── opening_loc: (23,4)-(23,6) = "do" │ └── closing_loc: (26,0)-(26,3) = "end" └── @ HashNode (location: (28,0)-(28,9)) + ├── flags: newline, static_literal ├── opening_loc: (28,0)-(28,1) = "{" ├── elements: (length: 1) │ └── @ AssocNode (location: (28,2)-(28,7)) + │ ├── flags: static_literal │ ├── key: │ │ @ SymbolNode (location: (28,2)-(28,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (28,2)-(28,3) = "a" │ │ ├── closing_loc: (28,3)-(28,4) = ":" │ │ └── unescaped: "a" │ ├── value: │ │ @ IntegerNode (location: (28,5)-(28,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: -1 │ └── operator_loc: ∅ └── closing_loc: (28,8)-(28,9) = "}" diff --git a/test/prism/snapshots/heredoc.txt b/test/prism/snapshots/heredoc.txt index 3ca66dd9897..7145f0f7527 100644 --- a/test/prism/snapshots/heredoc.txt +++ b/test/prism/snapshots/heredoc.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ └── body: (length: 1) └── @ StringNode (location: (1,0)-(1,6)) - ├── flags: ∅ + ├── flags: newline ├── opening_loc: (1,0)-(1,6) = "< @@ -307,15 +309,15 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (31,6)-(31,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (33,0)-(33,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ IntegerNode (location: (33,0)-(33,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :== @@ -326,15 +328,15 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (33,5)-(33,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (35,0)-(35,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ IntegerNode (location: (35,0)-(35,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :=== @@ -345,15 +347,15 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (35,6)-(35,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (37,0)-(37,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ IntegerNode (location: (37,0)-(37,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :=~ @@ -364,15 +366,15 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (37,5)-(37,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (39,0)-(39,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ IntegerNode (location: (39,0)-(39,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :> @@ -383,15 +385,15 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (39,4)-(39,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (41,0)-(41,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ IntegerNode (location: (41,0)-(41,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :>= @@ -402,15 +404,15 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (41,5)-(41,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (43,0)-(43,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ IntegerNode (location: (43,0)-(43,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :>> @@ -421,15 +423,15 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (43,5)-(43,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (45,0)-(45,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ IntegerNode (location: (45,0)-(45,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :^ @@ -440,15 +442,15 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (45,4)-(45,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (47,0)-(47,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ IntegerNode (location: (47,0)-(47,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :| @@ -459,35 +461,37 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (47,4)-(47,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ AndNode (location: (49,0)-(49,6)) + │ ├── flags: newline │ ├── left: │ │ @ IntegerNode (location: (49,0)-(49,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (49,5)-(49,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ └── operator_loc: (49,2)-(49,4) = "&&" ├── @ AndNode (location: (51,0)-(51,7)) + │ ├── flags: newline │ ├── left: │ │ @ IntegerNode (location: (51,0)-(51,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (51,6)-(51,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ └── operator_loc: (51,2)-(51,5) = "and" ├── @ CallNode (location: (53,0)-(53,10)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ IntegerNode (location: (53,0)-(53,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :* @@ -501,7 +505,7 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (53,4)-(53,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :** @@ -512,20 +516,20 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (53,9)-(53,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (55,0)-(55,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (55,0)-(55,5)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (55,0)-(55,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :* @@ -536,7 +540,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (55,4)-(55,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ @@ -549,35 +553,37 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (55,8)-(55,9)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ OrNode (location: (57,0)-(57,6)) + │ ├── flags: newline │ ├── left: │ │ @ IntegerNode (location: (57,0)-(57,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (57,5)-(57,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ └── operator_loc: (57,2)-(57,4) = "or" ├── @ OrNode (location: (59,0)-(59,6)) + │ ├── flags: newline │ ├── left: │ │ @ IntegerNode (location: (59,0)-(59,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (59,5)-(59,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ └── operator_loc: (59,2)-(59,4) = "||" ├── @ CallNode (location: (61,0)-(61,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ IntegerNode (location: (61,0)-(61,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :+ @@ -591,7 +597,7 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (61,4)-(61,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :* @@ -602,21 +608,23 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (61,8)-(61,9)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ └── @ ParenthesesNode (location: (63,0)-(63,7)) + ├── flags: newline ├── body: │ @ StatementsNode (location: (63,1)-(63,6)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (63,1)-(63,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ IntegerNode (location: (63,1)-(63,2)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :+ @@ -627,7 +635,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (63,5)-(63,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ diff --git a/test/prism/snapshots/keyword_method_names.txt b/test/prism/snapshots/keyword_method_names.txt index 6d59790b070..6bb4d970845 100644 --- a/test/prism/snapshots/keyword_method_names.txt +++ b/test/prism/snapshots/keyword_method_names.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(29,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(29,3)) + ├── flags: ∅ └── body: (length: 10) ├── @ DefNode (location: (1,0)-(2,3)) + │ ├── flags: newline │ ├── name: :def │ ├── name_loc: (1,4)-(1,7) = "def" │ ├── receiver: ∅ @@ -17,10 +20,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (2,0)-(2,3) = "end" ├── @ DefNode (location: (4,0)-(5,3)) + │ ├── flags: newline │ ├── name: :ensure │ ├── name_loc: (4,9)-(4,15) = "ensure" │ ├── receiver: │ │ @ SelfNode (location: (4,4)-(4,8)) + │ │ └── flags: ∅ │ ├── parameters: ∅ │ ├── body: ∅ │ ├── locals: [] @@ -31,7 +36,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (5,0)-(5,3) = "end" ├── @ CallNode (location: (7,0)-(10,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :private @@ -42,15 +47,17 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ DefNode (location: (7,8)-(10,3)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ ├── name_loc: (7,12)-(7,15) = "foo" │ │ ├── receiver: ∅ │ │ ├── parameters: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (8,2)-(9,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (8,2)-(9,5)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -60,6 +67,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: │ │ │ @ BlockNode (location: (8,6)-(9,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── locals: [] │ │ │ ├── parameters: ∅ │ │ │ ├── body: ∅ @@ -75,11 +83,13 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ DefNode (location: (12,0)-(13,3)) + │ ├── flags: newline │ ├── name: :m │ ├── name_loc: (12,4)-(12,5) = "m" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (12,6)-(12,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (12,6)-(12,7)) │ │ │ ├── flags: ∅ @@ -90,6 +100,7 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ NoKeywordsParameterNode (location: (12,9)-(12,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (12,9)-(12,11) = "**" │ │ │ └── keyword_loc: (12,11)-(12,14) = "nil" │ │ └── block: ∅ @@ -102,10 +113,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (13,0)-(13,3) = "end" ├── @ DefNode (location: (15,0)-(16,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (15,17)-(15,18) = "a" │ ├── receiver: │ │ @ SourceEncodingNode (location: (15,4)-(15,16)) + │ │ └── flags: static_literal │ ├── parameters: ∅ │ ├── body: ∅ │ ├── locals: [] @@ -116,18 +129,19 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (16,0)-(16,3) = "end" ├── @ StringNode (location: (18,0)-(18,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (18,0)-(18,2) = "%{" │ ├── content_loc: (18,2)-(18,5) = "abc" │ ├── closing_loc: (18,5)-(18,6) = "}" │ └── unescaped: "abc" ├── @ StringNode (location: (20,0)-(20,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (20,0)-(20,2) = "%\"" │ ├── content_loc: (20,2)-(20,5) = "abc" │ ├── closing_loc: (20,5)-(20,6) = "\"" │ └── unescaped: "abc" ├── @ DefNode (location: (22,0)-(23,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (22,13)-(22,14) = "a" │ ├── receiver: @@ -144,10 +158,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (23,0)-(23,3) = "end" ├── @ DefNode (location: (25,0)-(26,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (25,13)-(25,14) = "a" │ ├── receiver: │ │ @ SourceLineNode (location: (25,4)-(25,12)) + │ │ └── flags: static_literal │ ├── parameters: ∅ │ ├── body: ∅ │ ├── locals: [] @@ -158,10 +174,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (26,0)-(26,3) = "end" └── @ DefNode (location: (28,0)-(29,3)) + ├── flags: newline ├── name: :a ├── name_loc: (28,9)-(28,10) = "a" ├── receiver: │ @ NilNode (location: (28,4)-(28,7)) + │ └── flags: static_literal ├── parameters: ∅ ├── body: ∅ ├── locals: [] diff --git a/test/prism/snapshots/keywords.txt b/test/prism/snapshots/keywords.txt index b3d5c5e1c38..f7f0b8df09b 100644 --- a/test/prism/snapshots/keywords.txt +++ b/test/prism/snapshots/keywords.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(11,8)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(11,8)) + ├── flags: ∅ └── body: (length: 6) ├── @ CallNode (location: (1,0)-(1,12)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -14,34 +16,44 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (1,4)-(1,12)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,6)-(1,10)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RedoNode (location: (1,6)-(1,10)) + │ │ └── flags: newline │ ├── opening_loc: (1,4)-(1,5) = "{" │ └── closing_loc: (1,11)-(1,12) = "}" ├── @ BeginNode (location: (3,0)-(3,25)) + │ ├── flags: newline │ ├── begin_keyword_loc: (3,0)-(3,5) = "begin" │ ├── statements: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (3,7)-(3,20)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (3,7)-(3,13) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (3,15)-(3,20)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ RetryNode (location: (3,15)-(3,20)) - │ │ └── consequent: ∅ + │ │ │ └── flags: newline + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (3,22)-(3,25) = "end" ├── @ SelfNode (location: (5,0)-(5,4)) + │ └── flags: newline ├── @ SourceEncodingNode (location: (7,0)-(7,12)) + │ └── flags: newline, static_literal ├── @ SourceFileNode (location: (9,0)-(9,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ └── filepath: "keywords.txt" └── @ SourceLineNode (location: (11,0)-(11,8)) + └── flags: newline, static_literal diff --git a/test/prism/snapshots/lambda.txt b/test/prism/snapshots/lambda.txt index 0864b103695..90b0b523aa9 100644 --- a/test/prism/snapshots/lambda.txt +++ b/test/prism/snapshots/lambda.txt @@ -1,17 +1,22 @@ @ ProgramNode (location: (1,0)-(11,18)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(11,18)) + ├── flags: ∅ └── body: (length: 5) ├── @ LambdaNode (location: (1,0)-(3,4)) + │ ├── flags: newline │ ├── locals: [:foo] │ ├── operator_loc: (1,0)-(1,2) = "->" │ ├── opening_loc: (3,2)-(3,3) = "{" │ ├── closing_loc: (3,3)-(3,4) = "}" │ ├── parameters: │ │ @ BlockParametersNode (location: (1,2)-(3,1)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (2,2)-(2,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (2,2)-(2,5)) │ │ │ │ ├── flags: ∅ @@ -27,14 +32,17 @@ │ │ └── closing_loc: (3,0)-(3,1) = ")" │ └── body: ∅ ├── @ LambdaNode (location: (5,0)-(5,18)) + │ ├── flags: newline │ ├── locals: [:x] │ ├── operator_loc: (5,0)-(5,2) = "->" │ ├── opening_loc: (5,15)-(5,16) = "{" │ ├── closing_loc: (5,17)-(5,18) = "}" │ ├── parameters: │ │ @ BlockParametersNode (location: (5,2)-(5,14)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (5,3)-(5,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -50,15 +58,17 @@ │ │ │ │ ├── opening_loc: (5,6)-(5,7) = "\"" │ │ │ │ ├── parts: (length: 2) │ │ │ │ │ ├── @ StringNode (location: (5,7)-(5,8)) - │ │ │ │ │ │ ├── flags: frozen + │ │ │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ │ ├── content_loc: (5,7)-(5,8) = "b" │ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ │ └── unescaped: "b" │ │ │ │ │ └── @ EmbeddedStatementsNode (location: (5,8)-(5,12)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── opening_loc: (5,8)-(5,10) = "\#{" │ │ │ │ │ ├── statements: │ │ │ │ │ │ @ StatementsNode (location: (5,10)-(5,11)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ │ └── @ CallNode (location: (5,10)-(5,11)) │ │ │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -79,14 +89,17 @@ │ │ └── closing_loc: (5,13)-(5,14) = ")" │ └── body: ∅ ├── @ LambdaNode (location: (7,0)-(7,15)) + │ ├── flags: newline │ ├── locals: [:a] │ ├── operator_loc: (7,0)-(7,2) = "->" │ ├── opening_loc: (7,13)-(7,14) = "{" │ ├── closing_loc: (7,14)-(7,15) = "}" │ ├── parameters: │ │ @ BlockParametersNode (location: (7,2)-(7,12)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (7,3)-(7,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -119,7 +132,7 @@ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (7,10)-(7,11)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 3 │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ @@ -130,14 +143,17 @@ │ │ └── closing_loc: (7,11)-(7,12) = ")" │ └── body: ∅ ├── @ LambdaNode (location: (9,0)-(9,19)) + │ ├── flags: newline │ ├── locals: [:foo] │ ├── operator_loc: (9,0)-(9,2) = "->" │ ├── opening_loc: (9,13)-(9,15) = "do" │ ├── closing_loc: (9,16)-(9,19) = "end" │ ├── parameters: │ │ @ BlockParametersNode (location: (9,3)-(9,12)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (9,3)-(9,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (9,3)-(9,12)) @@ -166,14 +182,17 @@ │ │ └── closing_loc: ∅ │ └── body: ∅ └── @ LambdaNode (location: (11,0)-(11,18)) + ├── flags: newline ├── locals: [:foo] ├── operator_loc: (11,0)-(11,2) = "->" ├── opening_loc: (11,12)-(11,14) = "do" ├── closing_loc: (11,15)-(11,18) = "end" ├── parameters: │ @ BlockParametersNode (location: (11,3)-(11,11)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (11,3)-(11,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/method_calls.txt b/test/prism/snapshots/method_calls.txt index 6082b567f7b..dbd8c3172fd 100644 --- a/test/prism/snapshots/method_calls.txt +++ b/test/prism/snapshots/method_calls.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(156,19)) +├── flags: ∅ ├── locals: [:foo] └── statements: @ StatementsNode (location: (1,0)-(156,19)) + ├── flags: ∅ └── body: (length: 67) ├── @ CallNode (location: (1,0)-(1,14)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (1,0)-(1,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -33,7 +35,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (3,0)-(3,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (3,0)-(3,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -76,7 +78,7 @@ │ ├── closing_loc: (3,8)-(3,9) = ")" │ └── block: ∅ ├── @ CallNode (location: (5,0)-(5,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (5,0)-(5,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -96,7 +98,7 @@ │ ├── closing_loc: (5,4)-(5,5) = ")" │ └── block: ∅ ├── @ CallNode (location: (7,0)-(9,7)) - │ ├── flags: safe_navigation + │ ├── flags: newline, safe_navigation │ ├── receiver: │ │ @ CallNode (location: (7,0)-(8,6)) │ │ ├── flags: ∅ @@ -126,7 +128,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (11,0)-(11,2)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a! @@ -136,7 +138,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (13,0)-(13,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (13,0)-(13,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -156,7 +158,7 @@ │ ├── closing_loc: (13,3)-(13,4) = ")" │ └── block: ∅ ├── @ CallNode (location: (15,0)-(15,11)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (15,0)-(15,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -177,18 +179,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 3) │ │ ├── @ IntegerNode (location: (15,3)-(15,4)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── @ IntegerNode (location: (15,6)-(15,7)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── @ IntegerNode (location: (15,9)-(15,10)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ ├── closing_loc: (15,10)-(15,11) = ")" │ └── block: ∅ ├── @ CallNode (location: (17,0)-(17,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (17,0)-(17,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -208,7 +210,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (19,0)-(19,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (19,0)-(19,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -241,7 +243,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (21,0)-(21,11)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ CallNode (location: (21,0)-(21,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -262,12 +264,12 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (21,10)-(21,11)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (23,0)-(23,2)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a? @@ -277,7 +279,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (25,0)-(25,8)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a @@ -287,6 +289,7 @@ │ ├── closing_loc: (25,8)-(25,9) = ")" │ └── block: │ @ BlockArgumentNode (location: (25,2)-(25,8)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (25,3)-(25,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -300,7 +303,7 @@ │ │ └── block: ∅ │ └── operator_loc: (25,2)-(25,3) = "&" ├── @ CallNode (location: (27,0)-(27,11)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a @@ -314,6 +317,7 @@ │ │ ├── flags: ∅ │ │ └── elements: (length: 1) │ │ └── @ AssocSplatNode (location: (27,2)-(27,10)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ CallNode (location: (27,4)-(27,10)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -329,7 +333,7 @@ │ ├── closing_loc: (27,10)-(27,11) = ")" │ └── block: ∅ ├── @ CallNode (location: (29,0)-(29,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (29,0)-(29,3)) │ │ ├── flags: ∅ @@ -359,7 +363,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (31,0)-(31,7)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a @@ -392,7 +396,7 @@ │ ├── closing_loc: (31,6)-(31,7) = ")" │ └── block: ∅ ├── @ CallNode (location: (33,0)-(33,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a @@ -402,7 +406,7 @@ │ ├── closing_loc: (33,2)-(33,3) = ")" │ └── block: ∅ ├── @ CallNode (location: (35,0)-(35,8)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a @@ -410,9 +414,10 @@ │ ├── opening_loc: (35,1)-(35,2) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (35,2)-(35,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat │ │ └── arguments: (length: 1) │ │ └── @ SplatNode (location: (35,2)-(35,7)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (35,2)-(35,3) = "*" │ │ └── expression: │ │ @ CallNode (location: (35,3)-(35,7)) @@ -428,7 +433,7 @@ │ ├── closing_loc: (35,7)-(35,8) = ")" │ └── block: ∅ ├── @ CallNode (location: (37,0)-(37,6)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a @@ -461,7 +466,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (39,0)-(39,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (39,0)-(39,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -504,6 +509,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ MultiWriteNode (location: (41,0)-(41,23)) + │ ├── flags: newline │ ├── lefts: (length: 2) │ │ ├── @ CallTargetNode (location: (41,0)-(41,7)) │ │ │ ├── flags: ∅ @@ -544,18 +550,18 @@ │ ├── operator_loc: (41,17)-(41,18) = "=" │ └── value: │ @ ArrayNode (location: (41,19)-(41,23)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (41,19)-(41,20)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (41,22)-(41,23)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: ∅ │ └── closing_loc: ∅ ├── @ CallNode (location: (43,0)-(43,4)) - │ ├── flags: safe_navigation + │ ├── flags: newline, safe_navigation │ ├── receiver: │ │ @ CallNode (location: (43,0)-(43,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -575,7 +581,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (45,0)-(45,5)) - │ ├── flags: safe_navigation + │ ├── flags: newline, safe_navigation │ ├── receiver: │ │ @ CallNode (location: (45,0)-(45,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -595,7 +601,7 @@ │ ├── closing_loc: (45,4)-(45,5) = ")" │ └── block: ∅ ├── @ CallNode (location: (47,0)-(47,7)) - │ ├── flags: safe_navigation + │ ├── flags: newline, safe_navigation │ ├── receiver: │ │ @ CallNode (location: (47,0)-(47,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -628,7 +634,7 @@ │ ├── closing_loc: (47,6)-(47,7) = ")" │ └── block: ∅ ├── @ CallNode (location: (49,0)-(49,6)) - │ ├── flags: safe_navigation + │ ├── flags: newline, safe_navigation │ ├── receiver: │ │ @ CallNode (location: (49,0)-(49,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -648,11 +654,14 @@ │ ├── closing_loc: (49,5)-(49,6) = ")" │ └── block: ∅ ├── @ IfNode (location: (51,0)-(51,33)) + │ ├── flags: newline │ ├── if_keyword_loc: (51,11)-(51,13) = "if" │ ├── predicate: │ │ @ AndNode (location: (51,14)-(51,33)) + │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ OrNode (location: (51,14)-(51,25)) + │ │ │ ├── flags: ∅ │ │ │ ├── left: │ │ │ │ @ CallNode (location: (51,14)-(51,18)) │ │ │ │ ├── flags: ignore_visibility @@ -691,9 +700,10 @@ │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (51,0)-(51,10)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (51,0)-(51,10)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo @@ -704,23 +714,23 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 2) │ │ │ ├── @ SymbolNode (location: (51,4)-(51,6)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (51,4)-(51,5) = ":" │ │ │ │ ├── value_loc: (51,5)-(51,6) = "a" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "a" │ │ │ └── @ SymbolNode (location: (51,8)-(51,10)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (51,8)-(51,9) = ":" │ │ │ ├── value_loc: (51,9)-(51,10) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: ∅ ├── @ CallNode (location: (53,0)-(56,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -731,13 +741,13 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (53,4)-(53,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (53,4)-(53,5) = ":" │ │ │ ├── value_loc: (53,5)-(53,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (55,2)-(55,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (55,2)-(55,3) = ":" │ │ ├── value_loc: (55,3)-(55,4) = "b" │ │ ├── closing_loc: ∅ @@ -745,7 +755,7 @@ │ ├── closing_loc: (56,0)-(56,1) = ")" │ └── block: ∅ ├── @ CallNode (location: (58,0)-(58,10)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -753,9 +763,10 @@ │ ├── opening_loc: (58,3)-(58,4) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (58,4)-(58,9)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat │ │ └── arguments: (length: 1) │ │ └── @ SplatNode (location: (58,4)-(58,9)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (58,4)-(58,5) = "*" │ │ └── expression: │ │ @ CallNode (location: (58,5)-(58,9)) @@ -771,7 +782,7 @@ │ ├── closing_loc: (58,9)-(58,10) = ")" │ └── block: ∅ ├── @ CallNode (location: (60,0)-(60,39)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -782,7 +793,7 @@ │ │ ├── flags: contains_keywords │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (60,4)-(60,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (60,4)-(60,5) = ":" │ │ │ ├── value_loc: (60,5)-(60,6) = "a" │ │ │ ├── closing_loc: ∅ @@ -791,25 +802,26 @@ │ │ ├── flags: symbol_keys │ │ └── elements: (length: 2) │ │ ├── @ AssocNode (location: (60,8)-(60,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (60,8)-(60,10)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (60,8)-(60,9) = ":" │ │ │ │ ├── value_loc: (60,9)-(60,10) = "h" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "h" │ │ │ ├── value: │ │ │ │ @ ArrayNode (location: (60,14)-(60,22)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: static_literal │ │ │ │ ├── elements: (length: 2) │ │ │ │ │ ├── @ SymbolNode (location: (60,15)-(60,17)) - │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ │ ├── opening_loc: (60,15)-(60,16) = ":" │ │ │ │ │ │ ├── value_loc: (60,16)-(60,17) = "x" │ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ │ └── unescaped: "x" │ │ │ │ │ └── @ SymbolNode (location: (60,19)-(60,21)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (60,19)-(60,20) = ":" │ │ │ │ │ ├── value_loc: (60,20)-(60,21) = "y" │ │ │ │ │ ├── closing_loc: ∅ @@ -818,16 +830,17 @@ │ │ │ │ └── closing_loc: (60,21)-(60,22) = "]" │ │ │ └── operator_loc: (60,11)-(60,13) = "=>" │ │ └── @ AssocNode (location: (60,24)-(60,32)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (60,24)-(60,26)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (60,24)-(60,25) = ":" │ │ │ ├── value_loc: (60,25)-(60,26) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ ├── value: │ │ │ @ SymbolNode (location: (60,30)-(60,32)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (60,30)-(60,31) = ":" │ │ │ ├── value_loc: (60,31)-(60,32) = "b" │ │ │ ├── closing_loc: ∅ @@ -836,16 +849,17 @@ │ ├── closing_loc: (60,39)-(60,40) = ")" │ └── block: │ @ BlockArgumentNode (location: (60,34)-(60,39)) + │ ├── flags: ∅ │ ├── expression: │ │ @ SymbolNode (location: (60,35)-(60,39)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (60,35)-(60,36) = ":" │ │ ├── value_loc: (60,36)-(60,39) = "bar" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "bar" │ └── operator_loc: (60,34)-(60,35) = "&" ├── @ CallNode (location: (62,0)-(62,49)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :hi @@ -856,45 +870,50 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (62,3)-(62,6)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 123 │ │ └── @ HashNode (location: (62,8)-(62,49)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (62,8)-(62,9) = "{" │ │ ├── elements: (length: 3) │ │ │ ├── @ AssocNode (location: (62,10)-(62,27)) + │ │ │ │ ├── flags: static_literal │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (62,10)-(62,16)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (62,10)-(62,11) = ":" │ │ │ │ │ ├── value_loc: (62,11)-(62,16) = "there" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "there" │ │ │ │ ├── value: │ │ │ │ │ @ SymbolNode (location: (62,20)-(62,27)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (62,20)-(62,21) = ":" │ │ │ │ │ ├── value_loc: (62,21)-(62,27) = "friend" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "friend" │ │ │ │ └── operator_loc: (62,17)-(62,19) = "=>" │ │ │ ├── @ AssocSplatNode (location: (62,29)-(62,33)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── value: │ │ │ │ │ @ HashNode (location: (62,31)-(62,33)) + │ │ │ │ │ ├── flags: static_literal │ │ │ │ │ ├── opening_loc: (62,31)-(62,32) = "{" │ │ │ │ │ ├── elements: (length: 0) │ │ │ │ │ └── closing_loc: (62,32)-(62,33) = "}" │ │ │ │ └── operator_loc: (62,29)-(62,31) = "**" │ │ │ └── @ AssocNode (location: (62,35)-(62,47)) + │ │ │ ├── flags: static_literal │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (62,35)-(62,42)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (62,35)-(62,41) = "whatup" │ │ │ │ ├── closing_loc: (62,41)-(62,42) = ":" │ │ │ │ └── unescaped: "whatup" │ │ │ ├── value: │ │ │ │ @ SymbolNode (location: (62,43)-(62,47)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (62,43)-(62,44) = ":" │ │ │ │ ├── value_loc: (62,44)-(62,47) = "dog" │ │ │ │ ├── closing_loc: ∅ @@ -904,7 +923,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (64,0)-(64,36)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -915,7 +934,7 @@ │ │ ├── flags: contains_keywords │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (64,4)-(64,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (64,4)-(64,5) = ":" │ │ │ ├── value_loc: (64,5)-(64,6) = "a" │ │ │ ├── closing_loc: ∅ @@ -924,24 +943,29 @@ │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (64,8)-(64,15)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (64,8)-(64,10)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (64,8)-(64,9) = "b" │ │ │ ├── closing_loc: (64,9)-(64,10) = ":" │ │ │ └── unescaped: "b" │ │ ├── value: │ │ │ @ TrueNode (location: (64,11)-(64,15)) + │ │ │ └── flags: static_literal │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (64,16)-(64,36)) + │ ├── flags: ∅ │ ├── locals: [:a, :b] │ ├── parameters: │ │ @ BlockParametersNode (location: (64,19)-(64,25)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (64,20)-(64,24)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (64,20)-(64,21)) │ │ │ │ │ ├── flags: ∅ @@ -960,9 +984,10 @@ │ │ └── closing_loc: (64,24)-(64,25) = "|" │ ├── body: │ │ @ StatementsNode (location: (64,26)-(64,32)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (64,26)-(64,32)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :puts @@ -973,6 +998,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ LocalVariableReadNode (location: (64,31)-(64,32)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── closing_loc: ∅ @@ -980,7 +1006,7 @@ │ ├── opening_loc: (64,16)-(64,18) = "do" │ └── closing_loc: (64,33)-(64,36) = "end" ├── @ CallNode (location: (66,0)-(66,17)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :hi @@ -994,16 +1020,17 @@ │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (66,3)-(66,17)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (66,3)-(66,9)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (66,3)-(66,8) = "there" │ │ │ ├── closing_loc: (66,8)-(66,9) = ":" │ │ │ └── unescaped: "there" │ │ ├── value: │ │ │ @ SymbolNode (location: (66,10)-(66,17)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (66,10)-(66,11) = ":" │ │ │ ├── value_loc: (66,11)-(66,17) = "friend" │ │ │ ├── closing_loc: ∅ @@ -1012,7 +1039,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (68,0)-(68,40)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :hi @@ -1026,39 +1053,43 @@ │ │ ├── flags: ∅ │ │ └── elements: (length: 3) │ │ ├── @ AssocNode (location: (68,3)-(68,20)) + │ │ │ ├── flags: static_literal │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (68,3)-(68,9)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (68,3)-(68,4) = ":" │ │ │ │ ├── value_loc: (68,4)-(68,9) = "there" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "there" │ │ │ ├── value: │ │ │ │ @ SymbolNode (location: (68,13)-(68,20)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (68,13)-(68,14) = ":" │ │ │ │ ├── value_loc: (68,14)-(68,20) = "friend" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "friend" │ │ │ └── operator_loc: (68,10)-(68,12) = "=>" │ │ ├── @ AssocSplatNode (location: (68,22)-(68,26)) + │ │ │ ├── flags: ∅ │ │ │ ├── value: │ │ │ │ @ HashNode (location: (68,24)-(68,26)) + │ │ │ │ ├── flags: static_literal │ │ │ │ ├── opening_loc: (68,24)-(68,25) = "{" │ │ │ │ ├── elements: (length: 0) │ │ │ │ └── closing_loc: (68,25)-(68,26) = "}" │ │ │ └── operator_loc: (68,22)-(68,24) = "**" │ │ └── @ AssocNode (location: (68,28)-(68,40)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (68,28)-(68,35)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (68,28)-(68,34) = "whatup" │ │ │ ├── closing_loc: (68,34)-(68,35) = ":" │ │ │ └── unescaped: "whatup" │ │ ├── value: │ │ │ @ SymbolNode (location: (68,36)-(68,40)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (68,36)-(68,37) = ":" │ │ │ ├── value_loc: (68,37)-(68,40) = "dog" │ │ │ ├── closing_loc: ∅ @@ -1067,7 +1098,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (70,0)-(70,41)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :hi @@ -1081,39 +1112,43 @@ │ │ ├── flags: ∅ │ │ └── elements: (length: 3) │ │ ├── @ AssocNode (location: (70,3)-(70,20)) + │ │ │ ├── flags: static_literal │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (70,3)-(70,9)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (70,3)-(70,4) = ":" │ │ │ │ ├── value_loc: (70,4)-(70,9) = "there" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "there" │ │ │ ├── value: │ │ │ │ @ SymbolNode (location: (70,13)-(70,20)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (70,13)-(70,14) = ":" │ │ │ │ ├── value_loc: (70,14)-(70,20) = "friend" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "friend" │ │ │ └── operator_loc: (70,10)-(70,12) = "=>" │ │ ├── @ AssocSplatNode (location: (70,22)-(70,26)) + │ │ │ ├── flags: ∅ │ │ │ ├── value: │ │ │ │ @ HashNode (location: (70,24)-(70,26)) + │ │ │ │ ├── flags: static_literal │ │ │ │ ├── opening_loc: (70,24)-(70,25) = "{" │ │ │ │ ├── elements: (length: 0) │ │ │ │ └── closing_loc: (70,25)-(70,26) = "}" │ │ │ └── operator_loc: (70,22)-(70,24) = "**" │ │ └── @ AssocNode (location: (70,28)-(70,40)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (70,28)-(70,35)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (70,28)-(70,34) = "whatup" │ │ │ ├── closing_loc: (70,34)-(70,35) = ":" │ │ │ └── unescaped: "whatup" │ │ ├── value: │ │ │ @ SymbolNode (location: (70,36)-(70,40)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (70,36)-(70,37) = ":" │ │ │ ├── value_loc: (70,37)-(70,40) = "dog" │ │ │ ├── closing_loc: ∅ @@ -1122,7 +1157,7 @@ │ ├── closing_loc: (70,40)-(70,41) = ")" │ └── block: ∅ ├── @ CallNode (location: (72,0)-(72,35)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1133,44 +1168,50 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ HashNode (location: (72,4)-(72,26)) + │ │ ├── flags: static_literal │ │ ├── opening_loc: (72,4)-(72,5) = "{" │ │ ├── elements: (length: 2) │ │ │ ├── @ AssocNode (location: (72,6)-(72,13)) + │ │ │ │ ├── flags: static_literal │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (72,6)-(72,8)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (72,6)-(72,7) = "a" │ │ │ │ │ ├── closing_loc: (72,7)-(72,8) = ":" │ │ │ │ │ └── unescaped: "a" │ │ │ │ ├── value: │ │ │ │ │ @ TrueNode (location: (72,9)-(72,13)) + │ │ │ │ │ └── flags: static_literal │ │ │ │ └── operator_loc: ∅ │ │ │ └── @ AssocNode (location: (72,15)-(72,23)) + │ │ │ ├── flags: static_literal │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (72,15)-(72,17)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (72,15)-(72,16) = "b" │ │ │ │ ├── closing_loc: (72,16)-(72,17) = ":" │ │ │ │ └── unescaped: "b" │ │ │ ├── value: │ │ │ │ @ FalseNode (location: (72,18)-(72,23)) + │ │ │ │ └── flags: static_literal │ │ │ └── operator_loc: ∅ │ │ └── closing_loc: (72,25)-(72,26) = "}" │ ├── closing_loc: (72,35)-(72,36) = ")" │ └── block: │ @ BlockArgumentNode (location: (72,28)-(72,35)) + │ ├── flags: ∅ │ ├── expression: │ │ @ SymbolNode (location: (72,29)-(72,35)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (72,29)-(72,30) = ":" │ │ ├── value_loc: (72,30)-(72,35) = "block" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "block" │ └── operator_loc: (72,28)-(72,29) = "&" ├── @ CallNode (location: (74,0)-(74,20)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :hi @@ -1184,16 +1225,17 @@ │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (74,3)-(74,20)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (74,3)-(74,9)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (74,3)-(74,4) = ":" │ │ │ ├── value_loc: (74,4)-(74,9) = "there" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "there" │ │ ├── value: │ │ │ @ SymbolNode (location: (74,13)-(74,20)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (74,13)-(74,14) = ":" │ │ │ ├── value_loc: (74,14)-(74,20) = "friend" │ │ │ ├── closing_loc: ∅ @@ -1202,7 +1244,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (76,0)-(78,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1213,13 +1255,13 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (76,4)-(76,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (76,4)-(76,5) = ":" │ │ │ ├── value_loc: (76,5)-(76,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (77,0)-(77,2)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (77,0)-(77,1) = ":" │ │ ├── value_loc: (77,1)-(77,2) = "b" │ │ ├── closing_loc: ∅ @@ -1227,7 +1269,7 @@ │ ├── closing_loc: (78,0)-(78,1) = ")" │ └── block: ∅ ├── @ CallNode (location: (80,0)-(83,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1238,7 +1280,7 @@ │ │ ├── flags: contains_keywords │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (81,0)-(81,2)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (81,0)-(81,1) = ":" │ │ │ ├── value_loc: (81,1)-(81,2) = "a" │ │ │ ├── closing_loc: ∅ @@ -1247,16 +1289,17 @@ │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (82,0)-(82,5)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (82,0)-(82,2)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (82,0)-(82,1) = "b" │ │ │ ├── closing_loc: (82,1)-(82,2) = ":" │ │ │ └── unescaped: "b" │ │ ├── value: │ │ │ @ SymbolNode (location: (82,3)-(82,5)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (82,3)-(82,4) = ":" │ │ │ ├── value_loc: (82,4)-(82,5) = "c" │ │ │ ├── closing_loc: ∅ @@ -1265,7 +1308,7 @@ │ ├── closing_loc: (83,0)-(83,1) = ")" │ └── block: ∅ ├── @ CallNode (location: (85,0)-(85,11)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1275,16 +1318,17 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockArgumentNode (location: (85,4)-(85,11)) + │ ├── flags: ∅ │ ├── expression: │ │ @ SymbolNode (location: (85,5)-(85,11)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (85,5)-(85,6) = ":" │ │ ├── value_loc: (85,6)-(85,11) = "block" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "block" │ └── operator_loc: (85,4)-(85,5) = "&" ├── @ CallNode (location: (87,0)-(87,30)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1298,40 +1342,45 @@ │ │ ├── flags: symbol_keys │ │ └── elements: (length: 2) │ │ ├── @ AssocNode (location: (87,4)-(87,11)) + │ │ │ ├── flags: static_literal │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (87,4)-(87,6)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (87,4)-(87,5) = "a" │ │ │ │ ├── closing_loc: (87,5)-(87,6) = ":" │ │ │ │ └── unescaped: "a" │ │ │ ├── value: │ │ │ │ @ TrueNode (location: (87,7)-(87,11)) + │ │ │ │ └── flags: static_literal │ │ │ └── operator_loc: ∅ │ │ └── @ AssocNode (location: (87,13)-(87,21)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (87,13)-(87,15)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (87,13)-(87,14) = "b" │ │ │ ├── closing_loc: (87,14)-(87,15) = ":" │ │ │ └── unescaped: "b" │ │ ├── value: │ │ │ @ FalseNode (location: (87,16)-(87,21)) + │ │ │ └── flags: static_literal │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: │ @ BlockArgumentNode (location: (87,23)-(87,30)) + │ ├── flags: ∅ │ ├── expression: │ │ @ SymbolNode (location: (87,24)-(87,30)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (87,24)-(87,25) = ":" │ │ ├── value_loc: (87,25)-(87,30) = "block" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "block" │ └── operator_loc: (87,23)-(87,24) = "&" ├── @ CallNode (location: (89,0)-(89,21)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :some_func @@ -1342,30 +1391,32 @@ │ │ ├── flags: contains_keywords │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (89,10)-(89,11)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ KeywordHashNode (location: (89,13)-(89,21)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (89,13)-(89,21)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (89,13)-(89,19)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (89,13)-(89,18) = "kwarg" │ │ │ ├── closing_loc: (89,18)-(89,19) = ":" │ │ │ └── unescaped: "kwarg" │ │ ├── value: │ │ │ @ IntegerNode (location: (89,20)-(89,21)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (91,0)-(91,18)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (91,0)-(91,6)) + │ │ ├── flags: ∅ │ │ └── name: :Kernel │ ├── call_operator_loc: (91,6)-(91,7) = "." │ ├── name: :Integer @@ -1376,12 +1427,12 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (91,15)-(91,17)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 10 │ ├── closing_loc: (91,17)-(91,18) = ")" │ └── block: ∅ ├── @ CallNode (location: (93,0)-(93,10)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (93,0)-(93,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -1401,13 +1452,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (93,7)-(93,10)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ │ ├── opening_loc: (93,7)-(93,8) = "{" │ └── closing_loc: (93,9)-(93,10) = "}" ├── @ CallNode (location: (95,0)-(95,14)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (95,0)-(95,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1427,21 +1479,26 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (95,8)-(95,14)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (95,10)-(95,12)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ BackReferenceReadNode (location: (95,10)-(95,12)) + │ │ ├── flags: newline │ │ └── name: :$& │ ├── opening_loc: (95,8)-(95,9) = "{" │ └── closing_loc: (95,13)-(95,14) = "}" ├── @ CallNode (location: (97,0)-(97,12)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantPathNode (location: (97,0)-(97,4)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantReadNode (location: (97,0)-(97,1)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── name: :B │ │ ├── delimiter_loc: (97,1)-(97,3) = "::" @@ -1455,7 +1512,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (97,8)-(97,12)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (97,8)-(97,9) = ":" │ │ ├── value_loc: (97,9)-(97,12) = "foo" │ │ ├── closing_loc: ∅ @@ -1463,11 +1520,13 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (99,0)-(99,13)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantPathNode (location: (99,0)-(99,4)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantReadNode (location: (99,0)-(99,1)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── name: :B │ │ ├── delimiter_loc: (99,1)-(99,3) = "::" @@ -1481,7 +1540,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (99,8)-(99,12)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (99,8)-(99,9) = ":" │ │ ├── value_loc: (99,9)-(99,12) = "foo" │ │ ├── closing_loc: ∅ @@ -1489,11 +1548,13 @@ │ ├── closing_loc: (99,12)-(99,13) = ")" │ └── block: ∅ ├── @ CallNode (location: (101,0)-(101,17)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantPathNode (location: (101,0)-(101,4)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantReadNode (location: (101,0)-(101,1)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── name: :B │ │ ├── delimiter_loc: (101,1)-(101,3) = "::" @@ -1507,7 +1568,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (101,8)-(101,12)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (101,8)-(101,9) = ":" │ │ ├── value_loc: (101,9)-(101,12) = "foo" │ │ ├── closing_loc: ∅ @@ -1515,13 +1576,14 @@ │ ├── closing_loc: (101,12)-(101,13) = ")" │ └── block: │ @ BlockNode (location: (101,14)-(101,17)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ │ ├── opening_loc: (101,14)-(101,15) = "{" │ └── closing_loc: (101,16)-(101,17) = "}" ├── @ CallNode (location: (103,0)-(103,12)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1535,22 +1597,23 @@ │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (103,4)-(103,11)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (103,4)-(103,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (103,4)-(103,5) = "\"" │ │ │ ├── value_loc: (103,5)-(103,6) = "a" │ │ │ ├── closing_loc: (103,6)-(103,8) = "\":" │ │ │ └── unescaped: "a" │ │ ├── value: │ │ │ @ IntegerNode (location: (103,9)-(103,11)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: -1 │ │ └── operator_loc: ∅ │ ├── closing_loc: (103,11)-(103,12) = ")" │ └── block: ∅ ├── @ CallNode (location: (105,0)-(105,28)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1564,21 +1627,24 @@ │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (105,4)-(105,28)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ SymbolNode (location: (105,4)-(105,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (105,4)-(105,7) = "bar" │ │ │ ├── closing_loc: (105,7)-(105,8) = ":" │ │ │ └── unescaped: "bar" │ │ ├── value: │ │ │ @ HashNode (location: (105,9)-(105,28)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (105,9)-(105,10) = "{" │ │ │ ├── elements: (length: 1) │ │ │ │ └── @ AssocNode (location: (105,11)-(105,26)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (105,11)-(105,15)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (105,11)-(105,14) = "baz" │ │ │ │ │ ├── closing_loc: (105,14)-(105,15) = ":" @@ -1595,6 +1661,7 @@ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: │ │ │ │ │ @ BlockNode (location: (105,20)-(105,26)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── locals: [] │ │ │ │ │ ├── parameters: ∅ │ │ │ │ │ ├── body: ∅ @@ -1606,7 +1673,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (107,0)-(107,24)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1620,18 +1687,21 @@ │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (107,4)-(107,24)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ SymbolNode (location: (107,4)-(107,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (107,4)-(107,7) = "bar" │ │ │ ├── closing_loc: (107,7)-(107,8) = ":" │ │ │ └── unescaped: "bar" │ │ ├── value: │ │ │ @ HashNode (location: (107,9)-(107,24)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (107,9)-(107,10) = "{" │ │ │ ├── elements: (length: 1) │ │ │ │ └── @ AssocSplatNode (location: (107,11)-(107,22)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── value: │ │ │ │ │ @ CallNode (location: (107,13)-(107,22)) │ │ │ │ │ ├── flags: ignore_visibility @@ -1644,6 +1714,7 @@ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: │ │ │ │ │ @ BlockNode (location: (107,16)-(107,22)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── locals: [] │ │ │ │ │ ├── parameters: ∅ │ │ │ │ │ ├── body: ∅ @@ -1655,7 +1726,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (109,0)-(109,36)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1670,9 +1741,11 @@ │ │ ├── opening_loc: (109,4)-(109,5) = "\"" │ │ ├── parts: (length: 1) │ │ │ └── @ EmbeddedStatementsNode (location: (109,5)-(109,28)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (109,5)-(109,7) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (109,7)-(109,27)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (109,7)-(109,27)) │ │ │ │ ├── flags: ∅ @@ -1695,13 +1768,15 @@ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: │ │ │ │ @ BlockNode (location: (109,15)-(109,27)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── locals: [] │ │ │ │ ├── parameters: ∅ │ │ │ │ ├── body: │ │ │ │ │ @ StatementsNode (location: (109,18)-(109,23)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ StringNode (location: (109,18)-(109,23)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: newline │ │ │ │ │ ├── opening_loc: (109,18)-(109,19) = "\"" │ │ │ │ │ ├── content_loc: (109,19)-(109,22) = "baz" │ │ │ │ │ ├── closing_loc: (109,22)-(109,23) = "\"" @@ -1713,13 +1788,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (109,30)-(109,36)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ │ ├── opening_loc: (109,30)-(109,32) = "do" │ └── closing_loc: (109,33)-(109,36) = "end" ├── @ CallNode (location: (111,0)-(111,28)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1730,18 +1806,21 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ ClassNode (location: (111,4)-(111,28)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── class_keyword_loc: (111,4)-(111,9) = "class" │ │ ├── constant_path: │ │ │ @ ConstantReadNode (location: (111,10)-(111,13)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Bar │ │ ├── inheritance_operator_loc: ∅ │ │ ├── superclass: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (111,14)-(111,24)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (111,14)-(111,24)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz @@ -1751,6 +1830,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: │ │ │ @ BlockNode (location: (111,18)-(111,24)) + │ │ │ ├── flags: ∅ │ │ │ ├── locals: [] │ │ │ ├── parameters: ∅ │ │ │ ├── body: ∅ @@ -1761,7 +1841,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (113,0)-(113,29)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1772,16 +1852,19 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ ModuleNode (location: (113,4)-(113,29)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── module_keyword_loc: (113,4)-(113,10) = "module" │ │ ├── constant_path: │ │ │ @ ConstantReadNode (location: (113,11)-(113,14)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Bar │ │ ├── body: │ │ │ @ StatementsNode (location: (113,15)-(113,25)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (113,15)-(113,25)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz @@ -1791,6 +1874,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: │ │ │ @ BlockNode (location: (113,19)-(113,25)) + │ │ │ ├── flags: ∅ │ │ │ ├── locals: [] │ │ │ ├── parameters: ∅ │ │ │ ├── body: ∅ @@ -1801,7 +1885,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (115,0)-(115,16)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1825,6 +1909,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: │ │ │ @ BlockNode (location: (115,9)-(115,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── locals: [] │ │ │ ├── parameters: ∅ │ │ │ ├── body: ∅ @@ -1835,7 +1920,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (117,0)-(117,28)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :p @@ -1846,15 +1931,17 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ BeginNode (location: (117,2)-(117,28)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: (117,2)-(117,7) = "begin" │ │ ├── statements: │ │ │ @ StatementsNode (location: (117,8)-(117,24)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (117,8)-(117,24)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ IntegerNode (location: (117,8)-(117,9)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── call_operator_loc: (117,9)-(117,10) = "." │ │ │ ├── name: :times @@ -1864,13 +1951,15 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: │ │ │ @ BlockNode (location: (117,16)-(117,24)) + │ │ │ ├── flags: ∅ │ │ │ ├── locals: [] │ │ │ ├── parameters: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (117,19)-(117,20)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (117,19)-(117,20)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── opening_loc: (117,16)-(117,18) = "do" │ │ │ └── closing_loc: (117,21)-(117,24) = "end" @@ -1881,7 +1970,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (119,0)-(124,5)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1892,12 +1981,13 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (119,4)-(119,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (119,4)-(119,5) = ":" │ │ │ ├── value_loc: (119,5)-(119,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ IfNode (location: (120,2)-(124,5)) + │ │ ├── flags: newline │ │ ├── if_keyword_loc: (120,2)-(120,4) = "if" │ │ ├── predicate: │ │ │ @ CallNode (location: (120,5)-(120,6)) @@ -1913,9 +2003,10 @@ │ │ ├── then_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (121,4)-(123,7)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (121,4)-(123,7)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -1925,11 +2016,14 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: │ │ │ @ BlockNode (location: (121,8)-(123,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── locals: [:a] │ │ │ ├── parameters: │ │ │ │ @ BlockParametersNode (location: (121,11)-(121,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── parameters: │ │ │ │ │ @ ParametersNode (location: (121,12)-(121,13)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ │ └── @ RequiredParameterNode (location: (121,12)-(121,13)) │ │ │ │ │ │ ├── flags: ∅ @@ -1945,18 +2039,20 @@ │ │ │ │ └── closing_loc: (121,13)-(121,14) = "|" │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (122,6)-(122,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ LocalVariableReadNode (location: (122,6)-(122,7)) + │ │ │ │ ├── flags: newline │ │ │ │ ├── name: :a │ │ │ │ └── depth: 0 │ │ │ ├── opening_loc: (121,8)-(121,10) = "do" │ │ │ └── closing_loc: (123,4)-(123,7) = "end" - │ │ ├── consequent: ∅ + │ │ ├── subsequent: ∅ │ │ └── end_keyword_loc: (124,2)-(124,5) = "end" │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (126,0)-(135,5)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1967,7 +2063,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 3) │ │ ├── @ SymbolNode (location: (126,4)-(126,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (126,4)-(126,5) = ":" │ │ │ ├── value_loc: (126,5)-(126,6) = "a" │ │ │ ├── closing_loc: ∅ @@ -1989,9 +2085,10 @@ │ │ │ │ └── block: ∅ │ │ │ └── statements: │ │ │ @ StatementsNode (location: (128,4)-(130,7)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (128,4)-(130,7)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -2001,11 +2098,14 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: │ │ │ @ BlockNode (location: (128,8)-(130,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── locals: [:a] │ │ │ ├── parameters: │ │ │ │ @ BlockParametersNode (location: (128,11)-(128,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── parameters: │ │ │ │ │ @ ParametersNode (location: (128,12)-(128,13)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ │ └── @ RequiredParameterNode (location: (128,12)-(128,13)) │ │ │ │ │ │ ├── flags: ∅ @@ -2021,8 +2121,10 @@ │ │ │ │ └── closing_loc: (128,13)-(128,14) = "|" │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (129,6)-(129,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ LocalVariableReadNode (location: (129,6)-(129,7)) + │ │ │ │ ├── flags: newline │ │ │ │ ├── name: :a │ │ │ │ └── depth: 0 │ │ │ ├── opening_loc: (128,8)-(128,10) = "do" @@ -2044,9 +2146,10 @@ │ │ │ └── block: ∅ │ │ └── statements: │ │ @ StatementsNode (location: (133,4)-(134,7)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (133,4)-(134,7)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :baz @@ -2056,6 +2159,7 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (133,8)-(134,7)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: ∅ @@ -2064,9 +2168,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (137,0)-(137,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ HashNode (location: (137,0)-(137,2)) + │ │ ├── flags: static_literal │ │ ├── opening_loc: (137,0)-(137,1) = "{" │ │ ├── elements: (length: 0) │ │ └── closing_loc: (137,1)-(137,2) = "}" @@ -2089,6 +2194,7 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (137,7)-(137,9)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: ∅ @@ -2097,9 +2203,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (139,0)-(139,16)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ HashNode (location: (139,0)-(139,2)) + │ │ ├── flags: static_literal │ │ ├── opening_loc: (139,0)-(139,1) = "{" │ │ ├── elements: (length: 0) │ │ └── closing_loc: (139,1)-(139,2) = "}" @@ -2122,11 +2229,14 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (139,7)-(139,16)) + │ │ ├── flags: ∅ │ │ ├── locals: [:a] │ │ ├── parameters: │ │ │ @ BlockParametersNode (location: (139,9)-(139,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── parameters: │ │ │ │ @ ParametersNode (location: (139,10)-(139,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ └── @ RequiredParameterNode (location: (139,10)-(139,11)) │ │ │ │ │ ├── flags: ∅ @@ -2142,8 +2252,10 @@ │ │ │ └── closing_loc: (139,11)-(139,12) = "|" │ │ ├── body: │ │ │ @ StatementsNode (location: (139,13)-(139,14)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ LocalVariableReadNode (location: (139,13)-(139,14)) + │ │ │ ├── flags: newline │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── opening_loc: (139,7)-(139,8) = "{" @@ -2151,7 +2263,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (141,0)-(141,11)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (141,0)-(141,4)) │ │ ├── flags: ignore_visibility @@ -2164,6 +2276,7 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (141,2)-(141,4)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: ∅ @@ -2188,6 +2301,7 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (141,9)-(141,11)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: ∅ @@ -2196,7 +2310,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (143,0)-(143,11)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (143,0)-(143,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2227,6 +2341,7 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (143,9)-(143,11)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: ∅ @@ -2235,13 +2350,15 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ InterpolatedStringNode (location: (145,0)-(145,17)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (145,0)-(145,1) = "\"" │ ├── parts: (length: 1) │ │ └── @ EmbeddedStatementsNode (location: (145,1)-(145,16)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (145,1)-(145,3) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (145,4)-(145,14)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (145,4)-(145,14)) │ │ │ ├── flags: ignore_visibility @@ -2255,11 +2372,13 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ ParenthesesNode (location: (145,9)-(145,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── body: │ │ │ │ │ @ StatementsNode (location: (145,10)-(145,13)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ StringNode (location: (145,10)-(145,13)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: newline │ │ │ │ │ ├── opening_loc: (145,10)-(145,11) = "\"" │ │ │ │ │ ├── content_loc: (145,11)-(145,12) = " " │ │ │ │ │ ├── closing_loc: (145,12)-(145,13) = "\"" @@ -2271,20 +2390,24 @@ │ │ └── closing_loc: (145,15)-(145,16) = "}" │ └── closing_loc: (145,16)-(145,17) = "\"" ├── @ InterpolatedStringNode (location: (147,0)-(147,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (147,0)-(147,1) = "\"" │ ├── parts: (length: 1) │ │ └── @ EmbeddedStatementsNode (location: (147,1)-(147,7)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (147,1)-(147,3) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (147,3)-(147,6)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ ParenthesesNode (location: (147,3)-(147,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (147,4)-(147,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (147,4)-(147,5)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :v @@ -2298,11 +2421,13 @@ │ │ └── closing_loc: (147,6)-(147,7) = "}" │ └── closing_loc: (147,7)-(147,8) = "\"" ├── @ DefNode (location: (149,0)-(149,18)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (149,4)-(149,5) = "f" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (149,6)-(149,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: @@ -2317,9 +2442,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (149,10)-(149,13)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (149,10)-(149,13)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :p @@ -2327,9 +2453,10 @@ │ │ ├── opening_loc: ∅ │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (149,12)-(149,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_splat │ │ │ └── arguments: (length: 1) │ │ │ └── @ SplatNode (location: (149,12)-(149,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (149,12)-(149,13) = "*" │ │ │ └── expression: ∅ │ │ ├── closing_loc: ∅ @@ -2342,7 +2469,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (149,15)-(149,18) = "end" ├── @ CallNode (location: (151,0)-(151,16)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -2353,7 +2480,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (151,4)-(151,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ CallNode (location: (151,7)-(151,16)) │ │ ├── flags: ignore_visibility @@ -2366,29 +2493,32 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (151,11)-(151,16)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (151,13)-(151,14)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (151,13)-(151,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: newline, static_literal, decimal │ │ │ └── value: 1 │ │ ├── opening_loc: (151,11)-(151,12) = "{" │ │ └── closing_loc: (151,15)-(151,16) = "}" │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ LocalVariableWriteNode (location: (153,0)-(153,7)) + │ ├── flags: newline │ ├── name: :foo │ ├── depth: 0 │ ├── name_loc: (153,0)-(153,3) = "foo" │ ├── value: │ │ @ IntegerNode (location: (153,6)-(153,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (153,4)-(153,5) = "=" ├── @ CallNode (location: (154,0)-(154,6)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -2398,15 +2528,17 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (154,4)-(154,6)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ │ ├── opening_loc: (154,4)-(154,5) = "{" │ └── closing_loc: (154,5)-(154,6) = "}" └── @ CallNode (location: (156,0)-(156,19)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ InstanceVariableReadNode (location: (156,0)-(156,2)) + │ ├── flags: ∅ │ └── name: :@a ├── call_operator_loc: (156,2)-(156,3) = "." ├── name: :b @@ -2420,20 +2552,24 @@ │ ├── flags: ∅ │ └── elements: (length: 1) │ └── @ AssocNode (location: (156,5)-(156,19)) + │ ├── flags: ∅ │ ├── key: │ │ @ InterpolatedSymbolNode (location: (156,5)-(156,16)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (156,5)-(156,6) = "\"" │ │ ├── parts: (length: 2) │ │ │ ├── @ StringNode (location: (156,6)-(156,7)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (156,6)-(156,7) = "c" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "c" │ │ │ └── @ EmbeddedStatementsNode (location: (156,7)-(156,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (156,7)-(156,9) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (156,9)-(156,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (156,9)-(156,13)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -2449,7 +2585,7 @@ │ │ └── closing_loc: (156,14)-(156,16) = "\":" │ ├── value: │ │ @ IntegerNode (location: (156,17)-(156,19)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 42 │ └── operator_loc: ∅ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/methods.txt b/test/prism/snapshots/methods.txt index b38640399b0..1d2deb26968 100644 --- a/test/prism/snapshots/methods.txt +++ b/test/prism/snapshots/methods.txt @@ -1,16 +1,21 @@ -@ ProgramNode (location: (1,0)-(183,37)) +@ ProgramNode (location: (1,0)-(188,3)) +├── flags: ∅ ├── locals: [:a, :c, :foo] └── statements: - @ StatementsNode (location: (1,0)-(183,37)) - └── body: (length: 69) + @ StatementsNode (location: (1,0)-(188,3)) + ├── flags: ∅ + └── body: (length: 70) ├── @ DefNode (location: (1,0)-(2,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (1,4)-(1,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,8)-(1,18)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (1,9)-(1,12)) │ │ │ │ │ ├── flags: ∅ @@ -37,13 +42,16 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (2,0)-(2,3) = "end" ├── @ DefNode (location: (4,0)-(5,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (4,4)-(4,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (4,8)-(4,44)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ MultiTargetNode (location: (4,8)-(4,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (4,9)-(4,12)) │ │ │ │ │ ├── flags: ∅ @@ -63,11 +71,12 @@ │ │ │ ├── operator_loc: (4,29)-(4,30) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (4,31)-(4,32)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) │ │ │ └── @ MultiTargetNode (location: (4,34)-(4,44)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (4,35)-(4,38)) │ │ │ │ │ ├── flags: ∅ @@ -91,18 +100,21 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (5,0)-(5,3) = "end" ├── @ DefNode (location: (8,0)-(8,18)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (8,4)-(8,5) = "a" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (8,0)-(8,18)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── rescue_clause: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: │ │ │ @ EnsureNode (location: (8,7)-(8,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── ensure_keyword_loc: (8,7)-(8,13) = "ensure" │ │ │ ├── statements: ∅ │ │ │ └── end_keyword_loc: (8,15)-(8,18) = "end" @@ -115,10 +127,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (8,15)-(8,18) = "end" ├── @ DefNode (location: (10,0)-(11,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (10,8)-(10,9) = "a" │ ├── receiver: │ │ @ ParenthesesNode (location: (10,4)-(10,7)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ CallNode (location: (10,5)-(10,6)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -142,10 +156,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (11,0)-(11,3) = "end" ├── @ DefNode (location: (13,0)-(14,3)) + │ ├── flags: newline │ ├── name: :b │ ├── name_loc: (13,9)-(13,10) = "b" │ ├── receiver: │ │ @ ParenthesesNode (location: (13,4)-(13,7)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ CallNode (location: (13,5)-(13,6)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -169,10 +185,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (14,0)-(14,3) = "end" ├── @ DefNode (location: (16,0)-(17,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (16,10)-(16,11) = "a" │ ├── receiver: │ │ @ FalseNode (location: (16,4)-(16,9)) + │ │ └── flags: static_literal │ ├── parameters: ∅ │ ├── body: ∅ │ ├── locals: [] @@ -183,11 +201,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (17,0)-(17,3) = "end" ├── @ DefNode (location: (19,0)-(20,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (19,4)-(19,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (19,6)-(19,9)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -195,6 +215,7 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ ForwardingParameterNode (location: (19,6)-(19,9)) + │ │ │ └── flags: ∅ │ │ └── block: ∅ │ ├── body: ∅ │ ├── locals: [] @@ -205,10 +226,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (20,0)-(20,3) = "end" ├── @ DefNode (location: (22,0)-(23,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (22,9)-(22,10) = "a" │ ├── receiver: │ │ @ GlobalVariableReadNode (location: (22,4)-(22,8)) + │ │ ├── flags: ∅ │ │ └── name: :$var │ ├── parameters: ∅ │ ├── body: ∅ @@ -220,6 +243,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (23,0)-(23,3) = "end" ├── @ DefNode (location: (25,0)-(26,3)) + │ ├── flags: newline │ ├── name: :b │ ├── name_loc: (25,6)-(25,7) = "b" │ ├── receiver: @@ -243,10 +267,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (26,0)-(26,3) = "end" ├── @ DefNode (location: (28,0)-(29,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (28,9)-(28,10) = "a" │ ├── receiver: │ │ @ InstanceVariableReadNode (location: (28,4)-(28,8)) + │ │ ├── flags: ∅ │ │ └── name: :@var │ ├── parameters: ∅ │ ├── body: ∅ @@ -258,11 +284,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (29,0)-(29,3) = "end" ├── @ DefNode (location: (31,0)-(31,13)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (31,4)-(31,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (31,6)-(31,8)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -283,17 +311,19 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (31,10)-(31,13) = "end" ├── @ StringNode (location: (33,0)-(33,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (33,0)-(33,2) = "%," │ ├── content_loc: (33,2)-(33,5) = "abc" │ ├── closing_loc: (33,5)-(33,6) = "," │ └── unescaped: "abc" ├── @ DefNode (location: (35,0)-(36,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (35,4)-(35,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (35,6)-(35,8)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -314,11 +344,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (36,0)-(36,3) = "end" ├── @ DefNode (location: (38,0)-(39,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (38,4)-(38,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (38,6)-(38,9)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -340,11 +372,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (39,0)-(39,3) = "end" ├── @ DefNode (location: (41,0)-(42,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (41,4)-(41,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (41,6)-(41,8)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -366,15 +400,17 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (42,0)-(42,3) = "end" ├── @ LocalVariableWriteNode (location: (44,0)-(44,5)) + │ ├── flags: newline │ ├── name: :a │ ├── depth: 0 │ ├── name_loc: (44,0)-(44,1) = "a" │ ├── value: │ │ @ IntegerNode (location: (44,4)-(44,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (44,2)-(44,3) = "=" ├── @ DefNode (location: (44,7)-(45,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (44,11)-(44,12) = "a" │ ├── receiver: ∅ @@ -388,11 +424,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (45,0)-(45,3) = "end" ├── @ DefNode (location: (47,0)-(48,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (47,4)-(47,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (47,6)-(47,13)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 3) │ │ │ ├── @ RequiredParameterNode (location: (47,6)-(47,7)) │ │ │ │ ├── flags: ∅ @@ -418,10 +456,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (48,0)-(48,3) = "end" ├── @ DefNode (location: (50,0)-(51,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (50,8)-(50,9) = "a" │ ├── receiver: │ │ @ NilNode (location: (50,4)-(50,7)) + │ │ └── flags: static_literal │ ├── parameters: ∅ │ ├── body: ∅ │ ├── locals: [] @@ -432,11 +472,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (51,0)-(51,3) = "end" ├── @ DefNode (location: (53,0)-(54,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (53,4)-(53,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (53,6)-(53,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -452,7 +494,7 @@ │ │ │ ├── name_loc: (53,10)-(53,12) = "c:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (53,13)-(53,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ @@ -465,11 +507,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (54,0)-(54,3) = "end" ├── @ DefNode (location: (56,0)-(57,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (56,4)-(56,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (56,6)-(56,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -485,7 +529,7 @@ │ │ │ ├── name_loc: (56,10)-(56,12) = "c:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (56,13)-(56,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ @@ -498,11 +542,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (57,0)-(57,3) = "end" ├── @ DefNode (location: (59,0)-(61,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (59,4)-(59,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (59,6)-(60,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -514,7 +560,7 @@ │ │ │ │ ├── name_loc: (59,6)-(59,8) = "b:" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (60,2)-(60,3)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── @ RequiredKeywordParameterNode (location: (60,5)-(60,7)) │ │ │ ├── flags: ∅ @@ -531,17 +577,19 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (61,0)-(61,3) = "end" ├── @ StringNode (location: (63,0)-(63,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (63,0)-(63,2) = "%." │ ├── content_loc: (63,2)-(63,5) = "abc" │ ├── closing_loc: (63,5)-(63,6) = "." │ └── unescaped: "abc" ├── @ DefNode (location: (65,0)-(66,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (65,4)-(65,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (65,6)-(65,18)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 2) │ │ │ ├── @ OptionalParameterNode (location: (65,6)-(65,11)) @@ -551,7 +599,7 @@ │ │ │ │ ├── operator_loc: (65,8)-(65,9) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (65,10)-(65,11)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── @ OptionalParameterNode (location: (65,13)-(65,18)) │ │ │ ├── flags: ∅ @@ -560,7 +608,7 @@ │ │ │ ├── operator_loc: (65,15)-(65,16) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (65,17)-(65,18)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) @@ -576,6 +624,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (66,0)-(66,3) = "end" ├── @ DefNode (location: (68,0)-(69,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (68,4)-(68,5) = "a" │ ├── receiver: ∅ @@ -589,11 +638,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (69,0)-(69,3) = "end" ├── @ DefNode (location: (71,0)-(72,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (71,4)-(71,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (71,6)-(71,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (71,6)-(71,7)) │ │ │ ├── flags: ∅ @@ -606,7 +657,7 @@ │ │ │ ├── operator_loc: (71,11)-(71,12) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (71,13)-(71,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) @@ -622,11 +673,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (72,0)-(72,3) = "end" ├── @ DefNode (location: (74,0)-(75,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (74,4)-(74,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (74,6)-(74,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (74,6)-(74,7)) │ │ │ ├── flags: ∅ @@ -646,29 +699,34 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (75,0)-(75,3) = "end" ├── @ DefNode (location: (77,0)-(77,32)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (77,4)-(77,5) = "a" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (77,0)-(77,32)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (77,7)-(77,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (77,7)-(77,13) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: │ │ │ @ ElseNode (location: (77,15)-(77,27)) + │ │ │ ├── flags: ∅ │ │ │ ├── else_keyword_loc: (77,15)-(77,19) = "else" │ │ │ ├── statements: ∅ │ │ │ └── end_keyword_loc: (77,21)-(77,27) = "ensure" │ │ ├── ensure_clause: │ │ │ @ EnsureNode (location: (77,21)-(77,32)) + │ │ │ ├── flags: ∅ │ │ │ ├── ensure_keyword_loc: (77,21)-(77,27) = "ensure" │ │ │ ├── statements: ∅ │ │ │ └── end_keyword_loc: (77,29)-(77,32) = "end" @@ -681,11 +739,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (77,29)-(77,32) = "end" ├── @ DefNode (location: (79,0)-(80,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (79,4)-(79,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (79,6)-(79,8)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: @@ -707,11 +767,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (80,0)-(80,3) = "end" ├── @ DefNode (location: (82,0)-(83,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (82,4)-(82,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (82,6)-(82,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: @@ -733,20 +795,23 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (83,0)-(83,3) = "end" ├── @ DefNode (location: (85,0)-(87,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (85,4)-(85,5) = "a" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (86,0)-(86,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableWriteNode (location: (86,0)-(86,5)) + │ │ ├── flags: newline │ │ ├── name: :b │ │ ├── depth: 0 │ │ ├── name_loc: (86,0)-(86,1) = "b" │ │ ├── value: │ │ │ @ IntegerNode (location: (86,4)-(86,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── operator_loc: (86,2)-(86,3) = "=" │ ├── locals: [:b] @@ -757,10 +822,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (87,0)-(87,3) = "end" ├── @ DefNode (location: (89,0)-(90,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (89,9)-(89,10) = "a" │ ├── receiver: │ │ @ SelfNode (location: (89,4)-(89,8)) + │ │ └── flags: ∅ │ ├── parameters: ∅ │ ├── body: ∅ │ ├── locals: [] @@ -771,10 +838,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (90,0)-(90,3) = "end" ├── @ DefNode (location: (92,0)-(93,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (92,9)-(92,10) = "a" │ ├── receiver: │ │ @ TrueNode (location: (92,4)-(92,8)) + │ │ └── flags: static_literal │ ├── parameters: ∅ │ ├── body: ∅ │ ├── locals: [] @@ -785,6 +854,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (93,0)-(93,3) = "end" ├── @ DefNode (location: (95,0)-(96,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (95,4)-(95,5) = "a" │ ├── receiver: ∅ @@ -798,38 +868,43 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (96,0)-(96,3) = "end" ├── @ DefNode (location: (98,0)-(101,3)) + │ ├── flags: newline │ ├── name: :hi │ ├── name_loc: (98,4)-(98,6) = "hi" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (99,0)-(100,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 2) │ │ ├── @ IfNode (location: (99,0)-(99,18)) + │ │ │ ├── flags: newline │ │ │ ├── if_keyword_loc: (99,11)-(99,13) = "if" │ │ │ ├── predicate: │ │ │ │ @ TrueNode (location: (99,14)-(99,18)) + │ │ │ │ └── flags: static_literal │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (99,0)-(99,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ ReturnNode (location: (99,0)-(99,10)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: newline │ │ │ │ ├── keyword_loc: (99,0)-(99,6) = "return" │ │ │ │ └── arguments: │ │ │ │ @ ArgumentsNode (location: (99,7)-(99,10)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ SymbolNode (location: (99,7)-(99,10)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (99,7)-(99,8) = ":" │ │ │ │ ├── value_loc: (99,8)-(99,10) = "hi" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "hi" - │ │ │ ├── consequent: ∅ + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ └── @ SymbolNode (location: (100,0)-(100,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (100,0)-(100,1) = ":" │ │ ├── value_loc: (100,1)-(100,4) = "bye" │ │ ├── closing_loc: ∅ @@ -842,15 +917,17 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (101,0)-(101,3) = "end" ├── @ DefNode (location: (103,0)-(103,11)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (103,4)-(103,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (103,10)-(103,11)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (103,10)-(103,11)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── locals: [] │ ├── def_keyword_loc: (103,0)-(103,3) = "def" @@ -860,15 +937,17 @@ │ ├── equal_loc: (103,8)-(103,9) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (104,0)-(104,11)) + │ ├── flags: newline │ ├── name: :bar │ ├── name_loc: (104,4)-(104,7) = "bar" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (104,10)-(104,11)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (104,10)-(104,11)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── locals: [] │ ├── def_keyword_loc: (104,0)-(104,3) = "def" @@ -878,11 +957,13 @@ │ ├── equal_loc: (104,8)-(104,9) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (106,0)-(106,18)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (106,4)-(106,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (106,8)-(106,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (106,8)-(106,11)) │ │ │ ├── flags: ∅ @@ -895,9 +976,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (106,15)-(106,18)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (106,15)-(106,18)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 123 │ ├── locals: [:bar] │ ├── def_keyword_loc: (106,0)-(106,3) = "def" @@ -907,15 +989,17 @@ │ ├── equal_loc: (106,13)-(106,14) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (108,0)-(108,13)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (108,4)-(108,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (108,10)-(108,13)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (108,10)-(108,13)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 123 │ ├── locals: [] │ ├── def_keyword_loc: (108,0)-(108,3) = "def" @@ -925,11 +1009,13 @@ │ ├── equal_loc: (108,8)-(108,9) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (110,0)-(110,19)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (110,4)-(110,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (110,6)-(110,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: @@ -944,9 +1030,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (110,10)-(110,14)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (110,10)-(110,14)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :b @@ -954,9 +1041,10 @@ │ │ ├── opening_loc: (110,11)-(110,12) = "(" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (110,12)-(110,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_splat │ │ │ └── arguments: (length: 1) │ │ │ └── @ SplatNode (location: (110,12)-(110,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (110,12)-(110,13) = "*" │ │ │ └── expression: ∅ │ │ ├── closing_loc: (110,13)-(110,14) = ")" @@ -969,11 +1057,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (110,16)-(110,19) = "end" ├── @ DefNode (location: (112,0)-(112,23)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (112,4)-(112,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (112,6)-(112,9)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -981,12 +1071,14 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ ForwardingParameterNode (location: (112,6)-(112,9)) + │ │ │ └── flags: ∅ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (112,12)-(112,18)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (112,12)-(112,18)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :b @@ -994,9 +1086,10 @@ │ │ ├── opening_loc: (112,13)-(112,14) = "(" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (112,14)-(112,17)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_forwarding │ │ │ └── arguments: (length: 1) │ │ │ └── @ ForwardingArgumentsNode (location: (112,14)-(112,17)) + │ │ │ └── flags: ∅ │ │ ├── closing_loc: (112,17)-(112,18) = ")" │ │ └── block: ∅ │ ├── locals: [] @@ -1007,11 +1100,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (112,20)-(112,23) = "end" ├── @ DefNode (location: (114,0)-(114,29)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (114,4)-(114,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (114,6)-(114,9)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -1019,12 +1114,14 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ ForwardingParameterNode (location: (114,6)-(114,9)) + │ │ │ └── flags: ∅ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (114,12)-(114,24)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (114,12)-(114,24)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :b @@ -1032,15 +1129,16 @@ │ │ ├── opening_loc: (114,13)-(114,14) = "(" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (114,14)-(114,23)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_forwarding │ │ │ └── arguments: (length: 3) │ │ │ ├── @ IntegerNode (location: (114,14)-(114,15)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── @ IntegerNode (location: (114,17)-(114,18)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ └── @ ForwardingArgumentsNode (location: (114,20)-(114,23)) + │ │ │ └── flags: ∅ │ │ ├── closing_loc: (114,23)-(114,24) = ")" │ │ └── block: ∅ │ ├── locals: [] @@ -1051,12 +1149,15 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (114,26)-(114,29) = "end" ├── @ DefNode (location: (116,0)-(117,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (116,12)-(116,13) = "a" │ ├── receiver: │ │ @ ParenthesesNode (location: (116,4)-(116,11)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ LocalVariableWriteNode (location: (116,5)-(116,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── depth: 0 │ │ │ ├── name_loc: (116,5)-(116,6) = "c" @@ -1084,11 +1185,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (117,0)-(117,3) = "end" ├── @ DefNode (location: (119,0)-(120,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (119,4)-(119,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (119,6)-(119,8)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -1110,11 +1213,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (120,0)-(120,3) = "end" ├── @ DefNode (location: (122,0)-(123,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (122,4)-(122,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (122,6)-(122,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -1136,10 +1241,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (123,0)-(123,3) = "end" ├── @ DefNode (location: (125,0)-(126,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (125,10)-(125,11) = "a" │ ├── receiver: │ │ @ ClassVariableReadNode (location: (125,4)-(125,9)) + │ │ ├── flags: ∅ │ │ └── name: :@@var │ ├── parameters: ∅ │ ├── body: ∅ @@ -1151,12 +1258,15 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (126,0)-(126,3) = "end" ├── @ DefNode (location: (128,0)-(129,3)) + │ ├── flags: newline │ ├── name: :C │ ├── name_loc: (128,12)-(128,13) = "C" │ ├── receiver: │ │ @ ParenthesesNode (location: (128,4)-(128,11)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ LocalVariableWriteNode (location: (128,5)-(128,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ ├── depth: 0 │ │ │ ├── name_loc: (128,5)-(128,6) = "a" @@ -1184,10 +1294,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (129,0)-(129,3) = "end" ├── @ DefNode (location: (131,0)-(131,28)) + │ ├── flags: newline │ ├── name: :Array_function │ ├── name_loc: (131,9)-(131,23) = "Array_function" │ ├── receiver: │ │ @ SelfNode (location: (131,4)-(131,8)) + │ │ └── flags: ∅ │ ├── parameters: ∅ │ ├── body: ∅ │ ├── locals: [] @@ -1198,18 +1310,21 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (131,25)-(131,28) = "end" ├── @ ConstantWriteNode (location: (133,0)-(133,9)) + │ ├── flags: newline │ ├── name: :Const │ ├── name_loc: (133,0)-(133,5) = "Const" │ ├── value: │ │ @ IntegerNode (location: (133,8)-(133,9)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (133,6)-(133,7) = "=" ├── @ DefNode (location: (133,11)-(134,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (133,21)-(133,22) = "a" │ ├── receiver: │ │ @ ConstantReadNode (location: (133,15)-(133,20)) + │ │ ├── flags: ∅ │ │ └── name: :Const │ ├── parameters: ∅ │ ├── body: ∅ @@ -1221,11 +1336,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (134,0)-(134,3) = "end" ├── @ DefNode (location: (136,0)-(136,31)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (136,4)-(136,5) = "a" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (136,6)-(136,9)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -1233,24 +1350,28 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ ForwardingParameterNode (location: (136,6)-(136,9)) + │ │ │ └── flags: ∅ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (136,12)-(136,26)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ InterpolatedStringNode (location: (136,12)-(136,26)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── opening_loc: (136,12)-(136,13) = "\"" │ │ ├── parts: (length: 2) │ │ │ ├── @ StringNode (location: (136,13)-(136,16)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (136,13)-(136,16) = "foo" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "foo" │ │ │ └── @ EmbeddedStatementsNode (location: (136,16)-(136,25)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (136,16)-(136,18) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (136,18)-(136,24)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (136,18)-(136,24)) │ │ │ │ ├── flags: ignore_visibility @@ -1261,9 +1382,10 @@ │ │ │ │ ├── opening_loc: (136,19)-(136,20) = "(" │ │ │ │ ├── arguments: │ │ │ │ │ @ ArgumentsNode (location: (136,20)-(136,23)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: contains_forwarding │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ └── @ ForwardingArgumentsNode (location: (136,20)-(136,23)) + │ │ │ │ │ └── flags: ∅ │ │ │ │ ├── closing_loc: (136,23)-(136,24) = ")" │ │ │ │ └── block: ∅ │ │ │ └── closing_loc: (136,24)-(136,25) = "}" @@ -1276,17 +1398,20 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (136,28)-(136,31) = "end" ├── @ DefNode (location: (138,0)-(140,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (138,4)-(138,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (139,2)-(139,30)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (139,2)-(139,30)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ HashNode (location: (139,2)-(139,4)) + │ │ │ ├── flags: static_literal │ │ │ ├── opening_loc: (139,2)-(139,3) = "{" │ │ │ ├── elements: (length: 0) │ │ │ └── closing_loc: (139,3)-(139,4) = "}" @@ -1302,6 +1427,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── elements: (length: 3) │ │ │ ├── @ AssocSplatNode (location: (139,11)-(139,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── value: │ │ │ │ │ @ CallNode (location: (139,13)-(139,16)) │ │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -1315,6 +1441,7 @@ │ │ │ │ │ └── block: ∅ │ │ │ │ └── operator_loc: (139,11)-(139,13) = "**" │ │ │ ├── @ AssocSplatNode (location: (139,18)-(139,23)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── value: │ │ │ │ │ @ CallNode (location: (139,20)-(139,23)) │ │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -1328,6 +1455,7 @@ │ │ │ │ │ └── block: ∅ │ │ │ │ └── operator_loc: (139,18)-(139,20) = "**" │ │ │ └── @ AssocSplatNode (location: (139,25)-(139,30)) + │ │ │ ├── flags: ∅ │ │ │ ├── value: │ │ │ │ @ CallNode (location: (139,27)-(139,30)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -1350,11 +1478,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (140,0)-(140,3) = "end" ├── @ DefNode (location: (142,0)-(143,3)) + │ ├── flags: newline │ ├── name: :bar │ ├── name_loc: (142,4)-(142,7) = "bar" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (142,8)-(142,19)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -1366,18 +1496,20 @@ │ │ │ ├── name_loc: (142,8)-(142,10) = "a:" │ │ │ └── value: │ │ │ @ ParenthesesNode (location: (142,11)-(142,19)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (142,12)-(142,18)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ RangeNode (location: (142,12)-(142,18)) - │ │ │ │ ├── flags: exclude_end + │ │ │ │ ├── flags: newline, static_literal, exclude_end │ │ │ │ ├── left: │ │ │ │ │ @ IntegerNode (location: (142,12)-(142,13)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── right: │ │ │ │ │ @ IntegerNode (location: (142,16)-(142,18)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 10 │ │ │ │ └── operator_loc: (142,13)-(142,16) = "..." │ │ │ ├── opening_loc: (142,11)-(142,12) = "(" @@ -1393,11 +1525,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (143,0)-(143,3) = "end" ├── @ DefNode (location: (145,0)-(146,3)) + │ ├── flags: newline │ ├── name: :bar │ ├── name_loc: (145,4)-(145,7) = "bar" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (145,8)-(145,18)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -1409,15 +1543,17 @@ │ │ │ ├── name_loc: (145,8)-(145,10) = "a:" │ │ │ └── value: │ │ │ @ ParenthesesNode (location: (145,11)-(145,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (145,12)-(145,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ RangeNode (location: (145,12)-(145,17)) - │ │ │ │ ├── flags: exclude_end + │ │ │ │ ├── flags: newline, static_literal, exclude_end │ │ │ │ ├── left: ∅ │ │ │ │ ├── right: │ │ │ │ │ @ IntegerNode (location: (145,15)-(145,17)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 10 │ │ │ │ └── operator_loc: (145,12)-(145,15) = "..." │ │ │ ├── opening_loc: (145,11)-(145,12) = "(" @@ -1433,11 +1569,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (146,0)-(146,3) = "end" ├── @ DefNode (location: (148,0)-(149,3)) + │ ├── flags: newline │ ├── name: :bar │ ├── name_loc: (148,4)-(148,7) = "bar" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (148,8)-(148,17)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -1449,14 +1587,16 @@ │ │ │ ├── name_loc: (148,8)-(148,10) = "a:" │ │ │ └── value: │ │ │ @ ParenthesesNode (location: (148,11)-(148,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (148,12)-(148,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ RangeNode (location: (148,12)-(148,16)) - │ │ │ │ ├── flags: exclude_end + │ │ │ │ ├── flags: newline, static_literal, exclude_end │ │ │ │ ├── left: │ │ │ │ │ @ IntegerNode (location: (148,12)-(148,13)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── right: ∅ │ │ │ │ └── operator_loc: (148,13)-(148,16) = "..." @@ -1473,11 +1613,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (149,0)-(149,3) = "end" ├── @ DefNode (location: (151,0)-(152,3)) + │ ├── flags: newline │ ├── name: :bar │ ├── name_loc: (151,4)-(151,7) = "bar" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (151,8)-(151,20)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (151,8)-(151,20)) @@ -1487,18 +1629,20 @@ │ │ │ ├── operator_loc: (151,10)-(151,11) = "=" │ │ │ └── value: │ │ │ @ ParenthesesNode (location: (151,12)-(151,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (151,13)-(151,19)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ RangeNode (location: (151,13)-(151,19)) - │ │ │ │ ├── flags: exclude_end + │ │ │ │ ├── flags: newline, static_literal, exclude_end │ │ │ │ ├── left: │ │ │ │ │ @ IntegerNode (location: (151,13)-(151,14)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── right: │ │ │ │ │ @ IntegerNode (location: (151,17)-(151,19)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 10 │ │ │ │ └── operator_loc: (151,14)-(151,17) = "..." │ │ │ ├── opening_loc: (151,12)-(151,13) = "(" @@ -1517,11 +1661,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (152,0)-(152,3) = "end" ├── @ DefNode (location: (154,0)-(155,3)) + │ ├── flags: newline │ ├── name: :bar │ ├── name_loc: (154,4)-(154,7) = "bar" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (154,8)-(154,19)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (154,8)-(154,19)) @@ -1531,15 +1677,17 @@ │ │ │ ├── operator_loc: (154,10)-(154,11) = "=" │ │ │ └── value: │ │ │ @ ParenthesesNode (location: (154,12)-(154,19)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (154,13)-(154,18)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ RangeNode (location: (154,13)-(154,18)) - │ │ │ │ ├── flags: exclude_end + │ │ │ │ ├── flags: newline, static_literal, exclude_end │ │ │ │ ├── left: ∅ │ │ │ │ ├── right: │ │ │ │ │ @ IntegerNode (location: (154,16)-(154,18)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 10 │ │ │ │ └── operator_loc: (154,13)-(154,16) = "..." │ │ │ ├── opening_loc: (154,12)-(154,13) = "(" @@ -1558,11 +1706,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (155,0)-(155,3) = "end" ├── @ DefNode (location: (157,0)-(158,3)) + │ ├── flags: newline │ ├── name: :bar │ ├── name_loc: (157,4)-(157,7) = "bar" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (157,8)-(157,18)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (157,8)-(157,18)) @@ -1572,14 +1722,16 @@ │ │ │ ├── operator_loc: (157,10)-(157,11) = "=" │ │ │ └── value: │ │ │ @ ParenthesesNode (location: (157,12)-(157,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (157,13)-(157,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ RangeNode (location: (157,13)-(157,17)) - │ │ │ │ ├── flags: exclude_end + │ │ │ │ ├── flags: newline, static_literal, exclude_end │ │ │ │ ├── left: │ │ │ │ │ @ IntegerNode (location: (157,13)-(157,14)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── right: ∅ │ │ │ │ └── operator_loc: (157,14)-(157,17) = "..." @@ -1599,11 +1751,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (158,0)-(158,3) = "end" ├── @ DefNode (location: (160,0)-(162,3)) + │ ├── flags: newline │ ├── name: :method │ ├── name_loc: (160,4)-(160,10) = "method" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (160,11)-(160,12)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (160,11)-(160,12)) │ │ │ ├── flags: ∅ @@ -1616,9 +1770,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (161,2)-(161,14)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (161,2)-(161,14)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ CallNode (location: (161,2)-(161,6)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -1649,6 +1804,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: │ │ │ @ BlockNode (location: (161,12)-(161,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── locals: [] │ │ │ ├── parameters: ∅ │ │ │ ├── body: ∅ @@ -1664,19 +1820,22 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (162,0)-(162,3) = "end" ├── @ LocalVariableWriteNode (location: (164,0)-(164,7)) + │ ├── flags: newline │ ├── name: :foo │ ├── depth: 0 │ ├── name_loc: (164,0)-(164,3) = "foo" │ ├── value: │ │ @ IntegerNode (location: (164,6)-(164,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (164,4)-(164,5) = "=" ├── @ DefNode (location: (165,0)-(165,16)) + │ ├── flags: newline │ ├── name: :bar │ ├── name_loc: (165,8)-(165,11) = "bar" │ ├── receiver: │ │ @ LocalVariableReadNode (location: (165,4)-(165,7)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── depth: 0 │ ├── parameters: ∅ @@ -1689,11 +1848,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (165,13)-(165,16) = "end" ├── @ DefNode (location: (167,0)-(167,18)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (167,4)-(167,5) = "f" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (167,6)-(167,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: @@ -1708,11 +1869,13 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (167,10)-(167,13)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ ArrayNode (location: (167,10)-(167,13)) - │ │ ├── flags: contains_splat + │ │ ├── flags: newline, contains_splat │ │ ├── elements: (length: 1) │ │ │ └── @ SplatNode (location: (167,11)-(167,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (167,11)-(167,12) = "*" │ │ │ └── expression: ∅ │ │ ├── opening_loc: (167,10)-(167,11) = "[" @@ -1725,11 +1888,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (167,15)-(167,18) = "end" ├── @ DefNode (location: (169,0)-(169,15)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (169,4)-(169,5) = "f" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (169,6)-(169,10)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -1771,11 +1936,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (169,12)-(169,15) = "end" ├── @ DefNode (location: (171,0)-(171,15)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (171,4)-(171,5) = "f" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (171,6)-(171,10)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -1817,11 +1984,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (171,12)-(171,15) = "end" ├── @ DefNode (location: (173,0)-(173,15)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (173,4)-(173,5) = "f" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (173,6)-(173,10)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -1863,11 +2032,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (173,12)-(173,15) = "end" ├── @ DefNode (location: (175,0)-(175,20)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (175,4)-(175,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (175,8)-(175,15)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -1895,11 +2066,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (175,17)-(175,20) = "end" ├── @ DefNode (location: (177,0)-(179,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (177,4)-(177,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (177,8)-(177,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -1907,12 +2080,14 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ ForwardingParameterNode (location: (177,8)-(177,11)) + │ │ │ └── flags: ∅ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (178,2)-(178,10)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (178,2)-(178,10)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -1920,9 +2095,10 @@ │ │ ├── opening_loc: (178,5)-(178,6) = "(" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (178,6)-(178,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_forwarding │ │ │ └── arguments: (length: 1) │ │ │ └── @ ForwardingArgumentsNode (location: (178,6)-(178,9)) + │ │ │ └── flags: ∅ │ │ ├── closing_loc: (178,9)-(178,10) = ")" │ │ └── block: ∅ │ ├── locals: [] @@ -1933,11 +2109,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (179,0)-(179,3) = "end" ├── @ DefNode (location: (181,0)-(181,42)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (181,4)-(181,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (181,8)-(181,37)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (181,8)-(181,37)) @@ -1947,15 +2125,19 @@ │ │ │ ├── operator_loc: (181,12)-(181,13) = "=" │ │ │ └── value: │ │ │ @ ParenthesesNode (location: (181,14)-(181,37)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (181,15)-(181,36)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 2) │ │ │ │ ├── @ DefNode (location: (181,15)-(181,33)) + │ │ │ │ │ ├── flags: newline │ │ │ │ │ ├── name: :baz │ │ │ │ │ ├── name_loc: (181,19)-(181,22) = "baz" │ │ │ │ │ ├── receiver: ∅ │ │ │ │ │ ├── parameters: │ │ │ │ │ │ @ ParametersNode (location: (181,23)-(181,26)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ │ │ └── @ RequiredParameterNode (location: (181,23)-(181,26)) │ │ │ │ │ │ │ ├── flags: ∅ @@ -1968,8 +2150,10 @@ │ │ │ │ │ │ └── block: ∅ │ │ │ │ │ ├── body: │ │ │ │ │ │ @ StatementsNode (location: (181,30)-(181,33)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ │ └── @ LocalVariableReadNode (location: (181,30)-(181,33)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── name: :bar │ │ │ │ │ │ └── depth: 0 │ │ │ │ │ ├── locals: [:bar] @@ -1980,7 +2164,7 @@ │ │ │ │ │ ├── equal_loc: (181,28)-(181,29) = "=" │ │ │ │ │ └── end_keyword_loc: ∅ │ │ │ │ └── @ IntegerNode (location: (181,35)-(181,36)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── opening_loc: (181,14)-(181,15) = "(" │ │ │ └── closing_loc: (181,36)-(181,37) = ")" @@ -1991,9 +2175,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (181,41)-(181,42)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (181,41)-(181,42)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── locals: [:bar] │ ├── def_keyword_loc: (181,0)-(181,3) = "def" @@ -2002,53 +2187,126 @@ │ ├── rparen_loc: (181,37)-(181,38) = ")" │ ├── equal_loc: (181,39)-(181,40) = "=" │ └── end_keyword_loc: ∅ - └── @ DefNode (location: (183,0)-(183,37)) - ├── name: :foo - ├── name_loc: (183,21)-(183,24) = "foo" - ├── receiver: - │ @ ParenthesesNode (location: (183,4)-(183,20)) - │ ├── body: - │ │ @ ClassNode (location: (183,5)-(183,19)) - │ │ ├── locals: [] - │ │ ├── class_keyword_loc: (183,5)-(183,10) = "class" - │ │ ├── constant_path: - │ │ │ @ ConstantReadNode (location: (183,11)-(183,14)) - │ │ │ └── name: :Foo - │ │ ├── inheritance_operator_loc: ∅ - │ │ ├── superclass: ∅ - │ │ ├── body: ∅ - │ │ ├── end_keyword_loc: (183,16)-(183,19) = "end" - │ │ └── name: :Foo - │ ├── opening_loc: (183,4)-(183,5) = "(" - │ └── closing_loc: (183,19)-(183,20) = ")" - ├── parameters: - │ @ ParametersNode (location: (183,25)-(183,32)) - │ ├── requireds: (length: 0) - │ ├── optionals: (length: 1) - │ │ └── @ OptionalParameterNode (location: (183,25)-(183,32)) - │ │ ├── flags: ∅ - │ │ ├── name: :bar - │ │ ├── name_loc: (183,25)-(183,28) = "bar" - │ │ ├── operator_loc: (183,29)-(183,30) = "=" - │ │ └── value: - │ │ @ IntegerNode (location: (183,31)-(183,32)) - │ │ ├── flags: decimal - │ │ └── value: 1 - │ ├── rest: ∅ - │ ├── posts: (length: 0) - │ ├── keywords: (length: 0) - │ ├── keyword_rest: ∅ - │ └── block: ∅ + ├── @ DefNode (location: (183,0)-(183,37)) + │ ├── flags: newline + │ ├── name: :foo + │ ├── name_loc: (183,21)-(183,24) = "foo" + │ ├── receiver: + │ │ @ ParenthesesNode (location: (183,4)-(183,20)) + │ │ ├── flags: ∅ + │ │ ├── body: + │ │ │ @ ClassNode (location: (183,5)-(183,19)) + │ │ │ ├── flags: ∅ + │ │ │ ├── locals: [] + │ │ │ ├── class_keyword_loc: (183,5)-(183,10) = "class" + │ │ │ ├── constant_path: + │ │ │ │ @ ConstantReadNode (location: (183,11)-(183,14)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :Foo + │ │ │ ├── inheritance_operator_loc: ∅ + │ │ │ ├── superclass: ∅ + │ │ │ ├── body: ∅ + │ │ │ ├── end_keyword_loc: (183,16)-(183,19) = "end" + │ │ │ └── name: :Foo + │ │ ├── opening_loc: (183,4)-(183,5) = "(" + │ │ └── closing_loc: (183,19)-(183,20) = ")" + │ ├── parameters: + │ │ @ ParametersNode (location: (183,25)-(183,32)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 0) + │ │ ├── optionals: (length: 1) + │ │ │ └── @ OptionalParameterNode (location: (183,25)-(183,32)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :bar + │ │ │ ├── name_loc: (183,25)-(183,28) = "bar" + │ │ │ ├── operator_loc: (183,29)-(183,30) = "=" + │ │ │ └── value: + │ │ │ @ IntegerNode (location: (183,31)-(183,32)) + │ │ │ ├── flags: static_literal, decimal + │ │ │ └── value: 1 + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: + │ │ @ StatementsNode (location: (183,36)-(183,37)) + │ │ ├── flags: ∅ + │ │ └── body: (length: 1) + │ │ └── @ IntegerNode (location: (183,36)-(183,37)) + │ │ ├── flags: static_literal, decimal + │ │ └── value: 2 + │ ├── locals: [:bar] + │ ├── def_keyword_loc: (183,0)-(183,3) = "def" + │ ├── operator_loc: (183,20)-(183,21) = "." + │ ├── lparen_loc: (183,24)-(183,25) = "(" + │ ├── rparen_loc: (183,32)-(183,33) = ")" + │ ├── equal_loc: (183,34)-(183,35) = "=" + │ └── end_keyword_loc: ∅ + └── @ ModuleNode (location: (185,0)-(188,3)) + ├── flags: newline + ├── locals: [] + ├── module_keyword_loc: (185,0)-(185,6) = "module" + ├── constant_path: + │ @ ConstantReadNode (location: (185,7)-(185,10)) + │ ├── flags: ∅ + │ └── name: :Foo ├── body: - │ @ StatementsNode (location: (183,36)-(183,37)) + │ @ StatementsNode (location: (186,2)-(187,5)) + │ ├── flags: ∅ │ └── body: (length: 1) - │ └── @ IntegerNode (location: (183,36)-(183,37)) - │ ├── flags: decimal - │ └── value: 2 - ├── locals: [:bar] - ├── def_keyword_loc: (183,0)-(183,3) = "def" - ├── operator_loc: (183,20)-(183,21) = "." - ├── lparen_loc: (183,24)-(183,25) = "(" - ├── rparen_loc: (183,32)-(183,33) = ")" - ├── equal_loc: (183,34)-(183,35) = "=" - └── end_keyword_loc: ∅ + │ └── @ DefNode (location: (186,2)-(187,5)) + │ ├── flags: newline + │ ├── name: :clone + │ ├── name_loc: (186,6)-(186,11) = "clone" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (186,12)-(186,39)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 0) + │ │ ├── optionals: (length: 1) + │ │ │ └── @ OptionalParameterNode (location: (186,12)-(186,39)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :opts + │ │ │ ├── name_loc: (186,12)-(186,16) = "opts" + │ │ │ ├── operator_loc: (186,17)-(186,18) = "=" + │ │ │ └── value: + │ │ │ @ OrNode (location: (186,19)-(186,39)) + │ │ │ ├── flags: ∅ + │ │ │ ├── left: + │ │ │ │ @ NilNode (location: (186,19)-(186,22)) + │ │ │ │ └── flags: static_literal + │ │ │ ├── right: + │ │ │ │ @ ParenthesesNode (location: (186,26)-(186,39)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── body: + │ │ │ │ │ @ StatementsNode (location: (186,27)-(186,38)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ └── body: (length: 1) + │ │ │ │ │ └── @ ReturnNode (location: (186,27)-(186,38)) + │ │ │ │ │ ├── flags: newline + │ │ │ │ │ ├── keyword_loc: (186,27)-(186,33) = "return" + │ │ │ │ │ └── arguments: + │ │ │ │ │ @ ArgumentsNode (location: (186,34)-(186,38)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ └── arguments: (length: 1) + │ │ │ │ │ └── @ SelfNode (location: (186,34)-(186,38)) + │ │ │ │ │ └── flags: ∅ + │ │ │ │ ├── opening_loc: (186,26)-(186,27) = "(" + │ │ │ │ └── closing_loc: (186,38)-(186,39) = ")" + │ │ │ └── operator_loc: (186,23)-(186,25) = "||" + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:opts] + │ ├── def_keyword_loc: (186,2)-(186,5) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (186,11)-(186,12) = "(" + │ ├── rparen_loc: (186,39)-(186,40) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (187,2)-(187,5) = "end" + ├── end_keyword_loc: (188,0)-(188,3) = "end" + └── name: :Foo diff --git a/test/prism/snapshots/modules.txt b/test/prism/snapshots/modules.txt index de1ea8feebc..5e001229014 100644 --- a/test/prism/snapshots/modules.txt +++ b/test/prism/snapshots/modules.txt @@ -1,42 +1,50 @@ @ ProgramNode (location: (1,0)-(18,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(18,3)) + ├── flags: ∅ └── body: (length: 7) ├── @ ModuleNode (location: (1,0)-(1,18)) + │ ├── flags: newline │ ├── locals: [:a] │ ├── module_keyword_loc: (1,0)-(1,6) = "module" │ ├── constant_path: │ │ @ ConstantReadNode (location: (1,7)-(1,8)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── body: │ │ @ StatementsNode (location: (1,9)-(1,14)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableWriteNode (location: (1,9)-(1,14)) + │ │ ├── flags: newline │ │ ├── name: :a │ │ ├── depth: 0 │ │ ├── name_loc: (1,9)-(1,10) = "a" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,13)-(1,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── operator_loc: (1,11)-(1,12) = "=" │ ├── end_keyword_loc: (1,15)-(1,18) = "end" │ └── name: :A ├── @ InterpolatedStringNode (location: (3,0)-(3,18)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (3,0)-(3,3) = "%Q{" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (3,3)-(3,7)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (3,3)-(3,7) = "aaa " │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "aaa " │ │ ├── @ EmbeddedStatementsNode (location: (3,7)-(3,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (3,7)-(3,9) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (3,9)-(3,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (3,9)-(3,12)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -50,17 +58,19 @@ │ │ │ │ └── block: ∅ │ │ │ └── closing_loc: (3,12)-(3,13) = "}" │ │ └── @ StringNode (location: (3,13)-(3,17)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (3,13)-(3,17) = " ccc" │ │ ├── closing_loc: ∅ │ │ └── unescaped: " ccc" │ └── closing_loc: (3,17)-(3,18) = "}" ├── @ ModuleNode (location: (5,0)-(6,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── module_keyword_loc: (5,0)-(5,6) = "module" │ ├── constant_path: │ │ @ ConstantPathNode (location: (5,7)-(5,11)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ CallNode (location: (5,7)-(5,8)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -79,44 +89,52 @@ │ ├── end_keyword_loc: (6,0)-(6,3) = "end" │ └── name: :M ├── @ ModuleNode (location: (8,0)-(9,19)) + │ ├── flags: newline │ ├── locals: [:x] │ ├── module_keyword_loc: (8,0)-(8,6) = "module" │ ├── constant_path: │ │ @ ConstantReadNode (location: (8,7)-(8,8)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── body: │ │ @ BeginNode (location: (8,0)-(9,19)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (9,1)-(9,6)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ LocalVariableWriteNode (location: (9,1)-(9,6)) + │ │ │ ├── flags: newline │ │ │ ├── name: :x │ │ │ ├── depth: 0 │ │ │ ├── name_loc: (9,1)-(9,2) = "x" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (9,5)-(9,6)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── operator_loc: (9,3)-(9,4) = "=" │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (9,8)-(9,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (9,8)-(9,14) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (9,16)-(9,19) = "end" │ ├── end_keyword_loc: (9,16)-(9,19) = "end" │ └── name: :A ├── @ ModuleNode (location: (11,0)-(12,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── module_keyword_loc: (11,0)-(11,6) = "module" │ ├── constant_path: │ │ @ ConstantPathNode (location: (11,7)-(11,10)) + │ │ ├── flags: ∅ │ │ ├── parent: ∅ │ │ ├── name: :A │ │ ├── delimiter_loc: (11,7)-(11,9) = "::" @@ -125,15 +143,18 @@ │ ├── end_keyword_loc: (12,0)-(12,3) = "end" │ └── name: :A ├── @ ModuleNode (location: (14,0)-(15,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── module_keyword_loc: (14,0)-(14,6) = "module" │ ├── constant_path: │ │ @ ConstantPathNode (location: (14,7)-(14,13)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ CallNode (location: (14,7)-(14,10)) │ │ │ ├── flags: ∅ │ │ │ ├── receiver: │ │ │ │ @ ConstantReadNode (location: (14,7)-(14,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :A │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :[] @@ -149,15 +170,18 @@ │ ├── end_keyword_loc: (15,0)-(15,3) = "end" │ └── name: :B └── @ ModuleNode (location: (17,0)-(18,3)) + ├── flags: newline ├── locals: [] ├── module_keyword_loc: (17,0)-(17,6) = "module" ├── constant_path: │ @ ConstantPathNode (location: (17,7)-(17,14)) + │ ├── flags: ∅ │ ├── parent: │ │ @ CallNode (location: (17,7)-(17,11)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ ConstantReadNode (location: (17,7)-(17,8)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── call_operator_loc: ∅ │ │ ├── name: :[] @@ -168,7 +192,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (17,9)-(17,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: (17,10)-(17,11) = "]" │ │ └── block: ∅ diff --git a/test/prism/snapshots/multi_write.txt b/test/prism/snapshots/multi_write.txt index d313801fdb2..fa36f50423f 100644 --- a/test/prism/snapshots/multi_write.txt +++ b/test/prism/snapshots/multi_write.txt @@ -1,28 +1,36 @@ @ ProgramNode (location: (1,0)-(4,26)) +├── flags: ∅ ├── locals: [:foo, :bar] └── statements: @ StatementsNode (location: (1,0)-(4,26)) + ├── flags: ∅ └── body: (length: 4) ├── @ LocalVariableWriteNode (location: (1,0)-(1,18)) + │ ├── flags: newline │ ├── name: :foo │ ├── depth: 0 │ ├── name_loc: (1,0)-(1,3) = "foo" │ ├── value: │ │ @ RescueModifierNode (location: (1,6)-(1,18)) + │ │ ├── flags: ∅ │ │ ├── expression: │ │ │ @ IntegerNode (location: (1,6)-(1,7)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── keyword_loc: (1,8)-(1,14) = "rescue" │ │ └── rescue_expression: │ │ @ NilNode (location: (1,15)-(1,18)) + │ │ └── flags: static_literal │ └── operator_loc: (1,4)-(1,5) = "=" ├── @ MultiWriteNode (location: (2,0)-(2,23)) + │ ├── flags: newline │ ├── lefts: (length: 2) │ │ ├── @ LocalVariableTargetNode (location: (2,0)-(2,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :foo │ │ │ └── depth: 0 │ │ └── @ LocalVariableTargetNode (location: (2,5)-(2,8)) + │ │ ├── flags: ∅ │ │ ├── name: :bar │ │ └── depth: 0 │ ├── rest: ∅ @@ -32,28 +40,32 @@ │ ├── operator_loc: (2,9)-(2,10) = "=" │ └── value: │ @ RescueModifierNode (location: (2,11)-(2,23)) + │ ├── flags: ∅ │ ├── expression: │ │ @ IntegerNode (location: (2,11)-(2,12)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── keyword_loc: (2,13)-(2,19) = "rescue" │ └── rescue_expression: │ @ NilNode (location: (2,20)-(2,23)) + │ └── flags: static_literal ├── @ RescueModifierNode (location: (3,0)-(3,21)) + │ ├── flags: newline │ ├── expression: │ │ @ LocalVariableWriteNode (location: (3,0)-(3,10)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ ├── depth: 0 │ │ ├── name_loc: (3,0)-(3,3) = "foo" │ │ ├── value: │ │ │ @ ArrayNode (location: (3,6)-(3,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: static_literal │ │ │ ├── elements: (length: 2) │ │ │ │ ├── @ IntegerNode (location: (3,6)-(3,7)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ └── @ IntegerNode (location: (3,9)-(3,10)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ ├── opening_loc: ∅ │ │ │ └── closing_loc: ∅ @@ -61,12 +73,16 @@ │ ├── keyword_loc: (3,11)-(3,17) = "rescue" │ └── rescue_expression: │ @ NilNode (location: (3,18)-(3,21)) + │ └── flags: static_literal └── @ MultiWriteNode (location: (4,0)-(4,26)) + ├── flags: newline ├── lefts: (length: 2) │ ├── @ LocalVariableTargetNode (location: (4,0)-(4,3)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── depth: 0 │ └── @ LocalVariableTargetNode (location: (4,5)-(4,8)) + │ ├── flags: ∅ │ ├── name: :bar │ └── depth: 0 ├── rest: ∅ @@ -76,18 +92,20 @@ ├── operator_loc: (4,9)-(4,10) = "=" └── value: @ RescueModifierNode (location: (4,11)-(4,26)) + ├── flags: ∅ ├── expression: │ @ ArrayNode (location: (4,11)-(4,15)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (4,11)-(4,12)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (4,14)-(4,15)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: ∅ │ └── closing_loc: ∅ ├── keyword_loc: (4,16)-(4,22) = "rescue" └── rescue_expression: @ NilNode (location: (4,23)-(4,26)) + └── flags: static_literal diff --git a/test/prism/snapshots/newline_terminated.txt b/test/prism/snapshots/newline_terminated.txt index 6a3b28dba98..85e996fa5a2 100644 --- a/test/prism/snapshots/newline_terminated.txt +++ b/test/prism/snapshots/newline_terminated.txt @@ -1,106 +1,108 @@ @ ProgramNode (location: (3,0)-(41,0)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (3,0)-(41,0)) + ├── flags: ∅ └── body: (length: 17) ├── @ StringNode (location: (3,0)-(3,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (3,0)-(3,2) = "% " │ ├── content_loc: (3,2)-(3,5) = "abc" │ ├── closing_loc: (3,5)-(3,6) = " " │ └── unescaped: "abc" ├── @ StringNode (location: (4,0)-(4,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (4,0)-(4,2) = "%\t" │ ├── content_loc: (4,2)-(4,5) = "abc" │ ├── closing_loc: (4,5)-(4,6) = "\t" │ └── unescaped: "abc" ├── @ StringNode (location: (5,0)-(5,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (5,0)-(5,2) = "%\v" │ ├── content_loc: (5,2)-(5,5) = "abc" │ ├── closing_loc: (5,5)-(5,6) = "\v" │ └── unescaped: "abc" ├── @ StringNode (location: (6,0)-(6,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (6,0)-(6,2) = "%\r" │ ├── content_loc: (6,2)-(6,5) = "abc" │ ├── closing_loc: (6,5)-(6,6) = "\r" │ └── unescaped: "abc" ├── @ StringNode (location: (7,0)-(9,0)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (7,0)-(8,0) = "%\n" │ ├── content_loc: (8,0)-(8,3) = "abc" │ ├── closing_loc: (8,3)-(9,0) = "\n" │ └── unescaped: "abc" ├── @ StringNode (location: (10,0)-(10,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (10,0)-(10,2) = "%\u0000" │ ├── content_loc: (10,2)-(10,5) = "abc" │ ├── closing_loc: (10,5)-(10,6) = "\u0000" │ └── unescaped: "abc" ├── @ StringNode (location: (11,0)-(13,0)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (11,0)-(12,0) = "%\n" │ ├── content_loc: (12,0)-(12,3) = "abc" │ ├── closing_loc: (12,3)-(13,0) = "\n" │ └── unescaped: "abc" ├── @ StringNode (location: (14,0)-(16,0)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (14,0)-(15,0) = "%\n" │ ├── content_loc: (15,0)-(15,4) = "\rabc" │ ├── closing_loc: (15,4)-(16,0) = "\n" │ └── unescaped: "\rabc" ├── @ StringNode (location: (17,0)-(19,0)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (17,0)-(18,0) = "%\n" │ ├── content_loc: (18,0)-(18,4) = "\rabc" │ ├── closing_loc: (18,4)-(19,0) = "\n" │ └── unescaped: "\rabc" ├── @ StringNode (location: (20,0)-(22,0)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (20,0)-(21,0) = "%\n" │ ├── content_loc: (21,0)-(21,3) = "abc" │ ├── closing_loc: (21,3)-(22,0) = "\n" │ └── unescaped: "abc" ├── @ StringNode (location: (23,0)-(23,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (23,0)-(23,2) = "%\r" │ ├── content_loc: (23,2)-(23,5) = "abc" │ ├── closing_loc: (23,5)-(23,6) = "\r" │ └── unescaped: "abc" ├── @ StringNode (location: (24,0)-(26,0)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (24,0)-(25,0) = "%\n" │ ├── content_loc: (25,0)-(25,3) = "abc" │ ├── closing_loc: (25,3)-(26,0) = "\n" │ └── unescaped: "abc" ├── @ StringNode (location: (27,0)-(29,0)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (27,0)-(28,0) = "%\n" │ ├── content_loc: (28,0)-(28,3) = "abc" │ ├── closing_loc: (28,3)-(29,0) = "\n" │ └── unescaped: "abc" ├── @ StringNode (location: (30,0)-(32,0)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (30,0)-(31,0) = "%\n" │ ├── content_loc: (31,0)-(31,3) = "foo" │ ├── closing_loc: (31,3)-(32,0) = "\n" │ └── unescaped: "foo" ├── @ StringNode (location: (33,0)-(35,0)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (33,0)-(34,0) = "%q\n" │ ├── content_loc: (34,0)-(34,3) = "foo" │ ├── closing_loc: (34,3)-(35,0) = "\n" │ └── unescaped: "foo" ├── @ StringNode (location: (36,0)-(38,0)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (36,0)-(37,0) = "%Q\n" │ ├── content_loc: (37,0)-(37,3) = "foo" │ ├── closing_loc: (37,3)-(38,0) = "\n" │ └── unescaped: "foo" └── @ RegularExpressionNode (location: (39,0)-(41,0)) - ├── flags: forced_us_ascii_encoding + ├── flags: newline, static_literal, forced_us_ascii_encoding ├── opening_loc: (39,0)-(40,0) = "%r\n" ├── content_loc: (40,0)-(40,3) = "foo" ├── closing_loc: (40,3)-(41,0) = "\n" diff --git a/test/prism/snapshots/next.txt b/test/prism/snapshots/next.txt index ce2e497de93..5b0becea1c8 100644 --- a/test/prism/snapshots/next.txt +++ b/test/prism/snapshots/next.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(24,15)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(24,15)) + ├── flags: ∅ └── body: (length: 10) ├── @ CallNode (location: (1,0)-(1,12)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -14,18 +16,21 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (1,4)-(1,12)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,6)-(1,10)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NextNode (location: (1,6)-(1,10)) + │ │ ├── flags: newline │ │ ├── arguments: ∅ │ │ └── keyword_loc: (1,6)-(1,10) = "next" │ ├── opening_loc: (1,4)-(1,5) = "{" │ └── closing_loc: (1,11)-(1,12) = "}" ├── @ CallNode (location: (3,0)-(3,26)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -35,40 +40,49 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (3,4)-(3,26)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (3,6)-(3,24)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NextNode (location: (3,6)-(3,24)) + │ │ ├── flags: newline │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (3,11)-(3,24)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 3) │ │ │ ├── @ ParenthesesNode (location: (3,11)-(3,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── body: │ │ │ │ │ @ StatementsNode (location: (3,12)-(3,13)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (3,12)-(3,13)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── opening_loc: (3,11)-(3,12) = "(" │ │ │ │ └── closing_loc: (3,13)-(3,14) = ")" │ │ │ ├── @ ParenthesesNode (location: (3,16)-(3,19)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── body: │ │ │ │ │ @ StatementsNode (location: (3,17)-(3,18)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (3,17)-(3,18)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ │ └── value: 2 │ │ │ │ ├── opening_loc: (3,16)-(3,17) = "(" │ │ │ │ └── closing_loc: (3,18)-(3,19) = ")" │ │ │ └── @ ParenthesesNode (location: (3,21)-(3,24)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (3,22)-(3,23)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (3,22)-(3,23)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ └── value: 3 │ │ │ ├── opening_loc: (3,21)-(3,22) = "(" │ │ │ └── closing_loc: (3,23)-(3,24) = ")" @@ -76,7 +90,7 @@ │ ├── opening_loc: (3,4)-(3,5) = "{" │ └── closing_loc: (3,25)-(3,26) = "}" ├── @ CallNode (location: (5,0)-(5,14)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -86,24 +100,27 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (5,4)-(5,14)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (5,6)-(5,12)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NextNode (location: (5,6)-(5,12)) + │ │ ├── flags: newline │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (5,11)-(5,12)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (5,11)-(5,12)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── keyword_loc: (5,6)-(5,10) = "next" │ ├── opening_loc: (5,4)-(5,5) = "{" │ └── closing_loc: (5,13)-(5,14) = "}" ├── @ CallNode (location: (7,0)-(8,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -113,30 +130,33 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (7,4)-(8,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (7,6)-(8,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NextNode (location: (7,6)-(8,1)) + │ │ ├── flags: newline │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (7,11)-(8,1)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 3) │ │ │ ├── @ IntegerNode (location: (7,11)-(7,12)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── @ IntegerNode (location: (7,14)-(7,15)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ └── @ IntegerNode (location: (8,0)-(8,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ └── keyword_loc: (7,6)-(7,10) = "next" │ ├── opening_loc: (7,4)-(7,5) = "{" │ └── closing_loc: (8,2)-(8,3) = "}" ├── @ CallNode (location: (10,0)-(10,20)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -146,30 +166,33 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (10,4)-(10,20)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (10,6)-(10,18)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NextNode (location: (10,6)-(10,18)) + │ │ ├── flags: newline │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (10,11)-(10,18)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 3) │ │ │ ├── @ IntegerNode (location: (10,11)-(10,12)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── @ IntegerNode (location: (10,14)-(10,15)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ └── @ IntegerNode (location: (10,17)-(10,18)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ └── keyword_loc: (10,6)-(10,10) = "next" │ ├── opening_loc: (10,4)-(10,5) = "{" │ └── closing_loc: (10,19)-(10,20) = "}" ├── @ CallNode (location: (12,0)-(12,22)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -179,27 +202,30 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (12,4)-(12,22)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (12,6)-(12,20)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NextNode (location: (12,6)-(12,20)) + │ │ ├── flags: newline │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (12,11)-(12,20)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ ArrayNode (location: (12,11)-(12,20)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: static_literal │ │ │ ├── elements: (length: 3) │ │ │ │ ├── @ IntegerNode (location: (12,12)-(12,13)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── @ IntegerNode (location: (12,15)-(12,16)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 2 │ │ │ │ └── @ IntegerNode (location: (12,18)-(12,19)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 3 │ │ │ ├── opening_loc: (12,11)-(12,12) = "[" │ │ │ └── closing_loc: (12,19)-(12,20) = "]" @@ -207,7 +233,7 @@ │ ├── opening_loc: (12,4)-(12,5) = "{" │ └── closing_loc: (12,21)-(12,22) = "}" ├── @ CallNode (location: (14,0)-(17,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -217,25 +243,30 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (14,4)-(17,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (14,6)-(17,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NextNode (location: (14,6)-(17,1)) + │ │ ├── flags: newline │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (14,10)-(17,1)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ ParenthesesNode (location: (14,10)-(17,1)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (15,2)-(16,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 2) │ │ │ │ ├── @ IntegerNode (location: (15,2)-(15,3)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ └── @ IntegerNode (location: (16,2)-(16,3)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ └── value: 2 │ │ │ ├── opening_loc: (14,10)-(14,11) = "(" │ │ │ └── closing_loc: (17,0)-(17,1) = ")" @@ -243,7 +274,7 @@ │ ├── opening_loc: (14,4)-(14,5) = "{" │ └── closing_loc: (17,2)-(17,3) = "}" ├── @ CallNode (location: (19,0)-(20,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -253,21 +284,24 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (19,4)-(20,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (19,6)-(20,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 2) │ │ ├── @ NextNode (location: (19,6)-(19,10)) + │ │ │ ├── flags: newline │ │ │ ├── arguments: ∅ │ │ │ └── keyword_loc: (19,6)-(19,10) = "next" │ │ └── @ IntegerNode (location: (20,0)-(20,1)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 1 │ ├── opening_loc: (19,4)-(19,5) = "{" │ └── closing_loc: (20,2)-(20,3) = "}" ├── @ CallNode (location: (22,0)-(22,14)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -277,17 +311,21 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (22,4)-(22,14)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (22,6)-(22,12)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NextNode (location: (22,6)-(22,12)) + │ │ ├── flags: newline │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (22,10)-(22,12)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ ParenthesesNode (location: (22,10)-(22,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: ∅ │ │ │ ├── opening_loc: (22,10)-(22,11) = "(" │ │ │ └── closing_loc: (22,11)-(22,12) = ")" @@ -295,7 +333,7 @@ │ ├── opening_loc: (22,4)-(22,5) = "{" │ └── closing_loc: (22,13)-(22,14) = "}" └── @ CallNode (location: (24,0)-(24,15)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :tap @@ -305,22 +343,27 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (24,4)-(24,15)) + ├── flags: ∅ ├── locals: [] ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (24,6)-(24,13)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ NextNode (location: (24,6)-(24,13)) + │ ├── flags: newline │ ├── arguments: │ │ @ ArgumentsNode (location: (24,10)-(24,13)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ ParenthesesNode (location: (24,10)-(24,13)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (24,11)-(24,12)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (24,11)-(24,12)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: newline, static_literal, decimal │ │ │ └── value: 1 │ │ ├── opening_loc: (24,10)-(24,11) = "(" │ │ └── closing_loc: (24,12)-(24,13) = ")" diff --git a/test/prism/snapshots/nils.txt b/test/prism/snapshots/nils.txt index f72745560fe..275bc373a53 100644 --- a/test/prism/snapshots/nils.txt +++ b/test/prism/snapshots/nils.txt @@ -1,33 +1,42 @@ @ ProgramNode (location: (1,0)-(12,11)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(12,11)) + ├── flags: ∅ └── body: (length: 5) ├── @ NilNode (location: (1,0)-(1,3)) + │ └── flags: newline, static_literal ├── @ ParenthesesNode (location: (3,0)-(3,2)) + │ ├── flags: newline │ ├── body: ∅ │ ├── opening_loc: (3,0)-(3,1) = "(" │ └── closing_loc: (3,1)-(3,2) = ")" ├── @ ParenthesesNode (location: (5,0)-(8,1)) + │ ├── flags: newline │ ├── body: ∅ │ ├── opening_loc: (5,0)-(5,1) = "(" │ └── closing_loc: (8,0)-(8,1) = ")" ├── @ PostExecutionNode (location: (10,0)-(10,9)) + │ ├── flags: newline │ ├── statements: │ │ @ StatementsNode (location: (10,6)-(10,7)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (10,6)-(10,7)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 1 │ ├── keyword_loc: (10,0)-(10,3) = "END" │ ├── opening_loc: (10,4)-(10,5) = "{" │ └── closing_loc: (10,8)-(10,9) = "}" └── @ PreExecutionNode (location: (12,0)-(12,11)) + ├── flags: newline ├── statements: │ @ StatementsNode (location: (12,8)-(12,9)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ IntegerNode (location: (12,8)-(12,9)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 1 ├── keyword_loc: (12,0)-(12,5) = "BEGIN" ├── opening_loc: (12,6)-(12,7) = "{" diff --git a/test/prism/snapshots/non_alphanumeric_methods.txt b/test/prism/snapshots/non_alphanumeric_methods.txt index 2ed66fe0e2e..2d29d365e46 100644 --- a/test/prism/snapshots/non_alphanumeric_methods.txt +++ b/test/prism/snapshots/non_alphanumeric_methods.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(105,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(105,3)) + ├── flags: ∅ └── body: (length: 36) ├── @ DefNode (location: (1,0)-(2,3)) + │ ├── flags: newline │ ├── name: :! │ ├── name_loc: (1,4)-(1,5) = "!" │ ├── receiver: ∅ @@ -17,6 +20,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (2,0)-(2,3) = "end" ├── @ DefNode (location: (4,0)-(5,3)) + │ ├── flags: newline │ ├── name: :!= │ ├── name_loc: (4,4)-(4,6) = "!=" │ ├── receiver: ∅ @@ -30,6 +34,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (5,0)-(5,3) = "end" ├── @ DefNode (location: (7,0)-(8,3)) + │ ├── flags: newline │ ├── name: :!~ │ ├── name_loc: (7,4)-(7,6) = "!~" │ ├── receiver: ∅ @@ -43,6 +48,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (8,0)-(8,3) = "end" ├── @ DefNode (location: (10,0)-(11,3)) + │ ├── flags: newline │ ├── name: :% │ ├── name_loc: (10,4)-(10,5) = "%" │ ├── receiver: ∅ @@ -56,10 +62,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (11,0)-(11,3) = "end" ├── @ DefNode (location: (13,0)-(14,3)) + │ ├── flags: newline │ ├── name: :+ │ ├── name_loc: (13,9)-(13,10) = "+" │ ├── receiver: │ │ @ SelfNode (location: (13,4)-(13,8)) + │ │ └── flags: ∅ │ ├── parameters: ∅ │ ├── body: ∅ │ ├── locals: [] @@ -70,6 +78,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (14,0)-(14,3) = "end" ├── @ DefNode (location: (16,0)-(17,3)) + │ ├── flags: newline │ ├── name: :& │ ├── name_loc: (16,4)-(16,5) = "&" │ ├── receiver: ∅ @@ -83,6 +92,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (17,0)-(17,3) = "end" ├── @ DefNode (location: (19,0)-(20,3)) + │ ├── flags: newline │ ├── name: :* │ ├── name_loc: (19,4)-(19,5) = "*" │ ├── receiver: ∅ @@ -96,6 +106,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (20,0)-(20,3) = "end" ├── @ DefNode (location: (22,0)-(23,3)) + │ ├── flags: newline │ ├── name: :** │ ├── name_loc: (22,4)-(22,6) = "**" │ ├── receiver: ∅ @@ -109,17 +120,19 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (23,0)-(23,3) = "end" ├── @ StringNode (location: (25,0)-(25,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (25,0)-(25,2) = "%|" │ ├── content_loc: (25,2)-(25,5) = "abc" │ ├── closing_loc: (25,5)-(25,6) = "|" │ └── unescaped: "abc" ├── @ DefNode (location: (27,0)-(28,3)) + │ ├── flags: newline │ ├── name: :+ │ ├── name_loc: (27,4)-(27,5) = "+" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (27,6)-(27,9)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -141,6 +154,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (28,0)-(28,3) = "end" ├── @ DefNode (location: (30,0)-(31,3)) + │ ├── flags: newline │ ├── name: :+ │ ├── name_loc: (30,4)-(30,5) = "+" │ ├── receiver: ∅ @@ -154,11 +168,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (31,0)-(31,3) = "end" ├── @ DefNode (location: (33,0)-(34,3)) + │ ├── flags: newline │ ├── name: :+ │ ├── name_loc: (33,4)-(33,5) = "+" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (33,6)-(33,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (33,6)-(33,7)) │ │ │ ├── flags: ∅ @@ -178,10 +194,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (34,0)-(34,3) = "end" ├── @ DefNode (location: (36,0)-(37,3)) + │ ├── flags: newline │ ├── name: :+ │ ├── name_loc: (36,9)-(36,10) = "+" │ ├── receiver: │ │ @ SelfNode (location: (36,4)-(36,8)) + │ │ └── flags: ∅ │ ├── parameters: ∅ │ ├── body: ∅ │ ├── locals: [] @@ -192,6 +210,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (37,0)-(37,3) = "end" ├── @ DefNode (location: (39,0)-(40,3)) + │ ├── flags: newline │ ├── name: :+ │ ├── name_loc: (39,4)-(39,5) = "+" │ ├── receiver: ∅ @@ -205,6 +224,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (40,0)-(40,3) = "end" ├── @ DefNode (location: (42,0)-(43,3)) + │ ├── flags: newline │ ├── name: :+@ │ ├── name_loc: (42,4)-(42,6) = "+@" │ ├── receiver: ∅ @@ -218,6 +238,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (43,0)-(43,3) = "end" ├── @ DefNode (location: (45,0)-(46,3)) + │ ├── flags: newline │ ├── name: :- │ ├── name_loc: (45,4)-(45,5) = "-" │ ├── receiver: ∅ @@ -231,6 +252,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (46,0)-(46,3) = "end" ├── @ DefNode (location: (48,0)-(48,11)) + │ ├── flags: newline │ ├── name: :- │ ├── name_loc: (48,6)-(48,7) = "-" │ ├── receiver: @@ -254,6 +276,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (48,8)-(48,11) = "end" ├── @ DefNode (location: (50,0)-(51,3)) + │ ├── flags: newline │ ├── name: :-@ │ ├── name_loc: (50,4)-(50,6) = "-@" │ ├── receiver: ∅ @@ -267,6 +290,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (51,0)-(51,3) = "end" ├── @ DefNode (location: (53,0)-(54,3)) + │ ├── flags: newline │ ├── name: :/ │ ├── name_loc: (53,4)-(53,5) = "/" │ ├── receiver: ∅ @@ -280,6 +304,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (54,0)-(54,3) = "end" ├── @ DefNode (location: (56,0)-(57,3)) + │ ├── flags: newline │ ├── name: :< │ ├── name_loc: (56,4)-(56,5) = "<" │ ├── receiver: ∅ @@ -293,6 +318,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (57,0)-(57,3) = "end" ├── @ DefNode (location: (59,0)-(60,3)) + │ ├── flags: newline │ ├── name: :<< │ ├── name_loc: (59,4)-(59,6) = "<<" │ ├── receiver: ∅ @@ -306,6 +332,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (60,0)-(60,3) = "end" ├── @ DefNode (location: (62,0)-(63,3)) + │ ├── flags: newline │ ├── name: :<= │ ├── name_loc: (62,4)-(62,6) = "<=" │ ├── receiver: ∅ @@ -319,6 +346,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (63,0)-(63,3) = "end" ├── @ DefNode (location: (65,0)-(66,3)) + │ ├── flags: newline │ ├── name: :<=> │ ├── name_loc: (65,4)-(65,7) = "<=>" │ ├── receiver: ∅ @@ -332,6 +360,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (66,0)-(66,3) = "end" ├── @ DefNode (location: (68,0)-(69,3)) + │ ├── flags: newline │ ├── name: :== │ ├── name_loc: (68,4)-(68,6) = "==" │ ├── receiver: ∅ @@ -345,6 +374,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (69,0)-(69,3) = "end" ├── @ DefNode (location: (71,0)-(72,3)) + │ ├── flags: newline │ ├── name: :=== │ ├── name_loc: (71,4)-(71,7) = "===" │ ├── receiver: ∅ @@ -358,6 +388,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (72,0)-(72,3) = "end" ├── @ DefNode (location: (74,0)-(75,3)) + │ ├── flags: newline │ ├── name: :=~ │ ├── name_loc: (74,4)-(74,6) = "=~" │ ├── receiver: ∅ @@ -371,6 +402,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (75,0)-(75,3) = "end" ├── @ DefNode (location: (77,0)-(78,3)) + │ ├── flags: newline │ ├── name: :> │ ├── name_loc: (77,4)-(77,5) = ">" │ ├── receiver: ∅ @@ -384,6 +416,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (78,0)-(78,3) = "end" ├── @ DefNode (location: (80,0)-(81,3)) + │ ├── flags: newline │ ├── name: :>= │ ├── name_loc: (80,4)-(80,6) = ">=" │ ├── receiver: ∅ @@ -397,6 +430,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (81,0)-(81,3) = "end" ├── @ DefNode (location: (83,0)-(84,3)) + │ ├── flags: newline │ ├── name: :>> │ ├── name_loc: (83,4)-(83,6) = ">>" │ ├── receiver: ∅ @@ -410,6 +444,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (84,0)-(84,3) = "end" ├── @ DefNode (location: (86,0)-(87,3)) + │ ├── flags: newline │ ├── name: :[] │ ├── name_loc: (86,4)-(86,6) = "[]" │ ├── receiver: ∅ @@ -423,6 +458,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (87,0)-(87,3) = "end" ├── @ DefNode (location: (89,0)-(90,3)) + │ ├── flags: newline │ ├── name: :[]= │ ├── name_loc: (89,4)-(89,7) = "[]=" │ ├── receiver: ∅ @@ -436,6 +472,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (90,0)-(90,3) = "end" ├── @ DefNode (location: (92,0)-(93,3)) + │ ├── flags: newline │ ├── name: :^ │ ├── name_loc: (92,4)-(92,5) = "^" │ ├── receiver: ∅ @@ -449,6 +486,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (93,0)-(93,3) = "end" ├── @ DefNode (location: (95,0)-(96,3)) + │ ├── flags: newline │ ├── name: :` │ ├── name_loc: (95,4)-(95,5) = "`" │ ├── receiver: ∅ @@ -462,10 +500,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (96,0)-(96,3) = "end" ├── @ DefNode (location: (98,0)-(99,3)) + │ ├── flags: newline │ ├── name: :` │ ├── name_loc: (98,9)-(98,10) = "`" │ ├── receiver: │ │ @ SelfNode (location: (98,4)-(98,8)) + │ │ └── flags: ∅ │ ├── parameters: ∅ │ ├── body: ∅ │ ├── locals: [] @@ -476,6 +516,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (99,0)-(99,3) = "end" ├── @ DefNode (location: (101,0)-(102,3)) + │ ├── flags: newline │ ├── name: :| │ ├── name_loc: (101,4)-(101,5) = "|" │ ├── receiver: ∅ @@ -489,6 +530,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (102,0)-(102,3) = "end" └── @ DefNode (location: (104,0)-(105,3)) + ├── flags: newline ├── name: :~ ├── name_loc: (104,4)-(104,5) = "~" ├── receiver: ∅ diff --git a/test/prism/snapshots/not.txt b/test/prism/snapshots/not.txt index fda61bb4b58..e164b18813a 100644 --- a/test/prism/snapshots/not.txt +++ b/test/prism/snapshots/not.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(37,16)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(37,16)) + ├── flags: ∅ └── body: (length: 10) ├── @ AndNode (location: (1,0)-(1,19)) + │ ├── flags: newline │ ├── left: │ │ @ CallNode (location: (1,0)-(1,7)) │ │ ├── flags: ∅ @@ -48,9 +51,10 @@ │ │ └── block: ∅ │ └── operator_loc: (1,8)-(1,11) = "and" ├── @ CallNode (location: (3,0)-(3,16)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ AndNode (location: (3,4)-(3,15)) + │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ CallNode (location: (3,4)-(3,7)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -82,7 +86,7 @@ │ ├── closing_loc: (3,15)-(3,16) = ")" │ └── block: ∅ ├── @ CallNode (location: (5,0)-(5,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (5,4)-(5,7)) │ │ ├── flags: variable_call, ignore_visibility @@ -102,6 +106,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ AndNode (location: (7,0)-(8,5)) + │ ├── flags: newline │ ├── left: │ │ @ CallNode (location: (7,0)-(7,7)) │ │ ├── flags: ∅ @@ -146,6 +151,7 @@ │ │ └── block: ∅ │ └── operator_loc: (7,8)-(7,11) = "and" ├── @ AndNode (location: (11,0)-(13,5)) + │ ├── flags: newline │ ├── left: │ │ @ CallNode (location: (11,0)-(11,7)) │ │ ├── flags: ∅ @@ -190,6 +196,7 @@ │ │ └── block: ∅ │ └── operator_loc: (11,8)-(11,11) = "and" ├── @ AndNode (location: (16,0)-(20,5)) + │ ├── flags: newline │ ├── left: │ │ @ CallNode (location: (16,0)-(16,7)) │ │ ├── flags: ∅ @@ -234,7 +241,7 @@ │ │ └── block: ∅ │ └── operator_loc: (16,8)-(16,11) = "and" ├── @ CallNode (location: (22,0)-(25,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (22,4)-(22,7)) │ │ ├── flags: variable_call, ignore_visibility @@ -254,7 +261,7 @@ │ ├── closing_loc: (25,0)-(25,1) = ")" │ └── block: ∅ ├── @ CallNode (location: (27,0)-(33,3)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (30,0)-(30,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -274,7 +281,7 @@ │ ├── closing_loc: (33,2)-(33,3) = ")" │ └── block: ∅ ├── @ CallNode (location: (35,0)-(35,14)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ FlipFlopNode (location: (35,4)-(35,14)) │ │ ├── flags: ∅ @@ -309,14 +316,16 @@ │ ├── closing_loc: ∅ │ └── block: ∅ └── @ CallNode (location: (37,0)-(37,16)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ ParenthesesNode (location: (37,4)-(37,16)) + │ ├── flags: ∅ │ ├── body: │ │ @ StatementsNode (location: (37,5)-(37,15)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ FlipFlopNode (location: (37,5)-(37,15)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── left: │ │ │ @ CallNode (location: (37,5)-(37,8)) │ │ │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/numbers.txt b/test/prism/snapshots/numbers.txt index 740f3f5a2a1..4512427ef32 100644 --- a/test/prism/snapshots/numbers.txt +++ b/test/prism/snapshots/numbers.txt @@ -1,142 +1,147 @@ @ ProgramNode (location: (1,0)-(67,5)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(67,5)) + ├── flags: ∅ └── body: (length: 34) ├── @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 0 ├── @ IntegerNode (location: (3,0)-(3,1)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 1 ├── @ FloatNode (location: (5,0)-(5,3)) + │ ├── flags: newline, static_literal │ └── value: 1.0 ├── @ IntegerNode (location: (7,0)-(7,1)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 2 ├── @ IntegerNode (location: (9,0)-(9,3)) - │ ├── flags: binary + │ ├── flags: newline, static_literal, binary │ └── value: 0 ├── @ IntegerNode (location: (11,0)-(11,3)) - │ ├── flags: binary + │ ├── flags: newline, static_literal, binary │ └── value: 1 ├── @ IntegerNode (location: (13,0)-(13,4)) - │ ├── flags: binary + │ ├── flags: newline, static_literal, binary │ └── value: 2 ├── @ IntegerNode (location: (15,0)-(15,3)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 0 ├── @ IntegerNode (location: (17,0)-(17,3)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 1 ├── @ IntegerNode (location: (19,0)-(19,3)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 2 ├── @ IntegerNode (location: (21,0)-(21,2)) - │ ├── flags: octal + │ ├── flags: newline, static_literal, octal │ └── value: 0 ├── @ IntegerNode (location: (23,0)-(23,2)) - │ ├── flags: octal + │ ├── flags: newline, static_literal, octal │ └── value: 1 ├── @ IntegerNode (location: (25,0)-(25,2)) - │ ├── flags: octal + │ ├── flags: newline, static_literal, octal │ └── value: 2 ├── @ IntegerNode (location: (27,0)-(27,3)) - │ ├── flags: octal + │ ├── flags: newline, static_literal, octal │ └── value: 0 ├── @ IntegerNode (location: (29,0)-(29,3)) - │ ├── flags: octal + │ ├── flags: newline, static_literal, octal │ └── value: 1 ├── @ IntegerNode (location: (31,0)-(31,3)) - │ ├── flags: octal + │ ├── flags: newline, static_literal, octal │ └── value: 2 ├── @ IntegerNode (location: (33,0)-(33,3)) - │ ├── flags: hexadecimal + │ ├── flags: newline, static_literal, hexadecimal │ └── value: 0 ├── @ IntegerNode (location: (35,0)-(35,3)) - │ ├── flags: hexadecimal + │ ├── flags: newline, static_literal, hexadecimal │ └── value: 1 ├── @ IntegerNode (location: (37,0)-(37,3)) - │ ├── flags: hexadecimal + │ ├── flags: newline, static_literal, hexadecimal │ └── value: 2 ├── @ ImaginaryNode (location: (39,0)-(39,2)) + │ ├── flags: newline, static_literal │ └── numeric: │ @ IntegerNode (location: (39,0)-(39,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ RationalNode (location: (41,0)-(41,2)) - │ └── numeric: - │ @ IntegerNode (location: (41,0)-(41,1)) - │ ├── flags: decimal - │ └── value: 1 + │ ├── flags: newline, static_literal, decimal + │ ├── numerator: 1 + │ └── denominator: 1 ├── @ IntegerNode (location: (43,0)-(43,2)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: -1 ├── @ ImaginaryNode (location: (45,0)-(45,3)) + │ ├── flags: newline, static_literal │ └── numeric: │ @ RationalNode (location: (45,0)-(45,2)) - │ └── numeric: - │ @ IntegerNode (location: (45,0)-(45,1)) - │ ├── flags: decimal - │ └── value: 1 + │ ├── flags: static_literal, decimal + │ ├── numerator: 1 + │ └── denominator: 1 ├── @ RationalNode (location: (47,0)-(47,4)) - │ └── numeric: - │ @ FloatNode (location: (47,0)-(47,3)) - │ └── value: 1.2 + │ ├── flags: newline, static_literal, decimal + │ ├── numerator: 6 + │ └── denominator: 5 ├── @ ImaginaryNode (location: (49,0)-(49,5)) + │ ├── flags: newline, static_literal │ └── numeric: │ @ RationalNode (location: (49,0)-(49,4)) - │ └── numeric: - │ @ FloatNode (location: (49,0)-(49,3)) - │ └── value: 1.2 + │ ├── flags: static_literal, decimal + │ ├── numerator: 6 + │ └── denominator: 5 ├── @ ImaginaryNode (location: (51,0)-(51,4)) + │ ├── flags: newline, static_literal │ └── numeric: │ @ RationalNode (location: (51,0)-(51,3)) - │ └── numeric: - │ @ IntegerNode (location: (51,0)-(51,2)) - │ ├── flags: decimal - │ └── value: -1 + │ ├── flags: static_literal, decimal + │ ├── numerator: -1 + │ └── denominator: 1 ├── @ RationalNode (location: (53,0)-(53,5)) - │ └── numeric: - │ @ FloatNode (location: (53,0)-(53,4)) - │ └── value: -1.2 + │ ├── flags: newline, static_literal, decimal + │ ├── numerator: -6 + │ └── denominator: 5 ├── @ ImaginaryNode (location: (55,0)-(55,6)) + │ ├── flags: newline, static_literal │ └── numeric: │ @ RationalNode (location: (55,0)-(55,5)) - │ └── numeric: - │ @ FloatNode (location: (55,0)-(55,4)) - │ └── value: -1.2 + │ ├── flags: static_literal, decimal + │ ├── numerator: -6 + │ └── denominator: 5 ├── @ RationalNode (location: (57,0)-(57,4)) - │ └── numeric: - │ @ IntegerNode (location: (57,0)-(57,3)) - │ ├── flags: octal - │ └── value: 1 + │ ├── flags: newline, static_literal, octal + │ ├── numerator: 1 + │ └── denominator: 1 ├── @ ImaginaryNode (location: (59,0)-(59,4)) + │ ├── flags: newline, static_literal │ └── numeric: │ @ IntegerNode (location: (59,0)-(59,3)) - │ ├── flags: octal + │ ├── flags: static_literal, octal │ └── value: 1 ├── @ ImaginaryNode (location: (61,0)-(61,5)) + │ ├── flags: newline, static_literal │ └── numeric: │ @ RationalNode (location: (61,0)-(61,4)) - │ └── numeric: - │ @ IntegerNode (location: (61,0)-(61,3)) - │ ├── flags: octal - │ └── value: 1 + │ ├── flags: static_literal, octal + │ ├── numerator: 1 + │ └── denominator: 1 ├── @ RationalNode (location: (63,0)-(63,4)) - │ └── numeric: - │ @ IntegerNode (location: (63,0)-(63,3)) - │ ├── flags: decimal - │ └── value: 1 + │ ├── flags: newline, static_literal, decimal + │ ├── numerator: 1 + │ └── denominator: 1 ├── @ ImaginaryNode (location: (65,0)-(65,4)) + │ ├── flags: newline, static_literal │ └── numeric: │ @ IntegerNode (location: (65,0)-(65,3)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 └── @ ImaginaryNode (location: (67,0)-(67,5)) + ├── flags: newline, static_literal └── numeric: @ RationalNode (location: (67,0)-(67,4)) - └── numeric: - @ IntegerNode (location: (67,0)-(67,3)) - ├── flags: binary - └── value: 1 + ├── flags: static_literal, binary + ├── numerator: 1 + └── denominator: 1 diff --git a/test/prism/snapshots/patterns.txt b/test/prism/snapshots/patterns.txt index 16298e79849..3efabd279f3 100644 --- a/test/prism/snapshots/patterns.txt +++ b/test/prism/snapshots/patterns.txt @@ -1,9 +1,12 @@ -@ ProgramNode (location: (1,0)-(217,5)) -├── locals: [:bar, :baz, :qux, :b, :a, :foo, :x] +@ ProgramNode (location: (1,0)-(214,31)) +├── flags: ∅ +├── locals: [:bar, :baz, :qux, :b, :a, :foo, :x, :_a] └── statements: - @ StatementsNode (location: (1,0)-(217,5)) - └── body: (length: 180) + @ StatementsNode (location: (1,0)-(214,31)) + ├── flags: ∅ + └── body: (length: 182) ├── @ MatchRequiredNode (location: (1,0)-(1,10)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (1,0)-(1,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -17,10 +20,12 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ LocalVariableTargetNode (location: (1,7)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── name: :bar │ │ └── depth: 0 │ └── operator_loc: (1,4)-(1,6) = "=>" ├── @ MatchRequiredNode (location: (2,0)-(2,8)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (2,0)-(2,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -34,10 +39,11 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ IntegerNode (location: (2,7)-(2,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (2,4)-(2,6) = "=>" ├── @ MatchRequiredNode (location: (3,0)-(3,10)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (3,0)-(3,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -51,9 +57,11 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ FloatNode (location: (3,7)-(3,10)) + │ │ ├── flags: static_literal │ │ └── value: 1.0 │ └── operator_loc: (3,4)-(3,6) = "=>" ├── @ MatchRequiredNode (location: (4,0)-(4,9)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (4,0)-(4,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -67,12 +75,14 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ImaginaryNode (location: (4,7)-(4,9)) + │ │ ├── flags: static_literal │ │ └── numeric: │ │ @ IntegerNode (location: (4,7)-(4,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (4,4)-(4,6) = "=>" ├── @ MatchRequiredNode (location: (5,0)-(5,9)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (5,0)-(5,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -86,12 +96,12 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ RationalNode (location: (5,7)-(5,9)) - │ │ └── numeric: - │ │ @ IntegerNode (location: (5,7)-(5,8)) - │ │ ├── flags: decimal - │ │ └── value: 1 + │ │ ├── flags: static_literal, decimal + │ │ ├── numerator: 1 + │ │ └── denominator: 1 │ └── operator_loc: (5,4)-(5,6) = "=>" ├── @ MatchRequiredNode (location: (6,0)-(6,11)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (6,0)-(6,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -105,13 +115,14 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ SymbolNode (location: (6,7)-(6,11)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (6,7)-(6,8) = ":" │ │ ├── value_loc: (6,8)-(6,11) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ └── operator_loc: (6,4)-(6,6) = "=>" ├── @ MatchRequiredNode (location: (7,0)-(7,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (7,0)-(7,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -125,13 +136,14 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ SymbolNode (location: (7,7)-(7,14)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (7,7)-(7,10) = "%s[" │ │ ├── value_loc: (7,10)-(7,13) = "foo" │ │ ├── closing_loc: (7,13)-(7,14) = "]" │ │ └── unescaped: "foo" │ └── operator_loc: (7,4)-(7,6) = "=>" ├── @ MatchRequiredNode (location: (8,0)-(8,13)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (8,0)-(8,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -145,13 +157,14 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ SymbolNode (location: (8,7)-(8,13)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (8,7)-(8,9) = ":\"" │ │ ├── value_loc: (8,9)-(8,12) = "foo" │ │ ├── closing_loc: (8,12)-(8,13) = "\"" │ │ └── unescaped: "foo" │ └── operator_loc: (8,4)-(8,6) = "=>" ├── @ MatchRequiredNode (location: (9,0)-(9,12)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (9,0)-(9,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -165,13 +178,14 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ RegularExpressionNode (location: (9,7)-(9,12)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (9,7)-(9,8) = "/" │ │ ├── content_loc: (9,8)-(9,11) = "foo" │ │ ├── closing_loc: (9,11)-(9,12) = "/" │ │ └── unescaped: "foo" │ └── operator_loc: (9,4)-(9,6) = "=>" ├── @ MatchRequiredNode (location: (10,0)-(10,12)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (10,0)-(10,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -192,6 +206,7 @@ │ │ └── unescaped: "foo" │ └── operator_loc: (10,4)-(10,6) = "=>" ├── @ MatchRequiredNode (location: (11,0)-(11,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (11,0)-(11,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -212,6 +227,7 @@ │ │ └── unescaped: "foo" │ └── operator_loc: (11,4)-(11,6) = "=>" ├── @ MatchRequiredNode (location: (12,0)-(12,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (12,0)-(12,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -225,10 +241,10 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayNode (location: (12,7)-(12,14)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── elements: (length: 1) │ │ │ └── @ SymbolNode (location: (12,10)-(12,13)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (12,10)-(12,13) = "foo" │ │ │ ├── closing_loc: ∅ @@ -237,6 +253,7 @@ │ │ └── closing_loc: (12,13)-(12,14) = "]" │ └── operator_loc: (12,4)-(12,6) = "=>" ├── @ MatchRequiredNode (location: (13,0)-(13,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (13,0)-(13,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -250,10 +267,10 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayNode (location: (13,7)-(13,14)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── elements: (length: 1) │ │ │ └── @ SymbolNode (location: (13,10)-(13,13)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (13,10)-(13,13) = "foo" │ │ │ ├── closing_loc: ∅ @@ -262,6 +279,7 @@ │ │ └── closing_loc: (13,13)-(13,14) = "]" │ └── operator_loc: (13,4)-(13,6) = "=>" ├── @ MatchRequiredNode (location: (14,0)-(14,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (14,0)-(14,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -287,6 +305,7 @@ │ │ └── closing_loc: (14,13)-(14,14) = "]" │ └── operator_loc: (14,4)-(14,6) = "=>" ├── @ MatchRequiredNode (location: (15,0)-(15,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (15,0)-(15,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -312,6 +331,7 @@ │ │ └── closing_loc: (15,13)-(15,14) = "]" │ └── operator_loc: (15,4)-(15,6) = "=>" ├── @ MatchRequiredNode (location: (16,0)-(16,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (16,0)-(16,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -332,6 +352,7 @@ │ │ └── unescaped: "foo" │ └── operator_loc: (16,4)-(16,6) = "=>" ├── @ MatchRequiredNode (location: (17,0)-(17,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (17,0)-(17,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -352,6 +373,7 @@ │ │ └── unescaped: "foo" │ └── operator_loc: (17,4)-(17,6) = "=>" ├── @ MatchRequiredNode (location: (18,0)-(18,12)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (18,0)-(18,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -372,6 +394,7 @@ │ │ └── unescaped: "foo" │ └── operator_loc: (18,4)-(18,6) = "=>" ├── @ MatchRequiredNode (location: (19,0)-(19,10)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (19,0)-(19,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -385,8 +408,10 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ NilNode (location: (19,7)-(19,10)) + │ │ └── flags: static_literal │ └── operator_loc: (19,4)-(19,6) = "=>" ├── @ MatchRequiredNode (location: (20,0)-(20,11)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (20,0)-(20,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -400,8 +425,10 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ SelfNode (location: (20,7)-(20,11)) + │ │ └── flags: ∅ │ └── operator_loc: (20,4)-(20,6) = "=>" ├── @ MatchRequiredNode (location: (21,0)-(21,11)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (21,0)-(21,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -415,8 +442,10 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ TrueNode (location: (21,7)-(21,11)) + │ │ └── flags: static_literal │ └── operator_loc: (21,4)-(21,6) = "=>" ├── @ MatchRequiredNode (location: (22,0)-(22,12)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (22,0)-(22,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -430,8 +459,10 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ FalseNode (location: (22,7)-(22,12)) + │ │ └── flags: static_literal │ └── operator_loc: (22,4)-(22,6) = "=>" ├── @ MatchRequiredNode (location: (23,0)-(23,15)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (23,0)-(23,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -449,6 +480,7 @@ │ │ └── filepath: "patterns.txt" │ └── operator_loc: (23,4)-(23,6) = "=>" ├── @ MatchRequiredNode (location: (24,0)-(24,15)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (24,0)-(24,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -462,8 +494,10 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ SourceLineNode (location: (24,7)-(24,15)) + │ │ └── flags: static_literal │ └── operator_loc: (24,4)-(24,6) = "=>" ├── @ MatchRequiredNode (location: (25,0)-(25,19)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (25,0)-(25,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -477,8 +511,10 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ SourceEncodingNode (location: (25,7)-(25,19)) + │ │ └── flags: static_literal │ └── operator_loc: (25,4)-(25,6) = "=>" ├── @ MatchRequiredNode (location: (26,0)-(26,17)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (26,0)-(26,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -492,6 +528,7 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ LambdaNode (location: (26,7)-(26,17)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── operator_loc: (26,7)-(26,9) = "->" │ │ ├── opening_loc: (26,10)-(26,11) = "{" @@ -499,12 +536,15 @@ │ │ ├── parameters: ∅ │ │ └── body: │ │ @ StatementsNode (location: (26,12)-(26,15)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (26,12)-(26,15)) + │ │ ├── flags: newline │ │ ├── name: :bar │ │ └── depth: 1 │ └── operator_loc: (26,4)-(26,6) = "=>" ├── @ MatchRequiredNode (location: (28,0)-(28,13)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (28,0)-(28,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -518,18 +558,19 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ RangeNode (location: (28,7)-(28,13)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (28,7)-(28,8)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ IntegerNode (location: (28,12)-(28,13)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── operator_loc: (28,9)-(28,11) = ".." │ └── operator_loc: (28,4)-(28,6) = "=>" ├── @ MatchRequiredNode (location: (29,0)-(29,17)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (29,0)-(29,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -546,13 +587,16 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ FloatNode (location: (29,7)-(29,10)) + │ │ │ ├── flags: static_literal │ │ │ └── value: 1.0 │ │ ├── right: │ │ │ @ FloatNode (location: (29,14)-(29,17)) + │ │ │ ├── flags: static_literal │ │ │ └── value: 1.0 │ │ └── operator_loc: (29,11)-(29,13) = ".." │ └── operator_loc: (29,4)-(29,6) = "=>" ├── @ MatchRequiredNode (location: (30,0)-(30,15)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (30,0)-(30,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -569,19 +613,22 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ ImaginaryNode (location: (30,7)-(30,9)) + │ │ │ ├── flags: static_literal │ │ │ └── numeric: │ │ │ @ IntegerNode (location: (30,7)-(30,8)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ ImaginaryNode (location: (30,13)-(30,15)) + │ │ │ ├── flags: static_literal │ │ │ └── numeric: │ │ │ @ IntegerNode (location: (30,13)-(30,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── operator_loc: (30,10)-(30,12) = ".." │ └── operator_loc: (30,4)-(30,6) = "=>" ├── @ MatchRequiredNode (location: (31,0)-(31,15)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (31,0)-(31,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -598,19 +645,18 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ RationalNode (location: (31,7)-(31,9)) - │ │ │ └── numeric: - │ │ │ @ IntegerNode (location: (31,7)-(31,8)) - │ │ │ ├── flags: decimal - │ │ │ └── value: 1 + │ │ │ ├── flags: static_literal, decimal + │ │ │ ├── numerator: 1 + │ │ │ └── denominator: 1 │ │ ├── right: │ │ │ @ RationalNode (location: (31,13)-(31,15)) - │ │ │ └── numeric: - │ │ │ @ IntegerNode (location: (31,13)-(31,14)) - │ │ │ ├── flags: decimal - │ │ │ └── value: 1 + │ │ │ ├── flags: static_literal, decimal + │ │ │ ├── numerator: 1 + │ │ │ └── denominator: 1 │ │ └── operator_loc: (31,10)-(31,12) = ".." │ └── operator_loc: (31,4)-(31,6) = "=>" ├── @ MatchRequiredNode (location: (32,0)-(32,19)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (32,0)-(32,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -627,14 +673,14 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ SymbolNode (location: (32,7)-(32,11)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (32,7)-(32,8) = ":" │ │ │ ├── value_loc: (32,8)-(32,11) = "foo" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "foo" │ │ ├── right: │ │ │ @ SymbolNode (location: (32,15)-(32,19)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (32,15)-(32,16) = ":" │ │ │ ├── value_loc: (32,16)-(32,19) = "foo" │ │ │ ├── closing_loc: ∅ @@ -642,6 +688,7 @@ │ │ └── operator_loc: (32,12)-(32,14) = ".." │ └── operator_loc: (32,4)-(32,6) = "=>" ├── @ MatchRequiredNode (location: (33,0)-(33,25)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (33,0)-(33,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -658,14 +705,14 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ SymbolNode (location: (33,7)-(33,14)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (33,7)-(33,10) = "%s[" │ │ │ ├── value_loc: (33,10)-(33,13) = "foo" │ │ │ ├── closing_loc: (33,13)-(33,14) = "]" │ │ │ └── unescaped: "foo" │ │ ├── right: │ │ │ @ SymbolNode (location: (33,18)-(33,25)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (33,18)-(33,21) = "%s[" │ │ │ ├── value_loc: (33,21)-(33,24) = "foo" │ │ │ ├── closing_loc: (33,24)-(33,25) = "]" @@ -673,6 +720,7 @@ │ │ └── operator_loc: (33,15)-(33,17) = ".." │ └── operator_loc: (33,4)-(33,6) = "=>" ├── @ MatchRequiredNode (location: (34,0)-(34,23)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (34,0)-(34,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -689,14 +737,14 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ SymbolNode (location: (34,7)-(34,13)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (34,7)-(34,9) = ":\"" │ │ │ ├── value_loc: (34,9)-(34,12) = "foo" │ │ │ ├── closing_loc: (34,12)-(34,13) = "\"" │ │ │ └── unescaped: "foo" │ │ ├── right: │ │ │ @ SymbolNode (location: (34,17)-(34,23)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (34,17)-(34,19) = ":\"" │ │ │ ├── value_loc: (34,19)-(34,22) = "foo" │ │ │ ├── closing_loc: (34,22)-(34,23) = "\"" @@ -704,6 +752,7 @@ │ │ └── operator_loc: (34,14)-(34,16) = ".." │ └── operator_loc: (34,4)-(34,6) = "=>" ├── @ MatchRequiredNode (location: (35,0)-(35,21)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (35,0)-(35,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -720,14 +769,14 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ RegularExpressionNode (location: (35,7)-(35,12)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (35,7)-(35,8) = "/" │ │ │ ├── content_loc: (35,8)-(35,11) = "foo" │ │ │ ├── closing_loc: (35,11)-(35,12) = "/" │ │ │ └── unescaped: "foo" │ │ ├── right: │ │ │ @ RegularExpressionNode (location: (35,16)-(35,21)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (35,16)-(35,17) = "/" │ │ │ ├── content_loc: (35,17)-(35,20) = "foo" │ │ │ ├── closing_loc: (35,20)-(35,21) = "/" @@ -735,6 +784,7 @@ │ │ └── operator_loc: (35,13)-(35,15) = ".." │ └── operator_loc: (35,4)-(35,6) = "=>" ├── @ MatchRequiredNode (location: (36,0)-(36,21)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (36,0)-(36,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -766,6 +816,7 @@ │ │ └── operator_loc: (36,13)-(36,15) = ".." │ └── operator_loc: (36,4)-(36,6) = "=>" ├── @ MatchRequiredNode (location: (37,0)-(37,25)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (37,0)-(37,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -797,6 +848,7 @@ │ │ └── operator_loc: (37,15)-(37,17) = ".." │ └── operator_loc: (37,4)-(37,6) = "=>" ├── @ MatchRequiredNode (location: (38,0)-(38,25)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (38,0)-(38,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -813,10 +865,10 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ ArrayNode (location: (38,7)-(38,14)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: static_literal │ │ │ ├── elements: (length: 1) │ │ │ │ └── @ SymbolNode (location: (38,10)-(38,13)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (38,10)-(38,13) = "foo" │ │ │ │ ├── closing_loc: ∅ @@ -825,10 +877,10 @@ │ │ │ └── closing_loc: (38,13)-(38,14) = "]" │ │ ├── right: │ │ │ @ ArrayNode (location: (38,18)-(38,25)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: static_literal │ │ │ ├── elements: (length: 1) │ │ │ │ └── @ SymbolNode (location: (38,21)-(38,24)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (38,21)-(38,24) = "foo" │ │ │ │ ├── closing_loc: ∅ @@ -838,6 +890,7 @@ │ │ └── operator_loc: (38,15)-(38,17) = ".." │ └── operator_loc: (38,4)-(38,6) = "=>" ├── @ MatchRequiredNode (location: (39,0)-(39,25)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (39,0)-(39,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -854,10 +907,10 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ ArrayNode (location: (39,7)-(39,14)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: static_literal │ │ │ ├── elements: (length: 1) │ │ │ │ └── @ SymbolNode (location: (39,10)-(39,13)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (39,10)-(39,13) = "foo" │ │ │ │ ├── closing_loc: ∅ @@ -866,10 +919,10 @@ │ │ │ └── closing_loc: (39,13)-(39,14) = "]" │ │ ├── right: │ │ │ @ ArrayNode (location: (39,18)-(39,25)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: static_literal │ │ │ ├── elements: (length: 1) │ │ │ │ └── @ SymbolNode (location: (39,21)-(39,24)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (39,21)-(39,24) = "foo" │ │ │ │ ├── closing_loc: ∅ @@ -879,6 +932,7 @@ │ │ └── operator_loc: (39,15)-(39,17) = ".." │ └── operator_loc: (39,4)-(39,6) = "=>" ├── @ MatchRequiredNode (location: (40,0)-(40,25)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (40,0)-(40,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -920,6 +974,7 @@ │ │ └── operator_loc: (40,15)-(40,17) = ".." │ └── operator_loc: (40,4)-(40,6) = "=>" ├── @ MatchRequiredNode (location: (41,0)-(41,25)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (41,0)-(41,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -961,6 +1016,7 @@ │ │ └── operator_loc: (41,15)-(41,17) = ".." │ └── operator_loc: (41,4)-(41,6) = "=>" ├── @ MatchRequiredNode (location: (42,0)-(42,25)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (42,0)-(42,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -992,6 +1048,7 @@ │ │ └── operator_loc: (42,15)-(42,17) = ".." │ └── operator_loc: (42,4)-(42,6) = "=>" ├── @ MatchRequiredNode (location: (43,0)-(43,25)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (43,0)-(43,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1023,6 +1080,7 @@ │ │ └── operator_loc: (43,15)-(43,17) = ".." │ └── operator_loc: (43,4)-(43,6) = "=>" ├── @ MatchRequiredNode (location: (44,0)-(44,21)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (44,0)-(44,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1054,6 +1112,7 @@ │ │ └── operator_loc: (44,13)-(44,15) = ".." │ └── operator_loc: (44,4)-(44,6) = "=>" ├── @ MatchRequiredNode (location: (45,0)-(45,17)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (45,0)-(45,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1067,14 +1126,17 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ RangeNode (location: (45,7)-(45,17)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ NilNode (location: (45,7)-(45,10)) + │ │ │ └── flags: static_literal │ │ ├── right: │ │ │ @ NilNode (location: (45,14)-(45,17)) + │ │ │ └── flags: static_literal │ │ └── operator_loc: (45,11)-(45,13) = ".." │ └── operator_loc: (45,4)-(45,6) = "=>" ├── @ MatchRequiredNode (location: (46,0)-(46,19)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (46,0)-(46,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1091,11 +1153,14 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ SelfNode (location: (46,7)-(46,11)) + │ │ │ └── flags: ∅ │ │ ├── right: │ │ │ @ SelfNode (location: (46,15)-(46,19)) + │ │ │ └── flags: ∅ │ │ └── operator_loc: (46,12)-(46,14) = ".." │ └── operator_loc: (46,4)-(46,6) = "=>" ├── @ MatchRequiredNode (location: (47,0)-(47,19)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (47,0)-(47,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1112,11 +1177,14 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ TrueNode (location: (47,7)-(47,11)) + │ │ │ └── flags: static_literal │ │ ├── right: │ │ │ @ TrueNode (location: (47,15)-(47,19)) + │ │ │ └── flags: static_literal │ │ └── operator_loc: (47,12)-(47,14) = ".." │ └── operator_loc: (47,4)-(47,6) = "=>" ├── @ MatchRequiredNode (location: (48,0)-(48,21)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (48,0)-(48,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1133,11 +1201,14 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ FalseNode (location: (48,7)-(48,12)) + │ │ │ └── flags: static_literal │ │ ├── right: │ │ │ @ FalseNode (location: (48,16)-(48,21)) + │ │ │ └── flags: static_literal │ │ └── operator_loc: (48,13)-(48,15) = ".." │ └── operator_loc: (48,4)-(48,6) = "=>" ├── @ MatchRequiredNode (location: (49,0)-(49,27)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (49,0)-(49,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1163,6 +1234,7 @@ │ │ └── operator_loc: (49,16)-(49,18) = ".." │ └── operator_loc: (49,4)-(49,6) = "=>" ├── @ MatchRequiredNode (location: (50,0)-(50,27)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (50,0)-(50,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1179,11 +1251,14 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ SourceLineNode (location: (50,7)-(50,15)) + │ │ │ └── flags: static_literal │ │ ├── right: │ │ │ @ SourceLineNode (location: (50,19)-(50,27)) + │ │ │ └── flags: static_literal │ │ └── operator_loc: (50,16)-(50,18) = ".." │ └── operator_loc: (50,4)-(50,6) = "=>" ├── @ MatchRequiredNode (location: (51,0)-(51,35)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (51,0)-(51,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1200,11 +1275,14 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ SourceEncodingNode (location: (51,7)-(51,19)) + │ │ │ └── flags: static_literal │ │ ├── right: │ │ │ @ SourceEncodingNode (location: (51,23)-(51,35)) + │ │ │ └── flags: static_literal │ │ └── operator_loc: (51,20)-(51,22) = ".." │ └── operator_loc: (51,4)-(51,6) = "=>" ├── @ MatchRequiredNode (location: (52,0)-(52,31)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (52,0)-(52,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1221,6 +1299,7 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ LambdaNode (location: (52,7)-(52,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── locals: [] │ │ │ ├── operator_loc: (52,7)-(52,9) = "->" │ │ │ ├── opening_loc: (52,10)-(52,11) = "{" @@ -1228,12 +1307,15 @@ │ │ │ ├── parameters: ∅ │ │ │ └── body: │ │ │ @ StatementsNode (location: (52,12)-(52,15)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ LocalVariableReadNode (location: (52,12)-(52,15)) + │ │ │ ├── flags: newline │ │ │ ├── name: :bar │ │ │ └── depth: 1 │ │ ├── right: │ │ │ @ LambdaNode (location: (52,21)-(52,31)) + │ │ │ ├── flags: ∅ │ │ │ ├── locals: [] │ │ │ ├── operator_loc: (52,21)-(52,23) = "->" │ │ │ ├── opening_loc: (52,24)-(52,25) = "{" @@ -1241,22 +1323,26 @@ │ │ │ ├── parameters: ∅ │ │ │ └── body: │ │ │ @ StatementsNode (location: (52,26)-(52,29)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ LocalVariableReadNode (location: (52,26)-(52,29)) + │ │ │ ├── flags: newline │ │ │ ├── name: :bar │ │ │ └── depth: 1 │ │ └── operator_loc: (52,18)-(52,20) = ".." │ └── operator_loc: (52,4)-(52,6) = "=>" ├── @ LocalVariableWriteNode (location: (54,0)-(54,7)) + │ ├── flags: newline │ ├── name: :bar │ ├── depth: 0 │ ├── name_loc: (54,0)-(54,3) = "bar" │ ├── value: │ │ @ IntegerNode (location: (54,6)-(54,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (54,4)-(54,5) = "=" ├── @ MatchRequiredNode (location: (54,9)-(54,20)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (54,9)-(54,12)) │ │ ├── flags: variable_call, ignore_visibility @@ -1270,13 +1356,16 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ PinnedVariableNode (location: (54,16)-(54,20)) + │ │ ├── flags: ∅ │ │ ├── variable: │ │ │ @ LocalVariableReadNode (location: (54,17)-(54,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ └── operator_loc: (54,16)-(54,17) = "^" │ └── operator_loc: (54,13)-(54,15) = "=>" ├── @ MatchRequiredNode (location: (55,0)-(55,12)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (55,0)-(55,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1290,12 +1379,15 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ PinnedVariableNode (location: (55,7)-(55,12)) + │ │ ├── flags: ∅ │ │ ├── variable: │ │ │ @ InstanceVariableReadNode (location: (55,8)-(55,12)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :@bar │ │ └── operator_loc: (55,7)-(55,8) = "^" │ └── operator_loc: (55,4)-(55,6) = "=>" ├── @ MatchRequiredNode (location: (56,0)-(56,13)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (56,0)-(56,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1309,12 +1401,15 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ PinnedVariableNode (location: (56,7)-(56,13)) + │ │ ├── flags: ∅ │ │ ├── variable: │ │ │ @ ClassVariableReadNode (location: (56,8)-(56,13)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :@@bar │ │ └── operator_loc: (56,7)-(56,8) = "^" │ └── operator_loc: (56,4)-(56,6) = "=>" ├── @ MatchRequiredNode (location: (57,0)-(57,12)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (57,0)-(57,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1328,12 +1423,15 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ PinnedVariableNode (location: (57,7)-(57,12)) + │ │ ├── flags: ∅ │ │ ├── variable: │ │ │ @ GlobalVariableReadNode (location: (57,8)-(57,12)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :$bar │ │ └── operator_loc: (57,7)-(57,8) = "^" │ └── operator_loc: (57,4)-(57,6) = "=>" ├── @ MatchRequiredNode (location: (59,0)-(59,11)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (59,0)-(59,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1347,15 +1445,17 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ PinnedExpressionNode (location: (59,7)-(59,11)) + │ │ ├── flags: ∅ │ │ ├── expression: │ │ │ @ IntegerNode (location: (59,9)-(59,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── operator_loc: (59,7)-(59,8) = "^" │ │ ├── lparen_loc: (59,8)-(59,9) = "(" │ │ └── rparen_loc: (59,10)-(59,11) = ")" │ └── operator_loc: (59,4)-(59,6) = "=>" ├── @ MatchRequiredNode (location: (60,0)-(60,13)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (60,0)-(60,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1369,13 +1469,16 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ PinnedExpressionNode (location: (60,7)-(60,13)) + │ │ ├── flags: ∅ │ │ ├── expression: │ │ │ @ NilNode (location: (60,9)-(60,12)) + │ │ │ └── flags: static_literal │ │ ├── operator_loc: (60,7)-(60,8) = "^" │ │ ├── lparen_loc: (60,8)-(60,9) = "(" │ │ └── rparen_loc: (60,12)-(60,13) = ")" │ └── operator_loc: (60,4)-(60,6) = "=>" ├── @ MatchRequiredNode (location: (61,0)-(61,23)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (61,0)-(61,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1389,6 +1492,7 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ PinnedExpressionNode (location: (61,7)-(61,23)) + │ │ ├── flags: ∅ │ │ ├── expression: │ │ │ @ CallNode (location: (61,9)-(61,22)) │ │ │ ├── flags: ∅ @@ -1420,6 +1524,7 @@ │ │ └── rparen_loc: (61,22)-(61,23) = ")" │ └── operator_loc: (61,4)-(61,6) = "=>" ├── @ MatchRequiredNode (location: (63,0)-(63,10)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (63,0)-(63,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1433,9 +1538,11 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ConstantReadNode (location: (63,7)-(63,10)) + │ │ ├── flags: ∅ │ │ └── name: :Foo │ └── operator_loc: (63,4)-(63,6) = "=>" ├── @ MatchRequiredNode (location: (64,0)-(64,20)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (64,0)-(64,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1449,10 +1556,13 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ConstantPathNode (location: (64,7)-(64,20)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantPathNode (location: (64,7)-(64,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── parent: │ │ │ │ @ ConstantReadNode (location: (64,7)-(64,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :Foo │ │ │ ├── name: :Bar │ │ │ ├── delimiter_loc: (64,10)-(64,12) = "::" @@ -1462,6 +1572,7 @@ │ │ └── name_loc: (64,17)-(64,20) = "Baz" │ └── operator_loc: (64,4)-(64,6) = "=>" ├── @ MatchRequiredNode (location: (65,0)-(65,12)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (65,0)-(65,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1475,12 +1586,14 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ConstantPathNode (location: (65,7)-(65,12)) + │ │ ├── flags: ∅ │ │ ├── parent: ∅ │ │ ├── name: :Foo │ │ ├── delimiter_loc: (65,7)-(65,9) = "::" │ │ └── name_loc: (65,9)-(65,12) = "Foo" │ └── operator_loc: (65,4)-(65,6) = "=>" ├── @ MatchRequiredNode (location: (66,0)-(66,22)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (66,0)-(66,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1494,10 +1607,13 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ConstantPathNode (location: (66,7)-(66,22)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantPathNode (location: (66,7)-(66,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── parent: │ │ │ │ @ ConstantPathNode (location: (66,7)-(66,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── parent: ∅ │ │ │ │ ├── name: :Foo │ │ │ │ ├── delimiter_loc: (66,7)-(66,9) = "::" @@ -1510,6 +1626,7 @@ │ │ └── name_loc: (66,19)-(66,22) = "Baz" │ └── operator_loc: (66,4)-(66,6) = "=>" ├── @ MatchRequiredNode (location: (68,0)-(68,12)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (68,0)-(68,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1523,8 +1640,10 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (68,7)-(68,12)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (68,7)-(68,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 0) │ │ ├── rest: ∅ @@ -1533,6 +1652,7 @@ │ │ └── closing_loc: (68,11)-(68,12) = ")" │ └── operator_loc: (68,4)-(68,6) = "=>" ├── @ MatchRequiredNode (location: (69,0)-(69,13)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (69,0)-(69,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1546,12 +1666,14 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (69,7)-(69,13)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (69,7)-(69,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 1) │ │ │ └── @ IntegerNode (location: (69,11)-(69,12)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) @@ -1559,6 +1681,7 @@ │ │ └── closing_loc: (69,12)-(69,13) = ")" │ └── operator_loc: (69,4)-(69,6) = "=>" ├── @ MatchRequiredNode (location: (70,0)-(70,19)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (70,0)-(70,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1572,18 +1695,20 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (70,7)-(70,19)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (70,7)-(70,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 3) │ │ │ ├── @ IntegerNode (location: (70,11)-(70,12)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── @ IntegerNode (location: (70,14)-(70,15)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ └── @ IntegerNode (location: (70,17)-(70,18)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) @@ -1591,6 +1716,7 @@ │ │ └── closing_loc: (70,18)-(70,19) = ")" │ └── operator_loc: (70,4)-(70,6) = "=>" ├── @ MatchRequiredNode (location: (71,0)-(71,15)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (71,0)-(71,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1604,11 +1730,14 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (71,7)-(71,15)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (71,7)-(71,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (71,11)-(71,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── rest: ∅ @@ -1617,6 +1746,7 @@ │ │ └── closing_loc: (71,14)-(71,15) = ")" │ └── operator_loc: (71,4)-(71,6) = "=>" ├── @ MatchRequiredNode (location: (72,0)-(72,21)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (72,0)-(72,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1630,25 +1760,31 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (72,7)-(72,21)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (72,7)-(72,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 0) │ │ ├── rest: │ │ │ @ SplatNode (location: (72,11)-(72,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (72,11)-(72,12) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (72,12)-(72,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── posts: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (72,17)-(72,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ └── depth: 0 │ │ ├── opening_loc: (72,10)-(72,11) = "(" │ │ └── closing_loc: (72,20)-(72,21) = ")" │ └── operator_loc: (72,4)-(72,6) = "=>" ├── @ MatchRequiredNode (location: (73,0)-(73,21)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (73,0)-(73,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1662,18 +1798,23 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (73,7)-(73,21)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (73,7)-(73,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (73,11)-(73,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── rest: │ │ │ @ SplatNode (location: (73,16)-(73,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (73,16)-(73,17) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (73,17)-(73,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ └── depth: 0 │ │ ├── posts: (length: 0) @@ -1681,6 +1822,7 @@ │ │ └── closing_loc: (73,20)-(73,21) = ")" │ └── operator_loc: (73,4)-(73,6) = "=>" ├── @ MatchRequiredNode (location: (74,0)-(74,27)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (74,0)-(74,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1694,31 +1836,39 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ FindPatternNode (location: (74,7)-(74,27)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (74,7)-(74,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Foo │ │ ├── left: │ │ │ @ SplatNode (location: (74,11)-(74,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (74,11)-(74,12) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (74,12)-(74,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── requireds: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (74,17)-(74,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ └── depth: 0 │ │ ├── right: │ │ │ @ SplatNode (location: (74,22)-(74,26)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (74,22)-(74,23) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (74,23)-(74,26)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :qux │ │ │ └── depth: 0 │ │ ├── opening_loc: (74,10)-(74,11) = "(" │ │ └── closing_loc: (74,26)-(74,27) = ")" │ └── operator_loc: (74,4)-(74,6) = "=>" ├── @ MatchRequiredNode (location: (76,0)-(76,12)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (76,0)-(76,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1732,8 +1882,10 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (76,7)-(76,12)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (76,7)-(76,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 0) │ │ ├── rest: ∅ @@ -1742,6 +1894,7 @@ │ │ └── closing_loc: (76,11)-(76,12) = "]" │ └── operator_loc: (76,4)-(76,6) = "=>" ├── @ MatchRequiredNode (location: (77,0)-(77,13)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (77,0)-(77,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1755,12 +1908,14 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (77,7)-(77,13)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (77,7)-(77,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 1) │ │ │ └── @ IntegerNode (location: (77,11)-(77,12)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) @@ -1768,6 +1923,7 @@ │ │ └── closing_loc: (77,12)-(77,13) = "]" │ └── operator_loc: (77,4)-(77,6) = "=>" ├── @ MatchRequiredNode (location: (78,0)-(78,19)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (78,0)-(78,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1781,18 +1937,20 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (78,7)-(78,19)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (78,7)-(78,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 3) │ │ │ ├── @ IntegerNode (location: (78,11)-(78,12)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── @ IntegerNode (location: (78,14)-(78,15)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ └── @ IntegerNode (location: (78,17)-(78,18)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) @@ -1800,6 +1958,7 @@ │ │ └── closing_loc: (78,18)-(78,19) = "]" │ └── operator_loc: (78,4)-(78,6) = "=>" ├── @ MatchRequiredNode (location: (79,0)-(79,17)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (79,0)-(79,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1813,13 +1972,17 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (79,7)-(79,17)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (79,7)-(79,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 1) │ │ │ └── @ ArrayPatternNode (location: (79,11)-(79,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: │ │ │ │ @ ConstantReadNode (location: (79,11)-(79,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :Foo │ │ │ ├── requireds: (length: 0) │ │ │ ├── rest: ∅ @@ -1832,6 +1995,7 @@ │ │ └── closing_loc: (79,16)-(79,17) = "]" │ └── operator_loc: (79,4)-(79,6) = "=>" ├── @ MatchRequiredNode (location: (80,0)-(80,15)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (80,0)-(80,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1845,11 +2009,14 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (80,7)-(80,15)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (80,7)-(80,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (80,11)-(80,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── rest: ∅ @@ -1858,6 +2025,7 @@ │ │ └── closing_loc: (80,14)-(80,15) = "]" │ └── operator_loc: (80,4)-(80,6) = "=>" ├── @ MatchRequiredNode (location: (81,0)-(81,21)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (81,0)-(81,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1871,25 +2039,31 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (81,7)-(81,21)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (81,7)-(81,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 0) │ │ ├── rest: │ │ │ @ SplatNode (location: (81,11)-(81,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (81,11)-(81,12) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (81,12)-(81,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── posts: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (81,17)-(81,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ └── depth: 0 │ │ ├── opening_loc: (81,10)-(81,11) = "[" │ │ └── closing_loc: (81,20)-(81,21) = "]" │ └── operator_loc: (81,4)-(81,6) = "=>" ├── @ MatchRequiredNode (location: (82,0)-(82,21)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (82,0)-(82,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1903,18 +2077,23 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (82,7)-(82,21)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (82,7)-(82,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (82,11)-(82,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── rest: │ │ │ @ SplatNode (location: (82,16)-(82,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (82,16)-(82,17) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (82,17)-(82,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ └── depth: 0 │ │ ├── posts: (length: 0) @@ -1922,6 +2101,7 @@ │ │ └── closing_loc: (82,20)-(82,21) = "]" │ └── operator_loc: (82,4)-(82,6) = "=>" ├── @ MatchRequiredNode (location: (83,0)-(83,27)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (83,0)-(83,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1935,31 +2115,39 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ FindPatternNode (location: (83,7)-(83,27)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (83,7)-(83,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Foo │ │ ├── left: │ │ │ @ SplatNode (location: (83,11)-(83,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (83,11)-(83,12) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (83,12)-(83,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── requireds: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (83,17)-(83,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ └── depth: 0 │ │ ├── right: │ │ │ @ SplatNode (location: (83,22)-(83,26)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (83,22)-(83,23) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (83,23)-(83,26)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :qux │ │ │ └── depth: 0 │ │ ├── opening_loc: (83,10)-(83,11) = "[" │ │ └── closing_loc: (83,26)-(83,27) = "]" │ └── operator_loc: (83,4)-(83,6) = "=>" ├── @ MatchRequiredNode (location: (85,0)-(85,11)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (85,0)-(85,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1973,13 +2161,16 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (85,7)-(85,11)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 0) │ │ ├── rest: │ │ │ @ SplatNode (location: (85,7)-(85,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (85,7)-(85,8) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (85,8)-(85,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── posts: (length: 0) @@ -1987,6 +2178,7 @@ │ │ └── closing_loc: ∅ │ └── operator_loc: (85,4)-(85,6) = "=>" ├── @ MatchRequiredNode (location: (86,0)-(86,21)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (86,0)-(86,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2000,26 +2192,32 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (86,7)-(86,21)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 0) │ │ ├── rest: │ │ │ @ SplatNode (location: (86,7)-(86,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (86,7)-(86,8) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (86,8)-(86,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── posts: (length: 2) │ │ │ ├── @ LocalVariableTargetNode (location: (86,13)-(86,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ └── @ LocalVariableTargetNode (location: (86,18)-(86,21)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :qux │ │ │ └── depth: 0 │ │ ├── opening_loc: ∅ │ │ └── closing_loc: ∅ │ └── operator_loc: (86,4)-(86,6) = "=>" ├── @ MatchRequiredNode (location: (87,0)-(87,21)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (87,0)-(87,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2033,26 +2231,32 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (87,7)-(87,21)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (87,7)-(87,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── rest: │ │ │ @ SplatNode (location: (87,12)-(87,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (87,12)-(87,13) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (87,13)-(87,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ └── depth: 0 │ │ ├── posts: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (87,18)-(87,21)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :qux │ │ │ └── depth: 0 │ │ ├── opening_loc: ∅ │ │ └── closing_loc: ∅ │ └── operator_loc: (87,4)-(87,6) = "=>" ├── @ MatchRequiredNode (location: (88,0)-(88,21)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (88,0)-(88,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2066,19 +2270,24 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (88,7)-(88,21)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ LocalVariableTargetNode (location: (88,7)-(88,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :bar │ │ │ │ └── depth: 0 │ │ │ └── @ LocalVariableTargetNode (location: (88,12)-(88,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ └── depth: 0 │ │ ├── rest: │ │ │ @ SplatNode (location: (88,17)-(88,21)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (88,17)-(88,18) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (88,18)-(88,21)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :qux │ │ │ └── depth: 0 │ │ ├── posts: (length: 0) @@ -2086,6 +2295,7 @@ │ │ └── closing_loc: ∅ │ └── operator_loc: (88,4)-(88,6) = "=>" ├── @ MatchRequiredNode (location: (89,0)-(89,22)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (89,0)-(89,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2099,303 +2309,410 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ FindPatternNode (location: (89,7)-(89,22)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── left: │ │ │ @ SplatNode (location: (89,7)-(89,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (89,7)-(89,8) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (89,8)-(89,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── requireds: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (89,13)-(89,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ └── depth: 0 │ │ ├── right: │ │ │ @ SplatNode (location: (89,18)-(89,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (89,18)-(89,19) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (89,19)-(89,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :qux │ │ │ └── depth: 0 │ │ ├── opening_loc: ∅ │ │ └── closing_loc: ∅ │ └── operator_loc: (89,4)-(89,6) = "=>" - ├── @ MatchRequiredNode (location: (91,0)-(91,11)) + ├── @ MatchRequiredNode (location: (90,0)-(90,11)) + │ ├── flags: newline │ ├── value: - │ │ @ CallNode (location: (91,0)-(91,3)) + │ │ @ CallNode (location: (90,0)-(90,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (91,0)-(91,3) = "foo" + │ │ ├── message_loc: (90,0)-(90,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ ArrayPatternNode (location: (91,7)-(91,11)) + │ │ @ ArrayPatternNode (location: (90,7)-(90,11)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 1) - │ │ │ └── @ LocalVariableTargetNode (location: (91,7)-(91,10)) + │ │ │ └── @ LocalVariableTargetNode (location: (90,7)-(90,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── rest: - │ │ │ @ ImplicitRestNode (location: (91,10)-(91,11)) + │ │ │ @ ImplicitRestNode (location: (90,10)-(90,11)) + │ │ │ └── flags: ∅ │ │ ├── posts: (length: 0) │ │ ├── opening_loc: ∅ │ │ └── closing_loc: ∅ - │ └── operator_loc: (91,4)-(91,6) = "=>" - ├── @ MatchRequiredNode (location: (95,0)-(95,9)) + │ └── operator_loc: (90,4)-(90,6) = "=>" + ├── @ MatchRequiredNode (location: (92,0)-(92,9)) + │ ├── flags: newline │ ├── value: - │ │ @ CallNode (location: (95,0)-(95,3)) + │ │ @ CallNode (location: (92,0)-(92,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (95,0)-(95,3) = "foo" + │ │ ├── message_loc: (92,0)-(92,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ ArrayPatternNode (location: (95,7)-(95,9)) + │ │ @ ArrayPatternNode (location: (92,7)-(92,9)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 0) │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) - │ │ ├── opening_loc: (95,7)-(95,8) = "[" - │ │ └── closing_loc: (95,8)-(95,9) = "]" - │ └── operator_loc: (95,4)-(95,6) = "=>" - ├── @ MatchRequiredNode (location: (96,0)-(96,17)) + │ │ ├── opening_loc: (92,7)-(92,8) = "[" + │ │ └── closing_loc: (92,8)-(92,9) = "]" + │ └── operator_loc: (92,4)-(92,6) = "=>" + ├── @ MatchRequiredNode (location: (93,0)-(93,17)) + │ ├── flags: newline │ ├── value: - │ │ @ CallNode (location: (96,0)-(96,3)) + │ │ @ CallNode (location: (93,0)-(93,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (96,0)-(96,3) = "foo" + │ │ ├── message_loc: (93,0)-(93,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ ArrayPatternNode (location: (96,7)-(96,17)) + │ │ @ ArrayPatternNode (location: (93,7)-(93,17)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 1) - │ │ │ └── @ ArrayPatternNode (location: (96,8)-(96,16)) + │ │ │ └── @ ArrayPatternNode (location: (93,8)-(93,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── requireds: (length: 1) - │ │ │ │ └── @ ArrayPatternNode (location: (96,9)-(96,15)) + │ │ │ │ └── @ ArrayPatternNode (location: (93,9)-(93,15)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── requireds: (length: 1) - │ │ │ │ │ └── @ ArrayPatternNode (location: (96,10)-(96,14)) + │ │ │ │ │ └── @ ArrayPatternNode (location: (93,10)-(93,14)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── constant: ∅ │ │ │ │ │ ├── requireds: (length: 1) - │ │ │ │ │ │ └── @ ArrayPatternNode (location: (96,11)-(96,13)) + │ │ │ │ │ │ └── @ ArrayPatternNode (location: (93,11)-(93,13)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── constant: ∅ │ │ │ │ │ │ ├── requireds: (length: 0) │ │ │ │ │ │ ├── rest: ∅ │ │ │ │ │ │ ├── posts: (length: 0) - │ │ │ │ │ │ ├── opening_loc: (96,11)-(96,12) = "[" - │ │ │ │ │ │ └── closing_loc: (96,12)-(96,13) = "]" + │ │ │ │ │ │ ├── opening_loc: (93,11)-(93,12) = "[" + │ │ │ │ │ │ └── closing_loc: (93,12)-(93,13) = "]" │ │ │ │ │ ├── rest: ∅ │ │ │ │ │ ├── posts: (length: 0) - │ │ │ │ │ ├── opening_loc: (96,10)-(96,11) = "[" - │ │ │ │ │ └── closing_loc: (96,13)-(96,14) = "]" + │ │ │ │ │ ├── opening_loc: (93,10)-(93,11) = "[" + │ │ │ │ │ └── closing_loc: (93,13)-(93,14) = "]" │ │ │ │ ├── rest: ∅ │ │ │ │ ├── posts: (length: 0) - │ │ │ │ ├── opening_loc: (96,9)-(96,10) = "[" - │ │ │ │ └── closing_loc: (96,14)-(96,15) = "]" + │ │ │ │ ├── opening_loc: (93,9)-(93,10) = "[" + │ │ │ │ └── closing_loc: (93,14)-(93,15) = "]" │ │ │ ├── rest: ∅ │ │ │ ├── posts: (length: 0) - │ │ │ ├── opening_loc: (96,8)-(96,9) = "[" - │ │ │ └── closing_loc: (96,15)-(96,16) = "]" + │ │ │ ├── opening_loc: (93,8)-(93,9) = "[" + │ │ │ └── closing_loc: (93,15)-(93,16) = "]" │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) - │ │ ├── opening_loc: (96,7)-(96,8) = "[" - │ │ └── closing_loc: (96,16)-(96,17) = "]" - │ └── operator_loc: (96,4)-(96,6) = "=>" - ├── @ MatchRequiredNode (location: (98,0)-(98,13)) + │ │ ├── opening_loc: (93,7)-(93,8) = "[" + │ │ └── closing_loc: (93,16)-(93,17) = "]" + │ └── operator_loc: (93,4)-(93,6) = "=>" + ├── @ MatchRequiredNode (location: (95,0)-(95,13)) + │ ├── flags: newline │ ├── value: - │ │ @ CallNode (location: (98,0)-(98,3)) + │ │ @ CallNode (location: (95,0)-(95,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (98,0)-(98,3) = "foo" + │ │ ├── message_loc: (95,0)-(95,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ ArrayPatternNode (location: (98,7)-(98,13)) + │ │ @ ArrayPatternNode (location: (95,7)-(95,13)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 0) │ │ ├── rest: - │ │ │ @ SplatNode (location: (98,8)-(98,12)) - │ │ │ ├── operator_loc: (98,8)-(98,9) = "*" + │ │ │ @ SplatNode (location: (95,8)-(95,12)) + │ │ │ ├── flags: ∅ + │ │ │ ├── operator_loc: (95,8)-(95,9) = "*" │ │ │ └── expression: - │ │ │ @ LocalVariableTargetNode (location: (98,9)-(98,12)) + │ │ │ @ LocalVariableTargetNode (location: (95,9)-(95,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── posts: (length: 0) - │ │ ├── opening_loc: (98,7)-(98,8) = "[" - │ │ └── closing_loc: (98,12)-(98,13) = "]" - │ └── operator_loc: (98,4)-(98,6) = "=>" - ├── @ MatchRequiredNode (location: (99,0)-(99,23)) + │ │ ├── opening_loc: (95,7)-(95,8) = "[" + │ │ └── closing_loc: (95,12)-(95,13) = "]" + │ └── operator_loc: (95,4)-(95,6) = "=>" + ├── @ MatchRequiredNode (location: (96,0)-(96,23)) + │ ├── flags: newline │ ├── value: - │ │ @ CallNode (location: (99,0)-(99,3)) + │ │ @ CallNode (location: (96,0)-(96,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (99,0)-(99,3) = "foo" + │ │ ├── message_loc: (96,0)-(96,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ ArrayPatternNode (location: (99,7)-(99,23)) + │ │ @ ArrayPatternNode (location: (96,7)-(96,23)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 0) │ │ ├── rest: - │ │ │ @ SplatNode (location: (99,8)-(99,12)) - │ │ │ ├── operator_loc: (99,8)-(99,9) = "*" + │ │ │ @ SplatNode (location: (96,8)-(96,12)) + │ │ │ ├── flags: ∅ + │ │ │ ├── operator_loc: (96,8)-(96,9) = "*" │ │ │ └── expression: - │ │ │ @ LocalVariableTargetNode (location: (99,9)-(99,12)) + │ │ │ @ LocalVariableTargetNode (location: (96,9)-(96,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── posts: (length: 2) - │ │ │ ├── @ LocalVariableTargetNode (location: (99,14)-(99,17)) + │ │ │ ├── @ LocalVariableTargetNode (location: (96,14)-(96,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 - │ │ │ └── @ LocalVariableTargetNode (location: (99,19)-(99,22)) + │ │ │ └── @ LocalVariableTargetNode (location: (96,19)-(96,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :qux │ │ │ └── depth: 0 - │ │ ├── opening_loc: (99,7)-(99,8) = "[" - │ │ └── closing_loc: (99,22)-(99,23) = "]" - │ └── operator_loc: (99,4)-(99,6) = "=>" - ├── @ MatchRequiredNode (location: (100,0)-(100,23)) + │ │ ├── opening_loc: (96,7)-(96,8) = "[" + │ │ └── closing_loc: (96,22)-(96,23) = "]" + │ └── operator_loc: (96,4)-(96,6) = "=>" + ├── @ MatchRequiredNode (location: (97,0)-(97,23)) + │ ├── flags: newline │ ├── value: - │ │ @ CallNode (location: (100,0)-(100,3)) + │ │ @ CallNode (location: (97,0)-(97,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (100,0)-(100,3) = "foo" + │ │ ├── message_loc: (97,0)-(97,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ ArrayPatternNode (location: (100,7)-(100,23)) + │ │ @ ArrayPatternNode (location: (97,7)-(97,23)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 1) - │ │ │ └── @ LocalVariableTargetNode (location: (100,8)-(100,11)) + │ │ │ └── @ LocalVariableTargetNode (location: (97,8)-(97,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── rest: - │ │ │ @ SplatNode (location: (100,13)-(100,17)) - │ │ │ ├── operator_loc: (100,13)-(100,14) = "*" + │ │ │ @ SplatNode (location: (97,13)-(97,17)) + │ │ │ ├── flags: ∅ + │ │ │ ├── operator_loc: (97,13)-(97,14) = "*" │ │ │ └── expression: - │ │ │ @ LocalVariableTargetNode (location: (100,14)-(100,17)) + │ │ │ @ LocalVariableTargetNode (location: (97,14)-(97,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ └── depth: 0 │ │ ├── posts: (length: 1) - │ │ │ └── @ LocalVariableTargetNode (location: (100,19)-(100,22)) + │ │ │ └── @ LocalVariableTargetNode (location: (97,19)-(97,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :qux │ │ │ └── depth: 0 - │ │ ├── opening_loc: (100,7)-(100,8) = "[" - │ │ └── closing_loc: (100,22)-(100,23) = "]" - │ └── operator_loc: (100,4)-(100,6) = "=>" - ├── @ MatchRequiredNode (location: (101,0)-(101,23)) + │ │ ├── opening_loc: (97,7)-(97,8) = "[" + │ │ └── closing_loc: (97,22)-(97,23) = "]" + │ └── operator_loc: (97,4)-(97,6) = "=>" + ├── @ MatchRequiredNode (location: (98,0)-(98,23)) + │ ├── flags: newline │ ├── value: - │ │ @ CallNode (location: (101,0)-(101,3)) + │ │ @ CallNode (location: (98,0)-(98,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (101,0)-(101,3) = "foo" + │ │ ├── message_loc: (98,0)-(98,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ ArrayPatternNode (location: (101,7)-(101,23)) + │ │ @ ArrayPatternNode (location: (98,7)-(98,23)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 2) - │ │ │ ├── @ LocalVariableTargetNode (location: (101,8)-(101,11)) + │ │ │ ├── @ LocalVariableTargetNode (location: (98,8)-(98,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :bar │ │ │ │ └── depth: 0 - │ │ │ └── @ LocalVariableTargetNode (location: (101,13)-(101,16)) + │ │ │ └── @ LocalVariableTargetNode (location: (98,13)-(98,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ └── depth: 0 │ │ ├── rest: - │ │ │ @ SplatNode (location: (101,18)-(101,22)) - │ │ │ ├── operator_loc: (101,18)-(101,19) = "*" + │ │ │ @ SplatNode (location: (98,18)-(98,22)) + │ │ │ ├── flags: ∅ + │ │ │ ├── operator_loc: (98,18)-(98,19) = "*" │ │ │ └── expression: - │ │ │ @ LocalVariableTargetNode (location: (101,19)-(101,22)) + │ │ │ @ LocalVariableTargetNode (location: (98,19)-(98,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :qux │ │ │ └── depth: 0 │ │ ├── posts: (length: 0) - │ │ ├── opening_loc: (101,7)-(101,8) = "[" - │ │ └── closing_loc: (101,22)-(101,23) = "]" - │ └── operator_loc: (101,4)-(101,6) = "=>" - ├── @ MatchRequiredNode (location: (102,0)-(102,24)) + │ │ ├── opening_loc: (98,7)-(98,8) = "[" + │ │ └── closing_loc: (98,22)-(98,23) = "]" + │ └── operator_loc: (98,4)-(98,6) = "=>" + ├── @ MatchRequiredNode (location: (99,0)-(99,24)) + │ ├── flags: newline │ ├── value: - │ │ @ CallNode (location: (102,0)-(102,3)) + │ │ @ CallNode (location: (99,0)-(99,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (102,0)-(102,3) = "foo" + │ │ ├── message_loc: (99,0)-(99,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ FindPatternNode (location: (102,7)-(102,24)) + │ │ @ FindPatternNode (location: (99,7)-(99,24)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── left: - │ │ │ @ SplatNode (location: (102,8)-(102,12)) - │ │ │ ├── operator_loc: (102,8)-(102,9) = "*" + │ │ │ @ SplatNode (location: (99,8)-(99,12)) + │ │ │ ├── flags: ∅ + │ │ │ ├── operator_loc: (99,8)-(99,9) = "*" │ │ │ └── expression: - │ │ │ @ LocalVariableTargetNode (location: (102,9)-(102,12)) + │ │ │ @ LocalVariableTargetNode (location: (99,9)-(99,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── requireds: (length: 1) - │ │ │ └── @ LocalVariableTargetNode (location: (102,14)-(102,17)) + │ │ │ └── @ LocalVariableTargetNode (location: (99,14)-(99,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ └── depth: 0 │ │ ├── right: - │ │ │ @ SplatNode (location: (102,19)-(102,23)) - │ │ │ ├── operator_loc: (102,19)-(102,20) = "*" + │ │ │ @ SplatNode (location: (99,19)-(99,23)) + │ │ │ ├── flags: ∅ + │ │ │ ├── operator_loc: (99,19)-(99,20) = "*" │ │ │ └── expression: - │ │ │ @ LocalVariableTargetNode (location: (102,20)-(102,23)) + │ │ │ @ LocalVariableTargetNode (location: (99,20)-(99,23)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :qux │ │ │ └── depth: 0 - │ │ ├── opening_loc: (102,7)-(102,8) = "[" - │ │ └── closing_loc: (102,23)-(102,24) = "]" - │ └── operator_loc: (102,4)-(102,6) = "=>" - ├── @ MatchPredicateNode (location: (104,0)-(104,10)) + │ │ ├── opening_loc: (99,7)-(99,8) = "[" + │ │ └── closing_loc: (99,23)-(99,24) = "]" + │ └── operator_loc: (99,4)-(99,6) = "=>" + ├── @ MatchPredicateNode (location: (101,0)-(101,10)) + │ ├── flags: newline │ ├── value: - │ │ @ CallNode (location: (104,0)-(104,3)) + │ │ @ CallNode (location: (101,0)-(101,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (104,0)-(104,3) = "foo" + │ │ ├── message_loc: (101,0)-(101,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ LocalVariableTargetNode (location: (104,7)-(104,10)) + │ │ @ LocalVariableTargetNode (location: (101,7)-(101,10)) + │ │ ├── flags: ∅ │ │ ├── name: :bar │ │ └── depth: 0 + │ └── operator_loc: (101,4)-(101,6) = "in" + ├── @ MatchPredicateNode (location: (102,0)-(102,8)) + │ ├── flags: newline + │ ├── value: + │ │ @ CallNode (location: (102,0)-(102,3)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :foo + │ │ ├── message_loc: (102,0)-(102,3) = "foo" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ ├── pattern: + │ │ @ IntegerNode (location: (102,7)-(102,8)) + │ │ ├── flags: static_literal, decimal + │ │ └── value: 1 + │ └── operator_loc: (102,4)-(102,6) = "in" + ├── @ MatchPredicateNode (location: (103,0)-(103,10)) + │ ├── flags: newline + │ ├── value: + │ │ @ CallNode (location: (103,0)-(103,3)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :foo + │ │ ├── message_loc: (103,0)-(103,3) = "foo" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ ├── pattern: + │ │ @ FloatNode (location: (103,7)-(103,10)) + │ │ ├── flags: static_literal + │ │ └── value: 1.0 + │ └── operator_loc: (103,4)-(103,6) = "in" + ├── @ MatchPredicateNode (location: (104,0)-(104,9)) + │ ├── flags: newline + │ ├── value: + │ │ @ CallNode (location: (104,0)-(104,3)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :foo + │ │ ├── message_loc: (104,0)-(104,3) = "foo" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ ├── pattern: + │ │ @ ImaginaryNode (location: (104,7)-(104,9)) + │ │ ├── flags: static_literal + │ │ └── numeric: + │ │ @ IntegerNode (location: (104,7)-(104,8)) + │ │ ├── flags: static_literal, decimal + │ │ └── value: 1 │ └── operator_loc: (104,4)-(104,6) = "in" - ├── @ MatchPredicateNode (location: (105,0)-(105,8)) + ├── @ MatchPredicateNode (location: (105,0)-(105,9)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (105,0)-(105,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2408,11 +2725,13 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ IntegerNode (location: (105,7)-(105,8)) - │ │ ├── flags: decimal - │ │ └── value: 1 + │ │ @ RationalNode (location: (105,7)-(105,9)) + │ │ ├── flags: static_literal, decimal + │ │ ├── numerator: 1 + │ │ └── denominator: 1 │ └── operator_loc: (105,4)-(105,6) = "in" - ├── @ MatchPredicateNode (location: (106,0)-(106,10)) + ├── @ MatchPredicateNode (location: (106,0)-(106,11)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (106,0)-(106,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2425,10 +2744,15 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ FloatNode (location: (106,7)-(106,10)) - │ │ └── value: 1.0 + │ │ @ SymbolNode (location: (106,7)-(106,11)) + │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ ├── opening_loc: (106,7)-(106,8) = ":" + │ │ ├── value_loc: (106,8)-(106,11) = "foo" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "foo" │ └── operator_loc: (106,4)-(106,6) = "in" - ├── @ MatchPredicateNode (location: (107,0)-(107,9)) + ├── @ MatchPredicateNode (location: (107,0)-(107,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (107,0)-(107,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2441,13 +2765,15 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ ImaginaryNode (location: (107,7)-(107,9)) - │ │ └── numeric: - │ │ @ IntegerNode (location: (107,7)-(107,8)) - │ │ ├── flags: decimal - │ │ └── value: 1 + │ │ @ SymbolNode (location: (107,7)-(107,14)) + │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ ├── opening_loc: (107,7)-(107,10) = "%s[" + │ │ ├── value_loc: (107,10)-(107,13) = "foo" + │ │ ├── closing_loc: (107,13)-(107,14) = "]" + │ │ └── unescaped: "foo" │ └── operator_loc: (107,4)-(107,6) = "in" - ├── @ MatchPredicateNode (location: (108,0)-(108,9)) + ├── @ MatchPredicateNode (location: (108,0)-(108,13)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (108,0)-(108,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2460,13 +2786,15 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ RationalNode (location: (108,7)-(108,9)) - │ │ └── numeric: - │ │ @ IntegerNode (location: (108,7)-(108,8)) - │ │ ├── flags: decimal - │ │ └── value: 1 + │ │ @ SymbolNode (location: (108,7)-(108,13)) + │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ ├── opening_loc: (108,7)-(108,9) = ":\"" + │ │ ├── value_loc: (108,9)-(108,12) = "foo" + │ │ ├── closing_loc: (108,12)-(108,13) = "\"" + │ │ └── unescaped: "foo" │ └── operator_loc: (108,4)-(108,6) = "in" - ├── @ MatchPredicateNode (location: (109,0)-(109,11)) + ├── @ MatchPredicateNode (location: (109,0)-(109,12)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (109,0)-(109,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2479,14 +2807,15 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ SymbolNode (location: (109,7)-(109,11)) - │ │ ├── flags: forced_us_ascii_encoding - │ │ ├── opening_loc: (109,7)-(109,8) = ":" - │ │ ├── value_loc: (109,8)-(109,11) = "foo" - │ │ ├── closing_loc: ∅ + │ │ @ RegularExpressionNode (location: (109,7)-(109,12)) + │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ ├── opening_loc: (109,7)-(109,8) = "/" + │ │ ├── content_loc: (109,8)-(109,11) = "foo" + │ │ ├── closing_loc: (109,11)-(109,12) = "/" │ │ └── unescaped: "foo" │ └── operator_loc: (109,4)-(109,6) = "in" - ├── @ MatchPredicateNode (location: (110,0)-(110,14)) + ├── @ MatchPredicateNode (location: (110,0)-(110,12)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (110,0)-(110,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2499,14 +2828,15 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ SymbolNode (location: (110,7)-(110,14)) - │ │ ├── flags: forced_us_ascii_encoding - │ │ ├── opening_loc: (110,7)-(110,10) = "%s[" - │ │ ├── value_loc: (110,10)-(110,13) = "foo" - │ │ ├── closing_loc: (110,13)-(110,14) = "]" + │ │ @ XStringNode (location: (110,7)-(110,12)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: (110,7)-(110,8) = "`" + │ │ ├── content_loc: (110,8)-(110,11) = "foo" + │ │ ├── closing_loc: (110,11)-(110,12) = "`" │ │ └── unescaped: "foo" │ └── operator_loc: (110,4)-(110,6) = "in" - ├── @ MatchPredicateNode (location: (111,0)-(111,13)) + ├── @ MatchPredicateNode (location: (111,0)-(111,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (111,0)-(111,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2519,14 +2849,15 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ SymbolNode (location: (111,7)-(111,13)) - │ │ ├── flags: forced_us_ascii_encoding - │ │ ├── opening_loc: (111,7)-(111,9) = ":\"" - │ │ ├── value_loc: (111,9)-(111,12) = "foo" - │ │ ├── closing_loc: (111,12)-(111,13) = "\"" + │ │ @ XStringNode (location: (111,7)-(111,14)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: (111,7)-(111,10) = "%x[" + │ │ ├── content_loc: (111,10)-(111,13) = "foo" + │ │ ├── closing_loc: (111,13)-(111,14) = "]" │ │ └── unescaped: "foo" │ └── operator_loc: (111,4)-(111,6) = "in" - ├── @ MatchPredicateNode (location: (112,0)-(112,12)) + ├── @ MatchPredicateNode (location: (112,0)-(112,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (112,0)-(112,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2539,14 +2870,20 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ RegularExpressionNode (location: (112,7)-(112,12)) - │ │ ├── flags: forced_us_ascii_encoding - │ │ ├── opening_loc: (112,7)-(112,8) = "/" - │ │ ├── content_loc: (112,8)-(112,11) = "foo" - │ │ ├── closing_loc: (112,11)-(112,12) = "/" - │ │ └── unescaped: "foo" + │ │ @ ArrayNode (location: (112,7)-(112,14)) + │ │ ├── flags: static_literal + │ │ ├── elements: (length: 1) + │ │ │ └── @ SymbolNode (location: (112,10)-(112,13)) + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── value_loc: (112,10)-(112,13) = "foo" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "foo" + │ │ ├── opening_loc: (112,7)-(112,10) = "%i[" + │ │ └── closing_loc: (112,13)-(112,14) = "]" │ └── operator_loc: (112,4)-(112,6) = "in" - ├── @ MatchPredicateNode (location: (113,0)-(113,12)) + ├── @ MatchPredicateNode (location: (113,0)-(113,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (113,0)-(113,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2559,14 +2896,20 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ XStringNode (location: (113,7)-(113,12)) - │ │ ├── flags: ∅ - │ │ ├── opening_loc: (113,7)-(113,8) = "`" - │ │ ├── content_loc: (113,8)-(113,11) = "foo" - │ │ ├── closing_loc: (113,11)-(113,12) = "`" - │ │ └── unescaped: "foo" + │ │ @ ArrayNode (location: (113,7)-(113,14)) + │ │ ├── flags: static_literal + │ │ ├── elements: (length: 1) + │ │ │ └── @ SymbolNode (location: (113,10)-(113,13)) + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── value_loc: (113,10)-(113,13) = "foo" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "foo" + │ │ ├── opening_loc: (113,7)-(113,10) = "%I[" + │ │ └── closing_loc: (113,13)-(113,14) = "]" │ └── operator_loc: (113,4)-(113,6) = "in" ├── @ MatchPredicateNode (location: (114,0)-(114,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (114,0)-(114,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2579,14 +2922,20 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ XStringNode (location: (114,7)-(114,14)) + │ │ @ ArrayNode (location: (114,7)-(114,14)) │ │ ├── flags: ∅ - │ │ ├── opening_loc: (114,7)-(114,10) = "%x[" - │ │ ├── content_loc: (114,10)-(114,13) = "foo" - │ │ ├── closing_loc: (114,13)-(114,14) = "]" - │ │ └── unescaped: "foo" + │ │ ├── elements: (length: 1) + │ │ │ └── @ StringNode (location: (114,10)-(114,13)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (114,10)-(114,13) = "foo" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "foo" + │ │ ├── opening_loc: (114,7)-(114,10) = "%w[" + │ │ └── closing_loc: (114,13)-(114,14) = "]" │ └── operator_loc: (114,4)-(114,6) = "in" ├── @ MatchPredicateNode (location: (115,0)-(115,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (115,0)-(115,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2602,16 +2951,17 @@ │ │ @ ArrayNode (location: (115,7)-(115,14)) │ │ ├── flags: ∅ │ │ ├── elements: (length: 1) - │ │ │ └── @ SymbolNode (location: (115,10)-(115,13)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ └── @ StringNode (location: (115,10)-(115,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (115,10)-(115,13) = "foo" + │ │ │ ├── content_loc: (115,10)-(115,13) = "foo" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "foo" - │ │ ├── opening_loc: (115,7)-(115,10) = "%i[" + │ │ ├── opening_loc: (115,7)-(115,10) = "%W[" │ │ └── closing_loc: (115,13)-(115,14) = "]" │ └── operator_loc: (115,4)-(115,6) = "in" ├── @ MatchPredicateNode (location: (116,0)-(116,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (116,0)-(116,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2624,19 +2974,15 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ ArrayNode (location: (116,7)-(116,14)) + │ │ @ StringNode (location: (116,7)-(116,14)) │ │ ├── flags: ∅ - │ │ ├── elements: (length: 1) - │ │ │ └── @ SymbolNode (location: (116,10)-(116,13)) - │ │ │ ├── flags: forced_us_ascii_encoding - │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (116,10)-(116,13) = "foo" - │ │ │ ├── closing_loc: ∅ - │ │ │ └── unescaped: "foo" - │ │ ├── opening_loc: (116,7)-(116,10) = "%I[" - │ │ └── closing_loc: (116,13)-(116,14) = "]" + │ │ ├── opening_loc: (116,7)-(116,10) = "%q[" + │ │ ├── content_loc: (116,10)-(116,13) = "foo" + │ │ ├── closing_loc: (116,13)-(116,14) = "]" + │ │ └── unescaped: "foo" │ └── operator_loc: (116,4)-(116,6) = "in" ├── @ MatchPredicateNode (location: (117,0)-(117,14)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (117,0)-(117,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2649,19 +2995,15 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ ArrayNode (location: (117,7)-(117,14)) + │ │ @ StringNode (location: (117,7)-(117,14)) │ │ ├── flags: ∅ - │ │ ├── elements: (length: 1) - │ │ │ └── @ StringNode (location: (117,10)-(117,13)) - │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (117,10)-(117,13) = "foo" - │ │ │ ├── closing_loc: ∅ - │ │ │ └── unescaped: "foo" - │ │ ├── opening_loc: (117,7)-(117,10) = "%w[" - │ │ └── closing_loc: (117,13)-(117,14) = "]" + │ │ ├── opening_loc: (117,7)-(117,10) = "%Q[" + │ │ ├── content_loc: (117,10)-(117,13) = "foo" + │ │ ├── closing_loc: (117,13)-(117,14) = "]" + │ │ └── unescaped: "foo" │ └── operator_loc: (117,4)-(117,6) = "in" - ├── @ MatchPredicateNode (location: (118,0)-(118,14)) + ├── @ MatchPredicateNode (location: (118,0)-(118,12)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (118,0)-(118,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2674,19 +3016,15 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ ArrayNode (location: (118,7)-(118,14)) + │ │ @ StringNode (location: (118,7)-(118,12)) │ │ ├── flags: ∅ - │ │ ├── elements: (length: 1) - │ │ │ └── @ StringNode (location: (118,10)-(118,13)) - │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (118,10)-(118,13) = "foo" - │ │ │ ├── closing_loc: ∅ - │ │ │ └── unescaped: "foo" - │ │ ├── opening_loc: (118,7)-(118,10) = "%W[" - │ │ └── closing_loc: (118,13)-(118,14) = "]" + │ │ ├── opening_loc: (118,7)-(118,8) = "\"" + │ │ ├── content_loc: (118,8)-(118,11) = "foo" + │ │ ├── closing_loc: (118,11)-(118,12) = "\"" + │ │ └── unescaped: "foo" │ └── operator_loc: (118,4)-(118,6) = "in" - ├── @ MatchPredicateNode (location: (119,0)-(119,14)) + ├── @ MatchPredicateNode (location: (119,0)-(119,10)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (119,0)-(119,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2699,14 +3037,11 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ StringNode (location: (119,7)-(119,14)) - │ │ ├── flags: ∅ - │ │ ├── opening_loc: (119,7)-(119,10) = "%q[" - │ │ ├── content_loc: (119,10)-(119,13) = "foo" - │ │ ├── closing_loc: (119,13)-(119,14) = "]" - │ │ └── unescaped: "foo" + │ │ @ NilNode (location: (119,7)-(119,10)) + │ │ └── flags: static_literal │ └── operator_loc: (119,4)-(119,6) = "in" - ├── @ MatchPredicateNode (location: (120,0)-(120,14)) + ├── @ MatchPredicateNode (location: (120,0)-(120,11)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (120,0)-(120,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2719,14 +3054,11 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ StringNode (location: (120,7)-(120,14)) - │ │ ├── flags: ∅ - │ │ ├── opening_loc: (120,7)-(120,10) = "%Q[" - │ │ ├── content_loc: (120,10)-(120,13) = "foo" - │ │ ├── closing_loc: (120,13)-(120,14) = "]" - │ │ └── unescaped: "foo" + │ │ @ SelfNode (location: (120,7)-(120,11)) + │ │ └── flags: ∅ │ └── operator_loc: (120,4)-(120,6) = "in" - ├── @ MatchPredicateNode (location: (121,0)-(121,12)) + ├── @ MatchPredicateNode (location: (121,0)-(121,11)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (121,0)-(121,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2739,14 +3071,11 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ StringNode (location: (121,7)-(121,12)) - │ │ ├── flags: ∅ - │ │ ├── opening_loc: (121,7)-(121,8) = "\"" - │ │ ├── content_loc: (121,8)-(121,11) = "foo" - │ │ ├── closing_loc: (121,11)-(121,12) = "\"" - │ │ └── unescaped: "foo" + │ │ @ TrueNode (location: (121,7)-(121,11)) + │ │ └── flags: static_literal │ └── operator_loc: (121,4)-(121,6) = "in" - ├── @ MatchPredicateNode (location: (122,0)-(122,10)) + ├── @ MatchPredicateNode (location: (122,0)-(122,12)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (122,0)-(122,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2759,9 +3088,11 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ NilNode (location: (122,7)-(122,10)) + │ │ @ FalseNode (location: (122,7)-(122,12)) + │ │ └── flags: static_literal │ └── operator_loc: (122,4)-(122,6) = "in" - ├── @ MatchPredicateNode (location: (123,0)-(123,11)) + ├── @ MatchPredicateNode (location: (123,0)-(123,15)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (123,0)-(123,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2774,9 +3105,12 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ SelfNode (location: (123,7)-(123,11)) + │ │ @ SourceFileNode (location: (123,7)-(123,15)) + │ │ ├── flags: ∅ + │ │ └── filepath: "patterns.txt" │ └── operator_loc: (123,4)-(123,6) = "in" - ├── @ MatchPredicateNode (location: (124,0)-(124,11)) + ├── @ MatchPredicateNode (location: (124,0)-(124,15)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (124,0)-(124,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2789,9 +3123,11 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ TrueNode (location: (124,7)-(124,11)) + │ │ @ SourceLineNode (location: (124,7)-(124,15)) + │ │ └── flags: static_literal │ └── operator_loc: (124,4)-(124,6) = "in" - ├── @ MatchPredicateNode (location: (125,0)-(125,12)) + ├── @ MatchPredicateNode (location: (125,0)-(125,19)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (125,0)-(125,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2804,9 +3140,11 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ FalseNode (location: (125,7)-(125,12)) + │ │ @ SourceEncodingNode (location: (125,7)-(125,19)) + │ │ └── flags: static_literal │ └── operator_loc: (125,4)-(125,6) = "in" - ├── @ MatchPredicateNode (location: (126,0)-(126,15)) + ├── @ MatchPredicateNode (location: (126,0)-(126,17)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (126,0)-(126,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2819,11 +3157,24 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ SourceFileNode (location: (126,7)-(126,15)) + │ │ @ LambdaNode (location: (126,7)-(126,17)) │ │ ├── flags: ∅ - │ │ └── filepath: "patterns.txt" + │ │ ├── locals: [] + │ │ ├── operator_loc: (126,7)-(126,9) = "->" + │ │ ├── opening_loc: (126,10)-(126,11) = "{" + │ │ ├── closing_loc: (126,16)-(126,17) = "}" + │ │ ├── parameters: ∅ + │ │ └── body: + │ │ @ StatementsNode (location: (126,12)-(126,15)) + │ │ ├── flags: ∅ + │ │ └── body: (length: 1) + │ │ └── @ LocalVariableReadNode (location: (126,12)-(126,15)) + │ │ ├── flags: newline + │ │ ├── name: :bar + │ │ └── depth: 1 │ └── operator_loc: (126,4)-(126,6) = "in" - ├── @ MatchPredicateNode (location: (127,0)-(127,15)) + ├── @ MatchPredicateNode (location: (127,0)-(127,11)) + │ ├── flags: newline │ ├── value: │ │ @ CallNode (location: (127,0)-(127,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2836,75 +3187,187 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ SourceLineNode (location: (127,7)-(127,15)) + │ │ @ ArrayPatternNode (location: (127,7)-(127,11)) + │ │ ├── flags: ∅ + │ │ ├── constant: ∅ + │ │ ├── requireds: (length: 1) + │ │ │ └── @ LocalVariableTargetNode (location: (127,7)-(127,10)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :bar + │ │ │ └── depth: 0 + │ │ ├── rest: + │ │ │ @ ImplicitRestNode (location: (127,10)-(127,11)) + │ │ │ └── flags: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── opening_loc: ∅ + │ │ └── closing_loc: ∅ │ └── operator_loc: (127,4)-(127,6) = "in" - ├── @ MatchPredicateNode (location: (128,0)-(128,19)) - │ ├── value: - │ │ @ CallNode (location: (128,0)-(128,3)) + ├── @ CaseMatchNode (location: (129,0)-(129,25)) + │ ├── flags: newline + │ ├── predicate: + │ │ @ CallNode (location: (129,5)-(129,8)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (128,0)-(128,3) = "foo" + │ │ ├── message_loc: (129,5)-(129,8) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── pattern: - │ │ @ SourceEncodingNode (location: (128,7)-(128,19)) - │ └── operator_loc: (128,4)-(128,6) = "in" - ├── @ MatchPredicateNode (location: (129,0)-(129,17)) - │ ├── value: - │ │ @ CallNode (location: (129,0)-(129,3)) + │ ├── conditions: (length: 1) + │ │ └── @ InNode (location: (129,10)-(129,21)) + │ │ ├── flags: ∅ + │ │ ├── pattern: + │ │ │ @ LocalVariableTargetNode (location: (129,13)-(129,16)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :bar + │ │ │ └── depth: 0 + │ │ ├── statements: ∅ + │ │ ├── in_loc: (129,10)-(129,12) = "in" + │ │ └── then_loc: (129,17)-(129,21) = "then" + │ ├── else_clause: ∅ + │ ├── case_keyword_loc: (129,0)-(129,4) = "case" + │ └── end_keyword_loc: (129,22)-(129,25) = "end" + ├── @ CaseMatchNode (location: (130,0)-(130,23)) + │ ├── flags: newline + │ ├── predicate: + │ │ @ CallNode (location: (130,5)-(130,8)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (129,0)-(129,3) = "foo" + │ │ ├── message_loc: (130,5)-(130,8) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── pattern: - │ │ @ LambdaNode (location: (129,7)-(129,17)) - │ │ ├── locals: [] - │ │ ├── operator_loc: (129,7)-(129,9) = "->" - │ │ ├── opening_loc: (129,10)-(129,11) = "{" - │ │ ├── closing_loc: (129,16)-(129,17) = "}" - │ │ ├── parameters: ∅ - │ │ └── body: - │ │ @ StatementsNode (location: (129,12)-(129,15)) - │ │ └── body: (length: 1) - │ │ └── @ LocalVariableReadNode (location: (129,12)-(129,15)) - │ │ ├── name: :bar - │ │ └── depth: 1 - │ └── operator_loc: (129,4)-(129,6) = "in" - ├── @ MatchPredicateNode (location: (131,0)-(131,11)) - │ ├── value: - │ │ @ CallNode (location: (131,0)-(131,3)) + │ ├── conditions: (length: 1) + │ │ └── @ InNode (location: (130,10)-(130,19)) + │ │ ├── flags: ∅ + │ │ ├── pattern: + │ │ │ @ IntegerNode (location: (130,13)-(130,14)) + │ │ │ ├── flags: static_literal, decimal + │ │ │ └── value: 1 + │ │ ├── statements: ∅ + │ │ ├── in_loc: (130,10)-(130,12) = "in" + │ │ └── then_loc: (130,15)-(130,19) = "then" + │ ├── else_clause: ∅ + │ ├── case_keyword_loc: (130,0)-(130,4) = "case" + │ └── end_keyword_loc: (130,20)-(130,23) = "end" + ├── @ CaseMatchNode (location: (131,0)-(131,25)) + │ ├── flags: newline + │ ├── predicate: + │ │ @ CallNode (location: (131,5)-(131,8)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (131,0)-(131,3) = "foo" + │ │ ├── message_loc: (131,5)-(131,8) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── pattern: - │ │ @ ArrayPatternNode (location: (131,7)-(131,11)) - │ │ ├── constant: ∅ - │ │ ├── requireds: (length: 1) - │ │ │ └── @ LocalVariableTargetNode (location: (131,7)-(131,10)) - │ │ │ ├── name: :bar - │ │ │ └── depth: 0 - │ │ ├── rest: - │ │ │ @ ImplicitRestNode (location: (131,10)-(131,11)) - │ │ ├── posts: (length: 0) + │ ├── conditions: (length: 1) + │ │ └── @ InNode (location: (131,10)-(131,21)) + │ │ ├── flags: ∅ + │ │ ├── pattern: + │ │ │ @ FloatNode (location: (131,13)-(131,16)) + │ │ │ ├── flags: static_literal + │ │ │ └── value: 1.0 + │ │ ├── statements: ∅ + │ │ ├── in_loc: (131,10)-(131,12) = "in" + │ │ └── then_loc: (131,17)-(131,21) = "then" + │ ├── else_clause: ∅ + │ ├── case_keyword_loc: (131,0)-(131,4) = "case" + │ └── end_keyword_loc: (131,22)-(131,25) = "end" + ├── @ CaseMatchNode (location: (132,0)-(132,24)) + │ ├── flags: newline + │ ├── predicate: + │ │ @ CallNode (location: (132,5)-(132,8)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :foo + │ │ ├── message_loc: (132,5)-(132,8) = "foo" │ │ ├── opening_loc: ∅ - │ │ └── closing_loc: ∅ - │ └── operator_loc: (131,4)-(131,6) = "in" - ├── @ CaseMatchNode (location: (135,0)-(135,25)) + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ ├── conditions: (length: 1) + │ │ └── @ InNode (location: (132,10)-(132,20)) + │ │ ├── flags: ∅ + │ │ ├── pattern: + │ │ │ @ ImaginaryNode (location: (132,13)-(132,15)) + │ │ │ ├── flags: static_literal + │ │ │ └── numeric: + │ │ │ @ IntegerNode (location: (132,13)-(132,14)) + │ │ │ ├── flags: static_literal, decimal + │ │ │ └── value: 1 + │ │ ├── statements: ∅ + │ │ ├── in_loc: (132,10)-(132,12) = "in" + │ │ └── then_loc: (132,16)-(132,20) = "then" + │ ├── else_clause: ∅ + │ ├── case_keyword_loc: (132,0)-(132,4) = "case" + │ └── end_keyword_loc: (132,21)-(132,24) = "end" + ├── @ CaseMatchNode (location: (133,0)-(133,24)) + │ ├── flags: newline + │ ├── predicate: + │ │ @ CallNode (location: (133,5)-(133,8)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :foo + │ │ ├── message_loc: (133,5)-(133,8) = "foo" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ ├── conditions: (length: 1) + │ │ └── @ InNode (location: (133,10)-(133,20)) + │ │ ├── flags: ∅ + │ │ ├── pattern: + │ │ │ @ RationalNode (location: (133,13)-(133,15)) + │ │ │ ├── flags: static_literal, decimal + │ │ │ ├── numerator: 1 + │ │ │ └── denominator: 1 + │ │ ├── statements: ∅ + │ │ ├── in_loc: (133,10)-(133,12) = "in" + │ │ └── then_loc: (133,16)-(133,20) = "then" + │ ├── else_clause: ∅ + │ ├── case_keyword_loc: (133,0)-(133,4) = "case" + │ └── end_keyword_loc: (133,21)-(133,24) = "end" + ├── @ CaseMatchNode (location: (134,0)-(134,26)) + │ ├── flags: newline + │ ├── predicate: + │ │ @ CallNode (location: (134,5)-(134,8)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :foo + │ │ ├── message_loc: (134,5)-(134,8) = "foo" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ ├── conditions: (length: 1) + │ │ └── @ InNode (location: (134,10)-(134,22)) + │ │ ├── flags: ∅ + │ │ ├── pattern: + │ │ │ @ SymbolNode (location: (134,13)-(134,17)) + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ ├── opening_loc: (134,13)-(134,14) = ":" + │ │ │ ├── value_loc: (134,14)-(134,17) = "foo" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "foo" + │ │ ├── statements: ∅ + │ │ ├── in_loc: (134,10)-(134,12) = "in" + │ │ └── then_loc: (134,18)-(134,22) = "then" + │ ├── else_clause: ∅ + │ ├── case_keyword_loc: (134,0)-(134,4) = "case" + │ └── end_keyword_loc: (134,23)-(134,26) = "end" + ├── @ CaseMatchNode (location: (135,0)-(135,29)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (135,5)-(135,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -2917,18 +3380,23 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (135,10)-(135,21)) + │ │ └── @ InNode (location: (135,10)-(135,25)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ LocalVariableTargetNode (location: (135,13)-(135,16)) - │ │ │ ├── name: :bar - │ │ │ └── depth: 0 + │ │ │ @ SymbolNode (location: (135,13)-(135,20)) + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ ├── opening_loc: (135,13)-(135,16) = "%s[" + │ │ │ ├── value_loc: (135,16)-(135,19) = "foo" + │ │ │ ├── closing_loc: (135,19)-(135,20) = "]" + │ │ │ └── unescaped: "foo" │ │ ├── statements: ∅ │ │ ├── in_loc: (135,10)-(135,12) = "in" - │ │ └── then_loc: (135,17)-(135,21) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (135,21)-(135,25) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (135,0)-(135,4) = "case" - │ └── end_keyword_loc: (135,22)-(135,25) = "end" - ├── @ CaseMatchNode (location: (136,0)-(136,23)) + │ └── end_keyword_loc: (135,26)-(135,29) = "end" + ├── @ CaseMatchNode (location: (136,0)-(136,28)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (136,5)-(136,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -2941,18 +3409,23 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (136,10)-(136,19)) + │ │ └── @ InNode (location: (136,10)-(136,24)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IntegerNode (location: (136,13)-(136,14)) - │ │ │ ├── flags: decimal - │ │ │ └── value: 1 + │ │ │ @ SymbolNode (location: (136,13)-(136,19)) + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ ├── opening_loc: (136,13)-(136,15) = ":\"" + │ │ │ ├── value_loc: (136,15)-(136,18) = "foo" + │ │ │ ├── closing_loc: (136,18)-(136,19) = "\"" + │ │ │ └── unescaped: "foo" │ │ ├── statements: ∅ │ │ ├── in_loc: (136,10)-(136,12) = "in" - │ │ └── then_loc: (136,15)-(136,19) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (136,20)-(136,24) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (136,0)-(136,4) = "case" - │ └── end_keyword_loc: (136,20)-(136,23) = "end" - ├── @ CaseMatchNode (location: (137,0)-(137,25)) + │ └── end_keyword_loc: (136,25)-(136,28) = "end" + ├── @ CaseMatchNode (location: (137,0)-(137,27)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (137,5)-(137,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -2965,17 +3438,23 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (137,10)-(137,21)) + │ │ └── @ InNode (location: (137,10)-(137,23)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ FloatNode (location: (137,13)-(137,16)) - │ │ │ └── value: 1.0 + │ │ │ @ RegularExpressionNode (location: (137,13)-(137,18)) + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ ├── opening_loc: (137,13)-(137,14) = "/" + │ │ │ ├── content_loc: (137,14)-(137,17) = "foo" + │ │ │ ├── closing_loc: (137,17)-(137,18) = "/" + │ │ │ └── unescaped: "foo" │ │ ├── statements: ∅ │ │ ├── in_loc: (137,10)-(137,12) = "in" - │ │ └── then_loc: (137,17)-(137,21) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (137,19)-(137,23) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (137,0)-(137,4) = "case" - │ └── end_keyword_loc: (137,22)-(137,25) = "end" - ├── @ CaseMatchNode (location: (138,0)-(138,24)) + │ └── end_keyword_loc: (137,24)-(137,27) = "end" + ├── @ CaseMatchNode (location: (138,0)-(138,27)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (138,5)-(138,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -2988,20 +3467,23 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (138,10)-(138,20)) + │ │ └── @ InNode (location: (138,10)-(138,23)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ ImaginaryNode (location: (138,13)-(138,15)) - │ │ │ └── numeric: - │ │ │ @ IntegerNode (location: (138,13)-(138,14)) - │ │ │ ├── flags: decimal - │ │ │ └── value: 1 + │ │ │ @ XStringNode (location: (138,13)-(138,18)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: (138,13)-(138,14) = "`" + │ │ │ ├── content_loc: (138,14)-(138,17) = "foo" + │ │ │ ├── closing_loc: (138,17)-(138,18) = "`" + │ │ │ └── unescaped: "foo" │ │ ├── statements: ∅ │ │ ├── in_loc: (138,10)-(138,12) = "in" - │ │ └── then_loc: (138,16)-(138,20) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (138,19)-(138,23) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (138,0)-(138,4) = "case" - │ └── end_keyword_loc: (138,21)-(138,24) = "end" - ├── @ CaseMatchNode (location: (139,0)-(139,24)) + │ └── end_keyword_loc: (138,24)-(138,27) = "end" + ├── @ CaseMatchNode (location: (139,0)-(139,29)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (139,5)-(139,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3014,20 +3496,23 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (139,10)-(139,20)) + │ │ └── @ InNode (location: (139,10)-(139,25)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ RationalNode (location: (139,13)-(139,15)) - │ │ │ └── numeric: - │ │ │ @ IntegerNode (location: (139,13)-(139,14)) - │ │ │ ├── flags: decimal - │ │ │ └── value: 1 + │ │ │ @ XStringNode (location: (139,13)-(139,20)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: (139,13)-(139,16) = "%x[" + │ │ │ ├── content_loc: (139,16)-(139,19) = "foo" + │ │ │ ├── closing_loc: (139,19)-(139,20) = "]" + │ │ │ └── unescaped: "foo" │ │ ├── statements: ∅ │ │ ├── in_loc: (139,10)-(139,12) = "in" - │ │ └── then_loc: (139,16)-(139,20) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (139,21)-(139,25) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (139,0)-(139,4) = "case" - │ └── end_keyword_loc: (139,21)-(139,24) = "end" - ├── @ CaseMatchNode (location: (140,0)-(140,26)) + │ └── end_keyword_loc: (139,26)-(139,29) = "end" + ├── @ CaseMatchNode (location: (140,0)-(140,29)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (140,5)-(140,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3040,21 +3525,28 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (140,10)-(140,22)) + │ │ └── @ InNode (location: (140,10)-(140,25)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ SymbolNode (location: (140,13)-(140,17)) - │ │ │ ├── flags: forced_us_ascii_encoding - │ │ │ ├── opening_loc: (140,13)-(140,14) = ":" - │ │ │ ├── value_loc: (140,14)-(140,17) = "foo" - │ │ │ ├── closing_loc: ∅ - │ │ │ └── unescaped: "foo" + │ │ │ @ ArrayNode (location: (140,13)-(140,20)) + │ │ │ ├── flags: static_literal + │ │ │ ├── elements: (length: 1) + │ │ │ │ └── @ SymbolNode (location: (140,16)-(140,19)) + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── value_loc: (140,16)-(140,19) = "foo" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "foo" + │ │ │ ├── opening_loc: (140,13)-(140,16) = "%i[" + │ │ │ └── closing_loc: (140,19)-(140,20) = "]" │ │ ├── statements: ∅ │ │ ├── in_loc: (140,10)-(140,12) = "in" - │ │ └── then_loc: (140,18)-(140,22) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (140,21)-(140,25) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (140,0)-(140,4) = "case" - │ └── end_keyword_loc: (140,23)-(140,26) = "end" + │ └── end_keyword_loc: (140,26)-(140,29) = "end" ├── @ CaseMatchNode (location: (141,0)-(141,29)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (141,5)-(141,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3068,20 +3560,27 @@ │ │ └── block: ∅ │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (141,10)-(141,25)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ SymbolNode (location: (141,13)-(141,20)) - │ │ │ ├── flags: forced_us_ascii_encoding - │ │ │ ├── opening_loc: (141,13)-(141,16) = "%s[" - │ │ │ ├── value_loc: (141,16)-(141,19) = "foo" - │ │ │ ├── closing_loc: (141,19)-(141,20) = "]" - │ │ │ └── unescaped: "foo" + │ │ │ @ ArrayNode (location: (141,13)-(141,20)) + │ │ │ ├── flags: static_literal + │ │ │ ├── elements: (length: 1) + │ │ │ │ └── @ SymbolNode (location: (141,16)-(141,19)) + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── value_loc: (141,16)-(141,19) = "foo" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "foo" + │ │ │ ├── opening_loc: (141,13)-(141,16) = "%I[" + │ │ │ └── closing_loc: (141,19)-(141,20) = "]" │ │ ├── statements: ∅ │ │ ├── in_loc: (141,10)-(141,12) = "in" │ │ └── then_loc: (141,21)-(141,25) = "then" - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (141,0)-(141,4) = "case" │ └── end_keyword_loc: (141,26)-(141,29) = "end" - ├── @ CaseMatchNode (location: (142,0)-(142,28)) + ├── @ CaseMatchNode (location: (142,0)-(142,29)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (142,5)-(142,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3094,21 +3593,28 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (142,10)-(142,24)) + │ │ └── @ InNode (location: (142,10)-(142,25)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ SymbolNode (location: (142,13)-(142,19)) - │ │ │ ├── flags: forced_us_ascii_encoding - │ │ │ ├── opening_loc: (142,13)-(142,15) = ":\"" - │ │ │ ├── value_loc: (142,15)-(142,18) = "foo" - │ │ │ ├── closing_loc: (142,18)-(142,19) = "\"" - │ │ │ └── unescaped: "foo" + │ │ │ @ ArrayNode (location: (142,13)-(142,20)) + │ │ │ ├── flags: ∅ + │ │ │ ├── elements: (length: 1) + │ │ │ │ └── @ StringNode (location: (142,16)-(142,19)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (142,16)-(142,19) = "foo" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "foo" + │ │ │ ├── opening_loc: (142,13)-(142,16) = "%w[" + │ │ │ └── closing_loc: (142,19)-(142,20) = "]" │ │ ├── statements: ∅ │ │ ├── in_loc: (142,10)-(142,12) = "in" - │ │ └── then_loc: (142,20)-(142,24) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (142,21)-(142,25) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (142,0)-(142,4) = "case" - │ └── end_keyword_loc: (142,25)-(142,28) = "end" - ├── @ CaseMatchNode (location: (143,0)-(143,27)) + │ └── end_keyword_loc: (142,26)-(142,29) = "end" + ├── @ CaseMatchNode (location: (143,0)-(143,29)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (143,5)-(143,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3121,21 +3627,28 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (143,10)-(143,23)) + │ │ └── @ InNode (location: (143,10)-(143,25)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ RegularExpressionNode (location: (143,13)-(143,18)) - │ │ │ ├── flags: forced_us_ascii_encoding - │ │ │ ├── opening_loc: (143,13)-(143,14) = "/" - │ │ │ ├── content_loc: (143,14)-(143,17) = "foo" - │ │ │ ├── closing_loc: (143,17)-(143,18) = "/" - │ │ │ └── unescaped: "foo" + │ │ │ @ ArrayNode (location: (143,13)-(143,20)) + │ │ │ ├── flags: ∅ + │ │ │ ├── elements: (length: 1) + │ │ │ │ └── @ StringNode (location: (143,16)-(143,19)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (143,16)-(143,19) = "foo" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "foo" + │ │ │ ├── opening_loc: (143,13)-(143,16) = "%W[" + │ │ │ └── closing_loc: (143,19)-(143,20) = "]" │ │ ├── statements: ∅ │ │ ├── in_loc: (143,10)-(143,12) = "in" - │ │ └── then_loc: (143,19)-(143,23) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (143,21)-(143,25) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (143,0)-(143,4) = "case" - │ └── end_keyword_loc: (143,24)-(143,27) = "end" - ├── @ CaseMatchNode (location: (144,0)-(144,27)) + │ └── end_keyword_loc: (143,26)-(143,29) = "end" + ├── @ CaseMatchNode (location: (144,0)-(144,29)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (144,5)-(144,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3148,21 +3661,23 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (144,10)-(144,23)) + │ │ └── @ InNode (location: (144,10)-(144,25)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ XStringNode (location: (144,13)-(144,18)) + │ │ │ @ StringNode (location: (144,13)-(144,20)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (144,13)-(144,14) = "`" - │ │ │ ├── content_loc: (144,14)-(144,17) = "foo" - │ │ │ ├── closing_loc: (144,17)-(144,18) = "`" + │ │ │ ├── opening_loc: (144,13)-(144,16) = "%q[" + │ │ │ ├── content_loc: (144,16)-(144,19) = "foo" + │ │ │ ├── closing_loc: (144,19)-(144,20) = "]" │ │ │ └── unescaped: "foo" │ │ ├── statements: ∅ │ │ ├── in_loc: (144,10)-(144,12) = "in" - │ │ └── then_loc: (144,19)-(144,23) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (144,21)-(144,25) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (144,0)-(144,4) = "case" - │ └── end_keyword_loc: (144,24)-(144,27) = "end" + │ └── end_keyword_loc: (144,26)-(144,29) = "end" ├── @ CaseMatchNode (location: (145,0)-(145,29)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (145,5)-(145,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3176,20 +3691,22 @@ │ │ └── block: ∅ │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (145,10)-(145,25)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ XStringNode (location: (145,13)-(145,20)) + │ │ │ @ StringNode (location: (145,13)-(145,20)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (145,13)-(145,16) = "%x[" + │ │ │ ├── opening_loc: (145,13)-(145,16) = "%Q[" │ │ │ ├── content_loc: (145,16)-(145,19) = "foo" │ │ │ ├── closing_loc: (145,19)-(145,20) = "]" │ │ │ └── unescaped: "foo" │ │ ├── statements: ∅ │ │ ├── in_loc: (145,10)-(145,12) = "in" │ │ └── then_loc: (145,21)-(145,25) = "then" - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (145,0)-(145,4) = "case" │ └── end_keyword_loc: (145,26)-(145,29) = "end" - ├── @ CaseMatchNode (location: (146,0)-(146,29)) + ├── @ CaseMatchNode (location: (146,0)-(146,27)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (146,5)-(146,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3202,26 +3719,23 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (146,10)-(146,25)) + │ │ └── @ InNode (location: (146,10)-(146,23)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ ArrayNode (location: (146,13)-(146,20)) + │ │ │ @ StringNode (location: (146,13)-(146,18)) │ │ │ ├── flags: ∅ - │ │ │ ├── elements: (length: 1) - │ │ │ │ └── @ SymbolNode (location: (146,16)-(146,19)) - │ │ │ │ ├── flags: forced_us_ascii_encoding - │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── value_loc: (146,16)-(146,19) = "foo" - │ │ │ │ ├── closing_loc: ∅ - │ │ │ │ └── unescaped: "foo" - │ │ │ ├── opening_loc: (146,13)-(146,16) = "%i[" - │ │ │ └── closing_loc: (146,19)-(146,20) = "]" + │ │ │ ├── opening_loc: (146,13)-(146,14) = "\"" + │ │ │ ├── content_loc: (146,14)-(146,17) = "foo" + │ │ │ ├── closing_loc: (146,17)-(146,18) = "\"" + │ │ │ └── unescaped: "foo" │ │ ├── statements: ∅ │ │ ├── in_loc: (146,10)-(146,12) = "in" - │ │ └── then_loc: (146,21)-(146,25) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (146,19)-(146,23) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (146,0)-(146,4) = "case" - │ └── end_keyword_loc: (146,26)-(146,29) = "end" - ├── @ CaseMatchNode (location: (147,0)-(147,29)) + │ └── end_keyword_loc: (146,24)-(146,27) = "end" + ├── @ CaseMatchNode (location: (147,0)-(147,25)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (147,5)-(147,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3234,26 +3748,19 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (147,10)-(147,25)) + │ │ └── @ InNode (location: (147,10)-(147,21)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ ArrayNode (location: (147,13)-(147,20)) - │ │ │ ├── flags: ∅ - │ │ │ ├── elements: (length: 1) - │ │ │ │ └── @ SymbolNode (location: (147,16)-(147,19)) - │ │ │ │ ├── flags: forced_us_ascii_encoding - │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── value_loc: (147,16)-(147,19) = "foo" - │ │ │ │ ├── closing_loc: ∅ - │ │ │ │ └── unescaped: "foo" - │ │ │ ├── opening_loc: (147,13)-(147,16) = "%I[" - │ │ │ └── closing_loc: (147,19)-(147,20) = "]" + │ │ │ @ NilNode (location: (147,13)-(147,16)) + │ │ │ └── flags: static_literal │ │ ├── statements: ∅ │ │ ├── in_loc: (147,10)-(147,12) = "in" - │ │ └── then_loc: (147,21)-(147,25) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (147,17)-(147,21) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (147,0)-(147,4) = "case" - │ └── end_keyword_loc: (147,26)-(147,29) = "end" - ├── @ CaseMatchNode (location: (148,0)-(148,29)) + │ └── end_keyword_loc: (147,22)-(147,25) = "end" + ├── @ CaseMatchNode (location: (148,0)-(148,26)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (148,5)-(148,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3266,26 +3773,19 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (148,10)-(148,25)) + │ │ └── @ InNode (location: (148,10)-(148,22)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ ArrayNode (location: (148,13)-(148,20)) - │ │ │ ├── flags: ∅ - │ │ │ ├── elements: (length: 1) - │ │ │ │ └── @ StringNode (location: (148,16)-(148,19)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── content_loc: (148,16)-(148,19) = "foo" - │ │ │ │ ├── closing_loc: ∅ - │ │ │ │ └── unescaped: "foo" - │ │ │ ├── opening_loc: (148,13)-(148,16) = "%w[" - │ │ │ └── closing_loc: (148,19)-(148,20) = "]" + │ │ │ @ SelfNode (location: (148,13)-(148,17)) + │ │ │ └── flags: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (148,10)-(148,12) = "in" - │ │ └── then_loc: (148,21)-(148,25) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (148,18)-(148,22) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (148,0)-(148,4) = "case" - │ └── end_keyword_loc: (148,26)-(148,29) = "end" - ├── @ CaseMatchNode (location: (149,0)-(149,29)) + │ └── end_keyword_loc: (148,23)-(148,26) = "end" + ├── @ CaseMatchNode (location: (149,0)-(149,26)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (149,5)-(149,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3298,26 +3798,19 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (149,10)-(149,25)) + │ │ └── @ InNode (location: (149,10)-(149,22)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ ArrayNode (location: (149,13)-(149,20)) - │ │ │ ├── flags: ∅ - │ │ │ ├── elements: (length: 1) - │ │ │ │ └── @ StringNode (location: (149,16)-(149,19)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── content_loc: (149,16)-(149,19) = "foo" - │ │ │ │ ├── closing_loc: ∅ - │ │ │ │ └── unescaped: "foo" - │ │ │ ├── opening_loc: (149,13)-(149,16) = "%W[" - │ │ │ └── closing_loc: (149,19)-(149,20) = "]" + │ │ │ @ TrueNode (location: (149,13)-(149,17)) + │ │ │ └── flags: static_literal │ │ ├── statements: ∅ │ │ ├── in_loc: (149,10)-(149,12) = "in" - │ │ └── then_loc: (149,21)-(149,25) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (149,18)-(149,22) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (149,0)-(149,4) = "case" - │ └── end_keyword_loc: (149,26)-(149,29) = "end" - ├── @ CaseMatchNode (location: (150,0)-(150,29)) + │ └── end_keyword_loc: (149,23)-(149,26) = "end" + ├── @ CaseMatchNode (location: (150,0)-(150,27)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (150,5)-(150,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3330,21 +3823,19 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (150,10)-(150,25)) + │ │ └── @ InNode (location: (150,10)-(150,23)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ StringNode (location: (150,13)-(150,20)) - │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (150,13)-(150,16) = "%q[" - │ │ │ ├── content_loc: (150,16)-(150,19) = "foo" - │ │ │ ├── closing_loc: (150,19)-(150,20) = "]" - │ │ │ └── unescaped: "foo" + │ │ │ @ FalseNode (location: (150,13)-(150,18)) + │ │ │ └── flags: static_literal │ │ ├── statements: ∅ │ │ ├── in_loc: (150,10)-(150,12) = "in" - │ │ └── then_loc: (150,21)-(150,25) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (150,19)-(150,23) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (150,0)-(150,4) = "case" - │ └── end_keyword_loc: (150,26)-(150,29) = "end" - ├── @ CaseMatchNode (location: (151,0)-(151,29)) + │ └── end_keyword_loc: (150,24)-(150,27) = "end" + ├── @ CaseMatchNode (location: (151,0)-(151,30)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (151,5)-(151,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3357,21 +3848,20 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (151,10)-(151,25)) + │ │ └── @ InNode (location: (151,10)-(151,26)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ StringNode (location: (151,13)-(151,20)) + │ │ │ @ SourceFileNode (location: (151,13)-(151,21)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (151,13)-(151,16) = "%Q[" - │ │ │ ├── content_loc: (151,16)-(151,19) = "foo" - │ │ │ ├── closing_loc: (151,19)-(151,20) = "]" - │ │ │ └── unescaped: "foo" + │ │ │ └── filepath: "patterns.txt" │ │ ├── statements: ∅ │ │ ├── in_loc: (151,10)-(151,12) = "in" - │ │ └── then_loc: (151,21)-(151,25) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (151,22)-(151,26) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (151,0)-(151,4) = "case" - │ └── end_keyword_loc: (151,26)-(151,29) = "end" - ├── @ CaseMatchNode (location: (152,0)-(152,27)) + │ └── end_keyword_loc: (151,27)-(151,30) = "end" + ├── @ CaseMatchNode (location: (152,0)-(152,30)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (152,5)-(152,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3384,21 +3874,19 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (152,10)-(152,23)) + │ │ └── @ InNode (location: (152,10)-(152,26)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ StringNode (location: (152,13)-(152,18)) - │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (152,13)-(152,14) = "\"" - │ │ │ ├── content_loc: (152,14)-(152,17) = "foo" - │ │ │ ├── closing_loc: (152,17)-(152,18) = "\"" - │ │ │ └── unescaped: "foo" + │ │ │ @ SourceLineNode (location: (152,13)-(152,21)) + │ │ │ └── flags: static_literal │ │ ├── statements: ∅ │ │ ├── in_loc: (152,10)-(152,12) = "in" - │ │ └── then_loc: (152,19)-(152,23) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (152,22)-(152,26) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (152,0)-(152,4) = "case" - │ └── end_keyword_loc: (152,24)-(152,27) = "end" - ├── @ CaseMatchNode (location: (153,0)-(153,25)) + │ └── end_keyword_loc: (152,27)-(152,30) = "end" + ├── @ CaseMatchNode (location: (153,0)-(153,34)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (153,5)-(153,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3411,16 +3899,19 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (153,10)-(153,21)) + │ │ └── @ InNode (location: (153,10)-(153,30)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ NilNode (location: (153,13)-(153,16)) + │ │ │ @ SourceEncodingNode (location: (153,13)-(153,25)) + │ │ │ └── flags: static_literal │ │ ├── statements: ∅ │ │ ├── in_loc: (153,10)-(153,12) = "in" - │ │ └── then_loc: (153,17)-(153,21) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (153,26)-(153,30) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (153,0)-(153,4) = "case" - │ └── end_keyword_loc: (153,22)-(153,25) = "end" - ├── @ CaseMatchNode (location: (154,0)-(154,26)) + │ └── end_keyword_loc: (153,31)-(153,34) = "end" + ├── @ CaseMatchNode (location: (154,0)-(154,32)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (154,5)-(154,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3433,38 +3924,32 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (154,10)-(154,22)) + │ │ └── @ InNode (location: (154,10)-(154,28)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ SelfNode (location: (154,13)-(154,17)) + │ │ │ @ LambdaNode (location: (154,13)-(154,23)) + │ │ │ ├── flags: ∅ + │ │ │ ├── locals: [] + │ │ │ ├── operator_loc: (154,13)-(154,15) = "->" + │ │ │ ├── opening_loc: (154,16)-(154,17) = "{" + │ │ │ ├── closing_loc: (154,22)-(154,23) = "}" + │ │ │ ├── parameters: ∅ + │ │ │ └── body: + │ │ │ @ StatementsNode (location: (154,18)-(154,21)) + │ │ │ ├── flags: ∅ + │ │ │ └── body: (length: 1) + │ │ │ └── @ LocalVariableReadNode (location: (154,18)-(154,21)) + │ │ │ ├── flags: newline + │ │ │ ├── name: :bar + │ │ │ └── depth: 1 │ │ ├── statements: ∅ │ │ ├── in_loc: (154,10)-(154,12) = "in" - │ │ └── then_loc: (154,18)-(154,22) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (154,24)-(154,28) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (154,0)-(154,4) = "case" - │ └── end_keyword_loc: (154,23)-(154,26) = "end" - ├── @ CaseMatchNode (location: (155,0)-(155,26)) - │ ├── predicate: - │ │ @ CallNode (location: (155,5)-(155,8)) - │ │ ├── flags: variable_call, ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :foo - │ │ ├── message_loc: (155,5)-(155,8) = "foo" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: ∅ - │ │ ├── closing_loc: ∅ - │ │ └── block: ∅ - │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (155,10)-(155,22)) - │ │ ├── pattern: - │ │ │ @ TrueNode (location: (155,13)-(155,17)) - │ │ ├── statements: ∅ - │ │ ├── in_loc: (155,10)-(155,12) = "in" - │ │ └── then_loc: (155,18)-(155,22) = "then" - │ ├── consequent: ∅ - │ ├── case_keyword_loc: (155,0)-(155,4) = "case" - │ └── end_keyword_loc: (155,23)-(155,26) = "end" - ├── @ CaseMatchNode (location: (156,0)-(156,27)) + │ └── end_keyword_loc: (154,29)-(154,32) = "end" + ├── @ CaseMatchNode (location: (156,0)-(156,32)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (156,5)-(156,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3477,16 +3962,36 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (156,10)-(156,23)) + │ │ └── @ InNode (location: (156,10)-(156,28)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ FalseNode (location: (156,13)-(156,18)) + │ │ │ @ IfNode (location: (156,13)-(156,23)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (156,17)-(156,19) = "if" + │ │ │ ├── predicate: + │ │ │ │ @ LocalVariableReadNode (location: (156,20)-(156,23)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── name: :baz + │ │ │ │ └── depth: 0 + │ │ │ ├── then_keyword_loc: ∅ + │ │ │ ├── statements: + │ │ │ │ @ StatementsNode (location: (156,13)-(156,16)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── body: (length: 1) + │ │ │ │ └── @ LocalVariableTargetNode (location: (156,13)-(156,16)) + │ │ │ │ ├── flags: newline + │ │ │ │ ├── name: :bar + │ │ │ │ └── depth: 0 + │ │ │ ├── subsequent: ∅ + │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (156,10)-(156,12) = "in" - │ │ └── then_loc: (156,19)-(156,23) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (156,24)-(156,28) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (156,0)-(156,4) = "case" - │ └── end_keyword_loc: (156,24)-(156,27) = "end" + │ └── end_keyword_loc: (156,29)-(156,32) = "end" ├── @ CaseMatchNode (location: (157,0)-(157,30)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (157,5)-(157,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3500,17 +4005,34 @@ │ │ └── block: ∅ │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (157,10)-(157,26)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ SourceFileNode (location: (157,13)-(157,21)) - │ │ │ ├── flags: ∅ - │ │ │ └── filepath: "patterns.txt" + │ │ │ @ IfNode (location: (157,13)-(157,21)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (157,15)-(157,17) = "if" + │ │ │ ├── predicate: + │ │ │ │ @ LocalVariableReadNode (location: (157,18)-(157,21)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── name: :baz + │ │ │ │ └── depth: 0 + │ │ │ ├── then_keyword_loc: ∅ + │ │ │ ├── statements: + │ │ │ │ @ StatementsNode (location: (157,13)-(157,14)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── body: (length: 1) + │ │ │ │ └── @ IntegerNode (location: (157,13)-(157,14)) + │ │ │ │ ├── flags: newline, static_literal, decimal + │ │ │ │ └── value: 1 + │ │ │ ├── subsequent: ∅ + │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (157,10)-(157,12) = "in" │ │ └── then_loc: (157,22)-(157,26) = "then" - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (157,0)-(157,4) = "case" │ └── end_keyword_loc: (157,27)-(157,30) = "end" - ├── @ CaseMatchNode (location: (158,0)-(158,30)) + ├── @ CaseMatchNode (location: (158,0)-(158,32)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (158,5)-(158,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3523,16 +4045,35 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (158,10)-(158,26)) + │ │ └── @ InNode (location: (158,10)-(158,28)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ SourceLineNode (location: (158,13)-(158,21)) + │ │ │ @ IfNode (location: (158,13)-(158,23)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (158,17)-(158,19) = "if" + │ │ │ ├── predicate: + │ │ │ │ @ LocalVariableReadNode (location: (158,20)-(158,23)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── name: :baz + │ │ │ │ └── depth: 0 + │ │ │ ├── then_keyword_loc: ∅ + │ │ │ ├── statements: + │ │ │ │ @ StatementsNode (location: (158,13)-(158,16)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── body: (length: 1) + │ │ │ │ └── @ FloatNode (location: (158,13)-(158,16)) + │ │ │ │ ├── flags: newline, static_literal + │ │ │ │ └── value: 1.0 + │ │ │ ├── subsequent: ∅ + │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (158,10)-(158,12) = "in" - │ │ └── then_loc: (158,22)-(158,26) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (158,24)-(158,28) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (158,0)-(158,4) = "case" - │ └── end_keyword_loc: (158,27)-(158,30) = "end" - ├── @ CaseMatchNode (location: (159,0)-(159,34)) + │ └── end_keyword_loc: (158,29)-(158,32) = "end" + ├── @ CaseMatchNode (location: (159,0)-(159,31)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (159,5)-(159,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3545,16 +4086,38 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (159,10)-(159,30)) + │ │ └── @ InNode (location: (159,10)-(159,27)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ SourceEncodingNode (location: (159,13)-(159,25)) + │ │ │ @ IfNode (location: (159,13)-(159,22)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (159,16)-(159,18) = "if" + │ │ │ ├── predicate: + │ │ │ │ @ LocalVariableReadNode (location: (159,19)-(159,22)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── name: :baz + │ │ │ │ └── depth: 0 + │ │ │ ├── then_keyword_loc: ∅ + │ │ │ ├── statements: + │ │ │ │ @ StatementsNode (location: (159,13)-(159,15)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── body: (length: 1) + │ │ │ │ └── @ ImaginaryNode (location: (159,13)-(159,15)) + │ │ │ │ ├── flags: newline, static_literal + │ │ │ │ └── numeric: + │ │ │ │ @ IntegerNode (location: (159,13)-(159,14)) + │ │ │ │ ├── flags: static_literal, decimal + │ │ │ │ └── value: 1 + │ │ │ ├── subsequent: ∅ + │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (159,10)-(159,12) = "in" - │ │ └── then_loc: (159,26)-(159,30) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (159,23)-(159,27) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (159,0)-(159,4) = "case" - │ └── end_keyword_loc: (159,31)-(159,34) = "end" - ├── @ CaseMatchNode (location: (160,0)-(160,32)) + │ └── end_keyword_loc: (159,28)-(159,31) = "end" + ├── @ CaseMatchNode (location: (160,0)-(160,31)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (160,5)-(160,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3567,27 +4130,80 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (160,10)-(160,28)) + │ │ └── @ InNode (location: (160,10)-(160,27)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ LambdaNode (location: (160,13)-(160,23)) - │ │ │ ├── locals: [] - │ │ │ ├── operator_loc: (160,13)-(160,15) = "->" - │ │ │ ├── opening_loc: (160,16)-(160,17) = "{" - │ │ │ ├── closing_loc: (160,22)-(160,23) = "}" - │ │ │ ├── parameters: ∅ - │ │ │ └── body: - │ │ │ @ StatementsNode (location: (160,18)-(160,21)) - │ │ │ └── body: (length: 1) - │ │ │ └── @ LocalVariableReadNode (location: (160,18)-(160,21)) - │ │ │ ├── name: :bar - │ │ │ └── depth: 1 + │ │ │ @ IfNode (location: (160,13)-(160,22)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (160,16)-(160,18) = "if" + │ │ │ ├── predicate: + │ │ │ │ @ LocalVariableReadNode (location: (160,19)-(160,22)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── name: :baz + │ │ │ │ └── depth: 0 + │ │ │ ├── then_keyword_loc: ∅ + │ │ │ ├── statements: + │ │ │ │ @ StatementsNode (location: (160,13)-(160,15)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── body: (length: 1) + │ │ │ │ └── @ RationalNode (location: (160,13)-(160,15)) + │ │ │ │ ├── flags: newline, static_literal, decimal + │ │ │ │ ├── numerator: 1 + │ │ │ │ └── denominator: 1 + │ │ │ ├── subsequent: ∅ + │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (160,10)-(160,12) = "in" - │ │ └── then_loc: (160,24)-(160,28) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (160,23)-(160,27) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (160,0)-(160,4) = "case" - │ └── end_keyword_loc: (160,29)-(160,32) = "end" - ├── @ CaseMatchNode (location: (162,0)-(162,32)) + │ └── end_keyword_loc: (160,28)-(160,31) = "end" + ├── @ CaseMatchNode (location: (161,0)-(161,33)) + │ ├── flags: newline + │ ├── predicate: + │ │ @ CallNode (location: (161,5)-(161,8)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :foo + │ │ ├── message_loc: (161,5)-(161,8) = "foo" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ ├── conditions: (length: 1) + │ │ └── @ InNode (location: (161,10)-(161,29)) + │ │ ├── flags: ∅ + │ │ ├── pattern: + │ │ │ @ IfNode (location: (161,13)-(161,24)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (161,18)-(161,20) = "if" + │ │ │ ├── predicate: + │ │ │ │ @ LocalVariableReadNode (location: (161,21)-(161,24)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── name: :baz + │ │ │ │ └── depth: 0 + │ │ │ ├── then_keyword_loc: ∅ + │ │ │ ├── statements: + │ │ │ │ @ StatementsNode (location: (161,13)-(161,17)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── body: (length: 1) + │ │ │ │ └── @ SymbolNode (location: (161,13)-(161,17)) + │ │ │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ │ │ │ ├── opening_loc: (161,13)-(161,14) = ":" + │ │ │ │ ├── value_loc: (161,14)-(161,17) = "foo" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "foo" + │ │ │ ├── subsequent: ∅ + │ │ │ └── end_keyword_loc: ∅ + │ │ ├── statements: ∅ + │ │ ├── in_loc: (161,10)-(161,12) = "in" + │ │ └── then_loc: (161,25)-(161,29) = "then" + │ ├── else_clause: ∅ + │ ├── case_keyword_loc: (161,0)-(161,4) = "case" + │ └── end_keyword_loc: (161,30)-(161,33) = "end" + ├── @ CaseMatchNode (location: (162,0)-(162,36)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (162,5)-(162,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3600,30 +4216,38 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (162,10)-(162,28)) + │ │ └── @ InNode (location: (162,10)-(162,32)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (162,13)-(162,23)) - │ │ │ ├── if_keyword_loc: (162,17)-(162,19) = "if" + │ │ │ @ IfNode (location: (162,13)-(162,27)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (162,21)-(162,23) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (162,20)-(162,23)) + │ │ │ │ @ LocalVariableReadNode (location: (162,24)-(162,27)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (162,13)-(162,16)) + │ │ │ │ @ StatementsNode (location: (162,13)-(162,20)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ LocalVariableTargetNode (location: (162,13)-(162,16)) - │ │ │ │ ├── name: :bar - │ │ │ │ └── depth: 0 - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ SymbolNode (location: (162,13)-(162,20)) + │ │ │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ │ │ │ ├── opening_loc: (162,13)-(162,16) = "%s[" + │ │ │ │ ├── value_loc: (162,16)-(162,19) = "foo" + │ │ │ │ ├── closing_loc: (162,19)-(162,20) = "]" + │ │ │ │ └── unescaped: "foo" + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (162,10)-(162,12) = "in" - │ │ └── then_loc: (162,24)-(162,28) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (162,28)-(162,32) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (162,0)-(162,4) = "case" - │ └── end_keyword_loc: (162,29)-(162,32) = "end" - ├── @ CaseMatchNode (location: (163,0)-(163,30)) + │ └── end_keyword_loc: (162,33)-(162,36) = "end" + ├── @ CaseMatchNode (location: (163,0)-(163,35)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (163,5)-(163,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3636,30 +4260,38 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (163,10)-(163,26)) + │ │ └── @ InNode (location: (163,10)-(163,31)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (163,13)-(163,21)) - │ │ │ ├── if_keyword_loc: (163,15)-(163,17) = "if" + │ │ │ @ IfNode (location: (163,13)-(163,26)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (163,20)-(163,22) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (163,18)-(163,21)) + │ │ │ │ @ LocalVariableReadNode (location: (163,23)-(163,26)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (163,13)-(163,14)) + │ │ │ │ @ StatementsNode (location: (163,13)-(163,19)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ IntegerNode (location: (163,13)-(163,14)) - │ │ │ │ ├── flags: decimal - │ │ │ │ └── value: 1 - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ SymbolNode (location: (163,13)-(163,19)) + │ │ │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ │ │ │ ├── opening_loc: (163,13)-(163,15) = ":\"" + │ │ │ │ ├── value_loc: (163,15)-(163,18) = "foo" + │ │ │ │ ├── closing_loc: (163,18)-(163,19) = "\"" + │ │ │ │ └── unescaped: "foo" + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (163,10)-(163,12) = "in" - │ │ └── then_loc: (163,22)-(163,26) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (163,27)-(163,31) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (163,0)-(163,4) = "case" - │ └── end_keyword_loc: (163,27)-(163,30) = "end" - ├── @ CaseMatchNode (location: (164,0)-(164,32)) + │ └── end_keyword_loc: (163,32)-(163,35) = "end" + ├── @ CaseMatchNode (location: (164,0)-(164,34)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (164,5)-(164,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3672,29 +4304,38 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (164,10)-(164,28)) + │ │ └── @ InNode (location: (164,10)-(164,30)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (164,13)-(164,23)) - │ │ │ ├── if_keyword_loc: (164,17)-(164,19) = "if" + │ │ │ @ IfNode (location: (164,13)-(164,25)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (164,19)-(164,21) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (164,20)-(164,23)) + │ │ │ │ @ LocalVariableReadNode (location: (164,22)-(164,25)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (164,13)-(164,16)) + │ │ │ │ @ StatementsNode (location: (164,13)-(164,18)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ FloatNode (location: (164,13)-(164,16)) - │ │ │ │ └── value: 1.0 - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ RegularExpressionNode (location: (164,13)-(164,18)) + │ │ │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ │ │ │ ├── opening_loc: (164,13)-(164,14) = "/" + │ │ │ │ ├── content_loc: (164,14)-(164,17) = "foo" + │ │ │ │ ├── closing_loc: (164,17)-(164,18) = "/" + │ │ │ │ └── unescaped: "foo" + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (164,10)-(164,12) = "in" - │ │ └── then_loc: (164,24)-(164,28) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (164,26)-(164,30) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (164,0)-(164,4) = "case" - │ └── end_keyword_loc: (164,29)-(164,32) = "end" - ├── @ CaseMatchNode (location: (165,0)-(165,31)) + │ └── end_keyword_loc: (164,31)-(164,34) = "end" + ├── @ CaseMatchNode (location: (165,0)-(165,34)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (165,5)-(165,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3707,32 +4348,38 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (165,10)-(165,27)) + │ │ └── @ InNode (location: (165,10)-(165,30)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (165,13)-(165,22)) - │ │ │ ├── if_keyword_loc: (165,16)-(165,18) = "if" + │ │ │ @ IfNode (location: (165,13)-(165,25)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (165,19)-(165,21) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (165,19)-(165,22)) + │ │ │ │ @ LocalVariableReadNode (location: (165,22)-(165,25)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (165,13)-(165,15)) + │ │ │ │ @ StatementsNode (location: (165,13)-(165,18)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ ImaginaryNode (location: (165,13)-(165,15)) - │ │ │ │ └── numeric: - │ │ │ │ @ IntegerNode (location: (165,13)-(165,14)) - │ │ │ │ ├── flags: decimal - │ │ │ │ └── value: 1 - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ XStringNode (location: (165,13)-(165,18)) + │ │ │ │ ├── flags: newline + │ │ │ │ ├── opening_loc: (165,13)-(165,14) = "`" + │ │ │ │ ├── content_loc: (165,14)-(165,17) = "foo" + │ │ │ │ ├── closing_loc: (165,17)-(165,18) = "`" + │ │ │ │ └── unescaped: "foo" + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (165,10)-(165,12) = "in" - │ │ └── then_loc: (165,23)-(165,27) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (165,26)-(165,30) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (165,0)-(165,4) = "case" - │ └── end_keyword_loc: (165,28)-(165,31) = "end" - ├── @ CaseMatchNode (location: (166,0)-(166,31)) + │ └── end_keyword_loc: (165,31)-(165,34) = "end" + ├── @ CaseMatchNode (location: (166,0)-(166,36)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (166,5)-(166,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3745,32 +4392,38 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (166,10)-(166,27)) + │ │ └── @ InNode (location: (166,10)-(166,32)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (166,13)-(166,22)) - │ │ │ ├── if_keyword_loc: (166,16)-(166,18) = "if" + │ │ │ @ IfNode (location: (166,13)-(166,27)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (166,21)-(166,23) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (166,19)-(166,22)) + │ │ │ │ @ LocalVariableReadNode (location: (166,24)-(166,27)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (166,13)-(166,15)) + │ │ │ │ @ StatementsNode (location: (166,13)-(166,20)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ RationalNode (location: (166,13)-(166,15)) - │ │ │ │ └── numeric: - │ │ │ │ @ IntegerNode (location: (166,13)-(166,14)) - │ │ │ │ ├── flags: decimal - │ │ │ │ └── value: 1 - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ XStringNode (location: (166,13)-(166,20)) + │ │ │ │ ├── flags: newline + │ │ │ │ ├── opening_loc: (166,13)-(166,16) = "%x[" + │ │ │ │ ├── content_loc: (166,16)-(166,19) = "foo" + │ │ │ │ ├── closing_loc: (166,19)-(166,20) = "]" + │ │ │ │ └── unescaped: "foo" + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (166,10)-(166,12) = "in" - │ │ └── then_loc: (166,23)-(166,27) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (166,28)-(166,32) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (166,0)-(166,4) = "case" - │ └── end_keyword_loc: (166,28)-(166,31) = "end" - ├── @ CaseMatchNode (location: (167,0)-(167,33)) + │ └── end_keyword_loc: (166,33)-(166,36) = "end" + ├── @ CaseMatchNode (location: (167,0)-(167,36)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (167,5)-(167,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3783,33 +4436,43 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (167,10)-(167,29)) + │ │ └── @ InNode (location: (167,10)-(167,32)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (167,13)-(167,24)) - │ │ │ ├── if_keyword_loc: (167,18)-(167,20) = "if" + │ │ │ @ IfNode (location: (167,13)-(167,27)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (167,21)-(167,23) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (167,21)-(167,24)) + │ │ │ │ @ LocalVariableReadNode (location: (167,24)-(167,27)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (167,13)-(167,17)) + │ │ │ │ @ StatementsNode (location: (167,13)-(167,20)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ SymbolNode (location: (167,13)-(167,17)) - │ │ │ │ ├── flags: forced_us_ascii_encoding - │ │ │ │ ├── opening_loc: (167,13)-(167,14) = ":" - │ │ │ │ ├── value_loc: (167,14)-(167,17) = "foo" - │ │ │ │ ├── closing_loc: ∅ - │ │ │ │ └── unescaped: "foo" - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ ArrayNode (location: (167,13)-(167,20)) + │ │ │ │ ├── flags: newline, static_literal + │ │ │ │ ├── elements: (length: 1) + │ │ │ │ │ └── @ SymbolNode (location: (167,16)-(167,19)) + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── value_loc: (167,16)-(167,19) = "foo" + │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ └── unescaped: "foo" + │ │ │ │ ├── opening_loc: (167,13)-(167,16) = "%i[" + │ │ │ │ └── closing_loc: (167,19)-(167,20) = "]" + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (167,10)-(167,12) = "in" - │ │ └── then_loc: (167,25)-(167,29) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (167,28)-(167,32) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (167,0)-(167,4) = "case" - │ └── end_keyword_loc: (167,30)-(167,33) = "end" + │ └── end_keyword_loc: (167,33)-(167,36) = "end" ├── @ CaseMatchNode (location: (168,0)-(168,36)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (168,5)-(168,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3823,32 +4486,42 @@ │ │ └── block: ∅ │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (168,10)-(168,32)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ IfNode (location: (168,13)-(168,27)) + │ │ │ ├── flags: newline │ │ │ ├── if_keyword_loc: (168,21)-(168,23) = "if" │ │ │ ├── predicate: │ │ │ │ @ LocalVariableReadNode (location: (168,24)-(168,27)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (168,13)-(168,20)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ SymbolNode (location: (168,13)-(168,20)) - │ │ │ │ ├── flags: forced_us_ascii_encoding - │ │ │ │ ├── opening_loc: (168,13)-(168,16) = "%s[" - │ │ │ │ ├── value_loc: (168,16)-(168,19) = "foo" - │ │ │ │ ├── closing_loc: (168,19)-(168,20) = "]" - │ │ │ │ └── unescaped: "foo" - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ ArrayNode (location: (168,13)-(168,20)) + │ │ │ │ ├── flags: newline, static_literal + │ │ │ │ ├── elements: (length: 1) + │ │ │ │ │ └── @ SymbolNode (location: (168,16)-(168,19)) + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── value_loc: (168,16)-(168,19) = "foo" + │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ └── unescaped: "foo" + │ │ │ │ ├── opening_loc: (168,13)-(168,16) = "%I[" + │ │ │ │ └── closing_loc: (168,19)-(168,20) = "]" + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (168,10)-(168,12) = "in" │ │ └── then_loc: (168,28)-(168,32) = "then" - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (168,0)-(168,4) = "case" │ └── end_keyword_loc: (168,33)-(168,36) = "end" - ├── @ CaseMatchNode (location: (169,0)-(169,35)) + ├── @ CaseMatchNode (location: (169,0)-(169,36)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (169,5)-(169,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3861,33 +4534,43 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (169,10)-(169,31)) + │ │ └── @ InNode (location: (169,10)-(169,32)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (169,13)-(169,26)) - │ │ │ ├── if_keyword_loc: (169,20)-(169,22) = "if" + │ │ │ @ IfNode (location: (169,13)-(169,27)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (169,21)-(169,23) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (169,23)-(169,26)) + │ │ │ │ @ LocalVariableReadNode (location: (169,24)-(169,27)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (169,13)-(169,19)) + │ │ │ │ @ StatementsNode (location: (169,13)-(169,20)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ SymbolNode (location: (169,13)-(169,19)) - │ │ │ │ ├── flags: forced_us_ascii_encoding - │ │ │ │ ├── opening_loc: (169,13)-(169,15) = ":\"" - │ │ │ │ ├── value_loc: (169,15)-(169,18) = "foo" - │ │ │ │ ├── closing_loc: (169,18)-(169,19) = "\"" - │ │ │ │ └── unescaped: "foo" - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ ArrayNode (location: (169,13)-(169,20)) + │ │ │ │ ├── flags: newline + │ │ │ │ ├── elements: (length: 1) + │ │ │ │ │ └── @ StringNode (location: (169,16)-(169,19)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── content_loc: (169,16)-(169,19) = "foo" + │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ └── unescaped: "foo" + │ │ │ │ ├── opening_loc: (169,13)-(169,16) = "%w[" + │ │ │ │ └── closing_loc: (169,19)-(169,20) = "]" + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (169,10)-(169,12) = "in" - │ │ └── then_loc: (169,27)-(169,31) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (169,28)-(169,32) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (169,0)-(169,4) = "case" - │ └── end_keyword_loc: (169,32)-(169,35) = "end" - ├── @ CaseMatchNode (location: (170,0)-(170,34)) + │ └── end_keyword_loc: (169,33)-(169,36) = "end" + ├── @ CaseMatchNode (location: (170,0)-(170,36)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (170,5)-(170,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3900,33 +4583,43 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (170,10)-(170,30)) + │ │ └── @ InNode (location: (170,10)-(170,32)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (170,13)-(170,25)) - │ │ │ ├── if_keyword_loc: (170,19)-(170,21) = "if" + │ │ │ @ IfNode (location: (170,13)-(170,27)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (170,21)-(170,23) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (170,22)-(170,25)) + │ │ │ │ @ LocalVariableReadNode (location: (170,24)-(170,27)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (170,13)-(170,18)) + │ │ │ │ @ StatementsNode (location: (170,13)-(170,20)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ RegularExpressionNode (location: (170,13)-(170,18)) - │ │ │ │ ├── flags: forced_us_ascii_encoding - │ │ │ │ ├── opening_loc: (170,13)-(170,14) = "/" - │ │ │ │ ├── content_loc: (170,14)-(170,17) = "foo" - │ │ │ │ ├── closing_loc: (170,17)-(170,18) = "/" - │ │ │ │ └── unescaped: "foo" - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ ArrayNode (location: (170,13)-(170,20)) + │ │ │ │ ├── flags: newline + │ │ │ │ ├── elements: (length: 1) + │ │ │ │ │ └── @ StringNode (location: (170,16)-(170,19)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── content_loc: (170,16)-(170,19) = "foo" + │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ └── unescaped: "foo" + │ │ │ │ ├── opening_loc: (170,13)-(170,16) = "%W[" + │ │ │ │ └── closing_loc: (170,19)-(170,20) = "]" + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (170,10)-(170,12) = "in" - │ │ └── then_loc: (170,26)-(170,30) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (170,28)-(170,32) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (170,0)-(170,4) = "case" - │ └── end_keyword_loc: (170,31)-(170,34) = "end" - ├── @ CaseMatchNode (location: (171,0)-(171,34)) + │ └── end_keyword_loc: (170,33)-(170,36) = "end" + ├── @ CaseMatchNode (location: (171,0)-(171,36)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (171,5)-(171,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3939,33 +4632,38 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (171,10)-(171,30)) + │ │ └── @ InNode (location: (171,10)-(171,32)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (171,13)-(171,25)) - │ │ │ ├── if_keyword_loc: (171,19)-(171,21) = "if" + │ │ │ @ IfNode (location: (171,13)-(171,27)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (171,21)-(171,23) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (171,22)-(171,25)) + │ │ │ │ @ LocalVariableReadNode (location: (171,24)-(171,27)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (171,13)-(171,18)) + │ │ │ │ @ StatementsNode (location: (171,13)-(171,20)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ XStringNode (location: (171,13)-(171,18)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (171,13)-(171,14) = "`" - │ │ │ │ ├── content_loc: (171,14)-(171,17) = "foo" - │ │ │ │ ├── closing_loc: (171,17)-(171,18) = "`" + │ │ │ │ └── @ StringNode (location: (171,13)-(171,20)) + │ │ │ │ ├── flags: newline + │ │ │ │ ├── opening_loc: (171,13)-(171,16) = "%q[" + │ │ │ │ ├── content_loc: (171,16)-(171,19) = "foo" + │ │ │ │ ├── closing_loc: (171,19)-(171,20) = "]" │ │ │ │ └── unescaped: "foo" - │ │ │ ├── consequent: ∅ + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (171,10)-(171,12) = "in" - │ │ └── then_loc: (171,26)-(171,30) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (171,28)-(171,32) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (171,0)-(171,4) = "case" - │ └── end_keyword_loc: (171,31)-(171,34) = "end" + │ └── end_keyword_loc: (171,33)-(171,36) = "end" ├── @ CaseMatchNode (location: (172,0)-(172,36)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (172,5)-(172,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -3979,32 +4677,37 @@ │ │ └── block: ∅ │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (172,10)-(172,32)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ IfNode (location: (172,13)-(172,27)) + │ │ │ ├── flags: newline │ │ │ ├── if_keyword_loc: (172,21)-(172,23) = "if" │ │ │ ├── predicate: │ │ │ │ @ LocalVariableReadNode (location: (172,24)-(172,27)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (172,13)-(172,20)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ XStringNode (location: (172,13)-(172,20)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (172,13)-(172,16) = "%x[" + │ │ │ │ └── @ StringNode (location: (172,13)-(172,20)) + │ │ │ │ ├── flags: newline + │ │ │ │ ├── opening_loc: (172,13)-(172,16) = "%Q[" │ │ │ │ ├── content_loc: (172,16)-(172,19) = "foo" │ │ │ │ ├── closing_loc: (172,19)-(172,20) = "]" │ │ │ │ └── unescaped: "foo" - │ │ │ ├── consequent: ∅ + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (172,10)-(172,12) = "in" │ │ └── then_loc: (172,28)-(172,32) = "then" - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (172,0)-(172,4) = "case" │ └── end_keyword_loc: (172,33)-(172,36) = "end" - ├── @ CaseMatchNode (location: (173,0)-(173,36)) + ├── @ CaseMatchNode (location: (173,0)-(173,34)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (173,5)-(173,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -4017,38 +4720,38 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (173,10)-(173,32)) + │ │ └── @ InNode (location: (173,10)-(173,30)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (173,13)-(173,27)) - │ │ │ ├── if_keyword_loc: (173,21)-(173,23) = "if" + │ │ │ @ IfNode (location: (173,13)-(173,25)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (173,19)-(173,21) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (173,24)-(173,27)) + │ │ │ │ @ LocalVariableReadNode (location: (173,22)-(173,25)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (173,13)-(173,20)) + │ │ │ │ @ StatementsNode (location: (173,13)-(173,18)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ ArrayNode (location: (173,13)-(173,20)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── elements: (length: 1) - │ │ │ │ │ └── @ SymbolNode (location: (173,16)-(173,19)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding - │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── value_loc: (173,16)-(173,19) = "foo" - │ │ │ │ │ ├── closing_loc: ∅ - │ │ │ │ │ └── unescaped: "foo" - │ │ │ │ ├── opening_loc: (173,13)-(173,16) = "%i[" - │ │ │ │ └── closing_loc: (173,19)-(173,20) = "]" - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ StringNode (location: (173,13)-(173,18)) + │ │ │ │ ├── flags: newline + │ │ │ │ ├── opening_loc: (173,13)-(173,14) = "\"" + │ │ │ │ ├── content_loc: (173,14)-(173,17) = "foo" + │ │ │ │ ├── closing_loc: (173,17)-(173,18) = "\"" + │ │ │ │ └── unescaped: "foo" + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (173,10)-(173,12) = "in" - │ │ └── then_loc: (173,28)-(173,32) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (173,26)-(173,30) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (173,0)-(173,4) = "case" - │ └── end_keyword_loc: (173,33)-(173,36) = "end" - ├── @ CaseMatchNode (location: (174,0)-(174,36)) + │ └── end_keyword_loc: (173,31)-(173,34) = "end" + ├── @ CaseMatchNode (location: (174,0)-(174,32)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (174,5)-(174,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -4061,38 +4764,34 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (174,10)-(174,32)) + │ │ └── @ InNode (location: (174,10)-(174,28)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (174,13)-(174,27)) - │ │ │ ├── if_keyword_loc: (174,21)-(174,23) = "if" + │ │ │ @ IfNode (location: (174,13)-(174,23)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (174,17)-(174,19) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (174,24)-(174,27)) + │ │ │ │ @ LocalVariableReadNode (location: (174,20)-(174,23)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (174,13)-(174,20)) + │ │ │ │ @ StatementsNode (location: (174,13)-(174,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ ArrayNode (location: (174,13)-(174,20)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── elements: (length: 1) - │ │ │ │ │ └── @ SymbolNode (location: (174,16)-(174,19)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding - │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── value_loc: (174,16)-(174,19) = "foo" - │ │ │ │ │ ├── closing_loc: ∅ - │ │ │ │ │ └── unescaped: "foo" - │ │ │ │ ├── opening_loc: (174,13)-(174,16) = "%I[" - │ │ │ │ └── closing_loc: (174,19)-(174,20) = "]" - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ NilNode (location: (174,13)-(174,16)) + │ │ │ │ └── flags: newline, static_literal + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (174,10)-(174,12) = "in" - │ │ └── then_loc: (174,28)-(174,32) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (174,24)-(174,28) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (174,0)-(174,4) = "case" - │ └── end_keyword_loc: (174,33)-(174,36) = "end" - ├── @ CaseMatchNode (location: (175,0)-(175,36)) + │ └── end_keyword_loc: (174,29)-(174,32) = "end" + ├── @ CaseMatchNode (location: (175,0)-(175,33)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (175,5)-(175,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -4105,38 +4804,34 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (175,10)-(175,32)) + │ │ └── @ InNode (location: (175,10)-(175,29)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (175,13)-(175,27)) - │ │ │ ├── if_keyword_loc: (175,21)-(175,23) = "if" + │ │ │ @ IfNode (location: (175,13)-(175,24)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (175,18)-(175,20) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (175,24)-(175,27)) + │ │ │ │ @ LocalVariableReadNode (location: (175,21)-(175,24)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (175,13)-(175,20)) + │ │ │ │ @ StatementsNode (location: (175,13)-(175,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ ArrayNode (location: (175,13)-(175,20)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── elements: (length: 1) - │ │ │ │ │ └── @ StringNode (location: (175,16)-(175,19)) - │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── content_loc: (175,16)-(175,19) = "foo" - │ │ │ │ │ ├── closing_loc: ∅ - │ │ │ │ │ └── unescaped: "foo" - │ │ │ │ ├── opening_loc: (175,13)-(175,16) = "%w[" - │ │ │ │ └── closing_loc: (175,19)-(175,20) = "]" - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ SelfNode (location: (175,13)-(175,17)) + │ │ │ │ └── flags: newline + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (175,10)-(175,12) = "in" - │ │ └── then_loc: (175,28)-(175,32) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (175,25)-(175,29) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (175,0)-(175,4) = "case" - │ └── end_keyword_loc: (175,33)-(175,36) = "end" - ├── @ CaseMatchNode (location: (176,0)-(176,36)) + │ └── end_keyword_loc: (175,30)-(175,33) = "end" + ├── @ CaseMatchNode (location: (176,0)-(176,33)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (176,5)-(176,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -4149,38 +4844,34 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (176,10)-(176,32)) + │ │ └── @ InNode (location: (176,10)-(176,29)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (176,13)-(176,27)) - │ │ │ ├── if_keyword_loc: (176,21)-(176,23) = "if" + │ │ │ @ IfNode (location: (176,13)-(176,24)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (176,18)-(176,20) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (176,24)-(176,27)) + │ │ │ │ @ LocalVariableReadNode (location: (176,21)-(176,24)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (176,13)-(176,20)) + │ │ │ │ @ StatementsNode (location: (176,13)-(176,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ ArrayNode (location: (176,13)-(176,20)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── elements: (length: 1) - │ │ │ │ │ └── @ StringNode (location: (176,16)-(176,19)) - │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── content_loc: (176,16)-(176,19) = "foo" - │ │ │ │ │ ├── closing_loc: ∅ - │ │ │ │ │ └── unescaped: "foo" - │ │ │ │ ├── opening_loc: (176,13)-(176,16) = "%W[" - │ │ │ │ └── closing_loc: (176,19)-(176,20) = "]" - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ TrueNode (location: (176,13)-(176,17)) + │ │ │ │ └── flags: newline, static_literal + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (176,10)-(176,12) = "in" - │ │ └── then_loc: (176,28)-(176,32) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (176,25)-(176,29) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (176,0)-(176,4) = "case" - │ └── end_keyword_loc: (176,33)-(176,36) = "end" - ├── @ CaseMatchNode (location: (177,0)-(177,36)) + │ └── end_keyword_loc: (176,30)-(176,33) = "end" + ├── @ CaseMatchNode (location: (177,0)-(177,34)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (177,5)-(177,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -4193,33 +4884,34 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (177,10)-(177,32)) + │ │ └── @ InNode (location: (177,10)-(177,30)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (177,13)-(177,27)) - │ │ │ ├── if_keyword_loc: (177,21)-(177,23) = "if" + │ │ │ @ IfNode (location: (177,13)-(177,25)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (177,19)-(177,21) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (177,24)-(177,27)) + │ │ │ │ @ LocalVariableReadNode (location: (177,22)-(177,25)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (177,13)-(177,20)) + │ │ │ │ @ StatementsNode (location: (177,13)-(177,18)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ StringNode (location: (177,13)-(177,20)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (177,13)-(177,16) = "%q[" - │ │ │ │ ├── content_loc: (177,16)-(177,19) = "foo" - │ │ │ │ ├── closing_loc: (177,19)-(177,20) = "]" - │ │ │ │ └── unescaped: "foo" - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ FalseNode (location: (177,13)-(177,18)) + │ │ │ │ └── flags: newline, static_literal + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (177,10)-(177,12) = "in" - │ │ └── then_loc: (177,28)-(177,32) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (177,26)-(177,30) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (177,0)-(177,4) = "case" - │ └── end_keyword_loc: (177,33)-(177,36) = "end" - ├── @ CaseMatchNode (location: (178,0)-(178,36)) + │ └── end_keyword_loc: (177,31)-(177,34) = "end" + ├── @ CaseMatchNode (location: (178,0)-(178,37)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (178,5)-(178,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -4232,33 +4924,35 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (178,10)-(178,32)) + │ │ └── @ InNode (location: (178,10)-(178,33)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (178,13)-(178,27)) - │ │ │ ├── if_keyword_loc: (178,21)-(178,23) = "if" + │ │ │ @ IfNode (location: (178,13)-(178,28)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (178,22)-(178,24) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (178,24)-(178,27)) + │ │ │ │ @ LocalVariableReadNode (location: (178,25)-(178,28)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (178,13)-(178,20)) + │ │ │ │ @ StatementsNode (location: (178,13)-(178,21)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ StringNode (location: (178,13)-(178,20)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (178,13)-(178,16) = "%Q[" - │ │ │ │ ├── content_loc: (178,16)-(178,19) = "foo" - │ │ │ │ ├── closing_loc: (178,19)-(178,20) = "]" - │ │ │ │ └── unescaped: "foo" - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ SourceFileNode (location: (178,13)-(178,21)) + │ │ │ │ ├── flags: newline + │ │ │ │ └── filepath: "patterns.txt" + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (178,10)-(178,12) = "in" - │ │ └── then_loc: (178,28)-(178,32) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (178,29)-(178,33) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (178,0)-(178,4) = "case" - │ └── end_keyword_loc: (178,33)-(178,36) = "end" - ├── @ CaseMatchNode (location: (179,0)-(179,34)) + │ └── end_keyword_loc: (178,34)-(178,37) = "end" + ├── @ CaseMatchNode (location: (179,0)-(179,37)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (179,5)-(179,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -4271,33 +4965,34 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (179,10)-(179,30)) + │ │ └── @ InNode (location: (179,10)-(179,33)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (179,13)-(179,25)) - │ │ │ ├── if_keyword_loc: (179,19)-(179,21) = "if" + │ │ │ @ IfNode (location: (179,13)-(179,28)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (179,22)-(179,24) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (179,22)-(179,25)) + │ │ │ │ @ LocalVariableReadNode (location: (179,25)-(179,28)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (179,13)-(179,18)) + │ │ │ │ @ StatementsNode (location: (179,13)-(179,21)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ StringNode (location: (179,13)-(179,18)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (179,13)-(179,14) = "\"" - │ │ │ │ ├── content_loc: (179,14)-(179,17) = "foo" - │ │ │ │ ├── closing_loc: (179,17)-(179,18) = "\"" - │ │ │ │ └── unescaped: "foo" - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ SourceLineNode (location: (179,13)-(179,21)) + │ │ │ │ └── flags: newline, static_literal + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (179,10)-(179,12) = "in" - │ │ └── then_loc: (179,26)-(179,30) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (179,29)-(179,33) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (179,0)-(179,4) = "case" - │ └── end_keyword_loc: (179,31)-(179,34) = "end" - ├── @ CaseMatchNode (location: (180,0)-(180,32)) + │ └── end_keyword_loc: (179,34)-(179,37) = "end" + ├── @ CaseMatchNode (location: (180,0)-(180,41)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (180,5)-(180,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -4310,28 +5005,34 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (180,10)-(180,28)) + │ │ └── @ InNode (location: (180,10)-(180,37)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (180,13)-(180,23)) - │ │ │ ├── if_keyword_loc: (180,17)-(180,19) = "if" + │ │ │ @ IfNode (location: (180,13)-(180,32)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (180,26)-(180,28) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (180,20)-(180,23)) + │ │ │ │ @ LocalVariableReadNode (location: (180,29)-(180,32)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (180,13)-(180,16)) + │ │ │ │ @ StatementsNode (location: (180,13)-(180,25)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ NilNode (location: (180,13)-(180,16)) - │ │ │ ├── consequent: ∅ + │ │ │ │ └── @ SourceEncodingNode (location: (180,13)-(180,25)) + │ │ │ │ └── flags: newline, static_literal + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── in_loc: (180,10)-(180,12) = "in" - │ │ └── then_loc: (180,24)-(180,28) = "then" - │ ├── consequent: ∅ + │ │ └── then_loc: (180,33)-(180,37) = "then" + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (180,0)-(180,4) = "case" - │ └── end_keyword_loc: (180,29)-(180,32) = "end" - ├── @ CaseMatchNode (location: (181,0)-(181,33)) + │ └── end_keyword_loc: (180,38)-(180,41) = "end" + ├── @ CaseMatchNode (location: (181,0)-(181,39)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (181,5)-(181,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -4344,572 +5045,526 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (181,10)-(181,29)) + │ │ └── @ InNode (location: (181,10)-(181,35)) + │ │ ├── flags: ∅ │ │ ├── pattern: - │ │ │ @ IfNode (location: (181,13)-(181,24)) - │ │ │ ├── if_keyword_loc: (181,18)-(181,20) = "if" + │ │ │ @ IfNode (location: (181,13)-(181,30)) + │ │ │ ├── flags: newline + │ │ │ ├── if_keyword_loc: (181,24)-(181,26) = "if" │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (181,21)-(181,24)) + │ │ │ │ @ LocalVariableReadNode (location: (181,27)-(181,30)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 0 │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (181,13)-(181,17)) + │ │ │ │ @ StatementsNode (location: (181,13)-(181,23)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ SelfNode (location: (181,13)-(181,17)) - │ │ │ ├── consequent: ∅ - │ │ │ └── end_keyword_loc: ∅ - │ │ ├── statements: ∅ - │ │ ├── in_loc: (181,10)-(181,12) = "in" - │ │ └── then_loc: (181,25)-(181,29) = "then" - │ ├── consequent: ∅ - │ ├── case_keyword_loc: (181,0)-(181,4) = "case" - │ └── end_keyword_loc: (181,30)-(181,33) = "end" - ├── @ CaseMatchNode (location: (182,0)-(182,33)) - │ ├── predicate: - │ │ @ CallNode (location: (182,5)-(182,8)) - │ │ ├── flags: variable_call, ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :foo - │ │ ├── message_loc: (182,5)-(182,8) = "foo" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: ∅ - │ │ ├── closing_loc: ∅ - │ │ └── block: ∅ - │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (182,10)-(182,29)) - │ │ ├── pattern: - │ │ │ @ IfNode (location: (182,13)-(182,24)) - │ │ │ ├── if_keyword_loc: (182,18)-(182,20) = "if" - │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (182,21)-(182,24)) - │ │ │ │ ├── name: :baz - │ │ │ │ └── depth: 0 - │ │ │ ├── then_keyword_loc: ∅ - │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (182,13)-(182,17)) - │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ TrueNode (location: (182,13)-(182,17)) - │ │ │ ├── consequent: ∅ - │ │ │ └── end_keyword_loc: ∅ - │ │ ├── statements: ∅ - │ │ ├── in_loc: (182,10)-(182,12) = "in" - │ │ └── then_loc: (182,25)-(182,29) = "then" - │ ├── consequent: ∅ - │ ├── case_keyword_loc: (182,0)-(182,4) = "case" - │ └── end_keyword_loc: (182,30)-(182,33) = "end" - ├── @ CaseMatchNode (location: (183,0)-(183,34)) - │ ├── predicate: - │ │ @ CallNode (location: (183,5)-(183,8)) - │ │ ├── flags: variable_call, ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :foo - │ │ ├── message_loc: (183,5)-(183,8) = "foo" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: ∅ - │ │ ├── closing_loc: ∅ - │ │ └── block: ∅ - │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (183,10)-(183,30)) - │ │ ├── pattern: - │ │ │ @ IfNode (location: (183,13)-(183,25)) - │ │ │ ├── if_keyword_loc: (183,19)-(183,21) = "if" - │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (183,22)-(183,25)) - │ │ │ │ ├── name: :baz - │ │ │ │ └── depth: 0 - │ │ │ ├── then_keyword_loc: ∅ - │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (183,13)-(183,18)) - │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ FalseNode (location: (183,13)-(183,18)) - │ │ │ ├── consequent: ∅ - │ │ │ └── end_keyword_loc: ∅ - │ │ ├── statements: ∅ - │ │ ├── in_loc: (183,10)-(183,12) = "in" - │ │ └── then_loc: (183,26)-(183,30) = "then" - │ ├── consequent: ∅ - │ ├── case_keyword_loc: (183,0)-(183,4) = "case" - │ └── end_keyword_loc: (183,31)-(183,34) = "end" - ├── @ CaseMatchNode (location: (184,0)-(184,37)) - │ ├── predicate: - │ │ @ CallNode (location: (184,5)-(184,8)) - │ │ ├── flags: variable_call, ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :foo - │ │ ├── message_loc: (184,5)-(184,8) = "foo" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: ∅ - │ │ ├── closing_loc: ∅ - │ │ └── block: ∅ - │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (184,10)-(184,33)) - │ │ ├── pattern: - │ │ │ @ IfNode (location: (184,13)-(184,28)) - │ │ │ ├── if_keyword_loc: (184,22)-(184,24) = "if" - │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (184,25)-(184,28)) - │ │ │ │ ├── name: :baz - │ │ │ │ └── depth: 0 - │ │ │ ├── then_keyword_loc: ∅ - │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (184,13)-(184,21)) - │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ SourceFileNode (location: (184,13)-(184,21)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ └── filepath: "patterns.txt" - │ │ │ ├── consequent: ∅ - │ │ │ └── end_keyword_loc: ∅ - │ │ ├── statements: ∅ - │ │ ├── in_loc: (184,10)-(184,12) = "in" - │ │ └── then_loc: (184,29)-(184,33) = "then" - │ ├── consequent: ∅ - │ ├── case_keyword_loc: (184,0)-(184,4) = "case" - │ └── end_keyword_loc: (184,34)-(184,37) = "end" - ├── @ CaseMatchNode (location: (185,0)-(185,37)) - │ ├── predicate: - │ │ @ CallNode (location: (185,5)-(185,8)) - │ │ ├── flags: variable_call, ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :foo - │ │ ├── message_loc: (185,5)-(185,8) = "foo" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: ∅ - │ │ ├── closing_loc: ∅ - │ │ └── block: ∅ - │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (185,10)-(185,33)) - │ │ ├── pattern: - │ │ │ @ IfNode (location: (185,13)-(185,28)) - │ │ │ ├── if_keyword_loc: (185,22)-(185,24) = "if" - │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (185,25)-(185,28)) - │ │ │ │ ├── name: :baz - │ │ │ │ └── depth: 0 - │ │ │ ├── then_keyword_loc: ∅ - │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (185,13)-(185,21)) - │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ SourceLineNode (location: (185,13)-(185,21)) - │ │ │ ├── consequent: ∅ - │ │ │ └── end_keyword_loc: ∅ - │ │ ├── statements: ∅ - │ │ ├── in_loc: (185,10)-(185,12) = "in" - │ │ └── then_loc: (185,29)-(185,33) = "then" - │ ├── consequent: ∅ - │ ├── case_keyword_loc: (185,0)-(185,4) = "case" - │ └── end_keyword_loc: (185,34)-(185,37) = "end" - ├── @ CaseMatchNode (location: (186,0)-(186,41)) - │ ├── predicate: - │ │ @ CallNode (location: (186,5)-(186,8)) - │ │ ├── flags: variable_call, ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :foo - │ │ ├── message_loc: (186,5)-(186,8) = "foo" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: ∅ - │ │ ├── closing_loc: ∅ - │ │ └── block: ∅ - │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (186,10)-(186,37)) - │ │ ├── pattern: - │ │ │ @ IfNode (location: (186,13)-(186,32)) - │ │ │ ├── if_keyword_loc: (186,26)-(186,28) = "if" - │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (186,29)-(186,32)) - │ │ │ │ ├── name: :baz - │ │ │ │ └── depth: 0 - │ │ │ ├── then_keyword_loc: ∅ - │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (186,13)-(186,25)) - │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ SourceEncodingNode (location: (186,13)-(186,25)) - │ │ │ ├── consequent: ∅ - │ │ │ └── end_keyword_loc: ∅ - │ │ ├── statements: ∅ - │ │ ├── in_loc: (186,10)-(186,12) = "in" - │ │ └── then_loc: (186,33)-(186,37) = "then" - │ ├── consequent: ∅ - │ ├── case_keyword_loc: (186,0)-(186,4) = "case" - │ └── end_keyword_loc: (186,38)-(186,41) = "end" - ├── @ CaseMatchNode (location: (187,0)-(187,39)) - │ ├── predicate: - │ │ @ CallNode (location: (187,5)-(187,8)) - │ │ ├── flags: variable_call, ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :foo - │ │ ├── message_loc: (187,5)-(187,8) = "foo" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: ∅ - │ │ ├── closing_loc: ∅ - │ │ └── block: ∅ - │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (187,10)-(187,35)) - │ │ ├── pattern: - │ │ │ @ IfNode (location: (187,13)-(187,30)) - │ │ │ ├── if_keyword_loc: (187,24)-(187,26) = "if" - │ │ │ ├── predicate: - │ │ │ │ @ LocalVariableReadNode (location: (187,27)-(187,30)) - │ │ │ │ ├── name: :baz - │ │ │ │ └── depth: 0 - │ │ │ ├── then_keyword_loc: ∅ - │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (187,13)-(187,23)) - │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ LambdaNode (location: (187,13)-(187,23)) + │ │ │ │ └── @ LambdaNode (location: (181,13)-(181,23)) + │ │ │ │ ├── flags: newline │ │ │ │ ├── locals: [] - │ │ │ │ ├── operator_loc: (187,13)-(187,15) = "->" - │ │ │ │ ├── opening_loc: (187,16)-(187,17) = "{" - │ │ │ │ ├── closing_loc: (187,22)-(187,23) = "}" + │ │ │ │ ├── operator_loc: (181,13)-(181,15) = "->" + │ │ │ │ ├── opening_loc: (181,16)-(181,17) = "{" + │ │ │ │ ├── closing_loc: (181,22)-(181,23) = "}" │ │ │ │ ├── parameters: ∅ │ │ │ │ └── body: - │ │ │ │ @ StatementsNode (location: (187,18)-(187,21)) + │ │ │ │ @ StatementsNode (location: (181,18)-(181,21)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ LocalVariableReadNode (location: (187,18)-(187,21)) + │ │ │ │ └── @ LocalVariableReadNode (location: (181,18)-(181,21)) + │ │ │ │ ├── flags: newline │ │ │ │ ├── name: :bar │ │ │ │ └── depth: 1 - │ │ │ ├── consequent: ∅ + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ - │ │ ├── in_loc: (187,10)-(187,12) = "in" - │ │ └── then_loc: (187,31)-(187,35) = "then" - │ ├── consequent: ∅ - │ ├── case_keyword_loc: (187,0)-(187,4) = "case" - │ └── end_keyword_loc: (187,36)-(187,39) = "end" - ├── @ IfNode (location: (189,0)-(190,3)) - │ ├── if_keyword_loc: (189,0)-(189,2) = "if" + │ │ ├── in_loc: (181,10)-(181,12) = "in" + │ │ └── then_loc: (181,31)-(181,35) = "then" + │ ├── else_clause: ∅ + │ ├── case_keyword_loc: (181,0)-(181,4) = "case" + │ └── end_keyword_loc: (181,36)-(181,39) = "end" + ├── @ IfNode (location: (183,0)-(184,3)) + │ ├── flags: newline + │ ├── if_keyword_loc: (183,0)-(183,2) = "if" │ ├── predicate: - │ │ @ MatchPredicateNode (location: (189,3)-(189,10)) + │ │ @ MatchPredicateNode (location: (183,3)-(183,10)) + │ │ ├── flags: ∅ │ │ ├── value: - │ │ │ @ CallNode (location: (189,3)-(189,4)) + │ │ │ @ CallNode (location: (183,3)-(183,4)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :a - │ │ │ ├── message_loc: (189,3)-(189,4) = "a" + │ │ │ ├── message_loc: (183,3)-(183,4) = "a" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ ├── pattern: - │ │ │ @ ArrayPatternNode (location: (189,8)-(189,10)) + │ │ │ @ ArrayPatternNode (location: (183,8)-(183,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── requireds: (length: 0) │ │ │ ├── rest: ∅ │ │ │ ├── posts: (length: 0) - │ │ │ ├── opening_loc: (189,8)-(189,9) = "[" - │ │ │ └── closing_loc: (189,9)-(189,10) = "]" - │ │ └── operator_loc: (189,5)-(189,7) = "in" + │ │ │ ├── opening_loc: (183,8)-(183,9) = "[" + │ │ │ └── closing_loc: (183,9)-(183,10) = "]" + │ │ └── operator_loc: (183,5)-(183,7) = "in" │ ├── then_keyword_loc: ∅ │ ├── statements: ∅ - │ ├── consequent: ∅ - │ └── end_keyword_loc: (190,0)-(190,3) = "end" - ├── @ MatchRequiredNode (location: (192,0)-(194,1)) + │ ├── subsequent: ∅ + │ └── end_keyword_loc: (184,0)-(184,3) = "end" + ├── @ MatchRequiredNode (location: (186,0)-(188,1)) + │ ├── flags: newline │ ├── value: - │ │ @ CallNode (location: (192,0)-(192,1)) + │ │ @ CallNode (location: (186,0)-(186,1)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a - │ │ ├── message_loc: (192,0)-(192,1) = "a" + │ │ ├── message_loc: (186,0)-(186,1) = "a" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ ArrayPatternNode (location: (192,5)-(194,1)) + │ │ @ ArrayPatternNode (location: (186,5)-(188,1)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 1) - │ │ │ └── @ LocalVariableTargetNode (location: (193,2)-(193,3)) + │ │ │ └── @ LocalVariableTargetNode (location: (187,2)-(187,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ └── depth: 0 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) - │ │ ├── opening_loc: (192,5)-(192,6) = "[" - │ │ └── closing_loc: (194,0)-(194,1) = "]" - │ └── operator_loc: (192,2)-(192,4) = "=>" - ├── @ MatchPredicateNode (location: (196,0)-(200,1)) + │ │ ├── opening_loc: (186,5)-(186,6) = "[" + │ │ └── closing_loc: (188,0)-(188,1) = "]" + │ └── operator_loc: (186,2)-(186,4) = "=>" + ├── @ MatchPredicateNode (location: (190,0)-(194,1)) + │ ├── flags: newline │ ├── value: - │ │ @ CallNode (location: (196,0)-(196,3)) + │ │ @ CallNode (location: (190,0)-(190,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (196,0)-(196,3) = "foo" + │ │ ├── message_loc: (190,0)-(190,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ HashPatternNode (location: (196,7)-(200,1)) + │ │ @ HashPatternNode (location: (190,7)-(194,1)) + │ │ ├── flags: ∅ │ │ ├── constant: - │ │ │ @ ConstantReadNode (location: (196,7)-(196,8)) + │ │ │ @ ConstantReadNode (location: (190,7)-(190,8)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── elements: (length: 1) - │ │ │ └── @ AssocNode (location: (197,2)-(199,3)) + │ │ │ └── @ AssocNode (location: (191,2)-(193,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (197,2)-(197,6)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ @ SymbolNode (location: (191,2)-(191,6)) + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── value_loc: (197,2)-(197,5) = "bar" - │ │ │ │ ├── closing_loc: (197,5)-(197,6) = ":" + │ │ │ │ ├── value_loc: (191,2)-(191,5) = "bar" + │ │ │ │ ├── closing_loc: (191,5)-(191,6) = ":" │ │ │ │ └── unescaped: "bar" │ │ │ ├── value: - │ │ │ │ @ HashPatternNode (location: (197,7)-(199,3)) + │ │ │ │ @ HashPatternNode (location: (191,7)-(193,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: - │ │ │ │ │ @ ConstantReadNode (location: (197,7)-(197,8)) + │ │ │ │ │ @ ConstantReadNode (location: (191,7)-(191,8)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :B │ │ │ │ ├── elements: (length: 1) - │ │ │ │ │ └── @ AssocNode (location: (198,4)-(198,12)) + │ │ │ │ │ └── @ AssocNode (location: (192,4)-(192,12)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── key: - │ │ │ │ │ │ @ SymbolNode (location: (198,4)-(198,10)) - │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ │ @ SymbolNode (location: (192,4)-(192,10)) + │ │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ │ ├── value_loc: (198,4)-(198,9) = "value" - │ │ │ │ │ │ ├── closing_loc: (198,9)-(198,10) = ":" + │ │ │ │ │ │ ├── value_loc: (192,4)-(192,9) = "value" + │ │ │ │ │ │ ├── closing_loc: (192,9)-(192,10) = ":" │ │ │ │ │ │ └── unescaped: "value" │ │ │ │ │ ├── value: - │ │ │ │ │ │ @ LocalVariableTargetNode (location: (198,11)-(198,12)) + │ │ │ │ │ │ @ LocalVariableTargetNode (location: (192,11)-(192,12)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── name: :a │ │ │ │ │ │ └── depth: 0 │ │ │ │ │ └── operator_loc: ∅ │ │ │ │ ├── rest: ∅ - │ │ │ │ ├── opening_loc: (197,8)-(197,9) = "[" - │ │ │ │ └── closing_loc: (199,2)-(199,3) = "]" + │ │ │ │ ├── opening_loc: (191,8)-(191,9) = "[" + │ │ │ │ └── closing_loc: (193,2)-(193,3) = "]" │ │ │ └── operator_loc: ∅ │ │ ├── rest: ∅ - │ │ ├── opening_loc: (196,8)-(196,9) = "[" - │ │ └── closing_loc: (200,0)-(200,1) = "]" - │ └── operator_loc: (196,4)-(196,6) = "in" - ├── @ MatchPredicateNode (location: (202,0)-(202,17)) + │ │ ├── opening_loc: (190,8)-(190,9) = "[" + │ │ └── closing_loc: (194,0)-(194,1) = "]" + │ └── operator_loc: (190,4)-(190,6) = "in" + ├── @ MatchPredicateNode (location: (196,0)-(196,17)) + │ ├── flags: newline │ ├── value: - │ │ @ CallNode (location: (202,0)-(202,3)) + │ │ @ CallNode (location: (196,0)-(196,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (202,0)-(202,3) = "foo" + │ │ ├── message_loc: (196,0)-(196,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ CapturePatternNode (location: (202,7)-(202,17)) + │ │ @ CapturePatternNode (location: (196,7)-(196,17)) + │ │ ├── flags: ∅ │ │ ├── value: - │ │ │ @ LocalVariableTargetNode (location: (202,7)-(202,10)) + │ │ │ @ LocalVariableTargetNode (location: (196,7)-(196,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── target: - │ │ │ @ LocalVariableTargetNode (location: (202,14)-(202,17)) + │ │ │ @ LocalVariableTargetNode (location: (196,14)-(196,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ └── depth: 0 - │ │ └── operator_loc: (202,11)-(202,13) = "=>" - │ └── operator_loc: (202,4)-(202,6) = "in" - ├── @ MatchRequiredNode (location: (203,0)-(203,17)) + │ │ └── operator_loc: (196,11)-(196,13) = "=>" + │ └── operator_loc: (196,4)-(196,6) = "in" + ├── @ MatchRequiredNode (location: (197,0)-(197,17)) + │ ├── flags: newline │ ├── value: - │ │ @ CallNode (location: (203,0)-(203,3)) + │ │ @ CallNode (location: (197,0)-(197,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (203,0)-(203,3) = "foo" + │ │ ├── message_loc: (197,0)-(197,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── pattern: - │ │ @ CapturePatternNode (location: (203,7)-(203,17)) + │ │ @ CapturePatternNode (location: (197,7)-(197,17)) + │ │ ├── flags: ∅ │ │ ├── value: - │ │ │ @ LocalVariableTargetNode (location: (203,7)-(203,10)) + │ │ │ @ LocalVariableTargetNode (location: (197,7)-(197,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── target: - │ │ │ @ LocalVariableTargetNode (location: (203,14)-(203,17)) + │ │ │ @ LocalVariableTargetNode (location: (197,14)-(197,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ └── depth: 0 - │ │ └── operator_loc: (203,11)-(203,13) = "=>" - │ └── operator_loc: (203,4)-(203,6) = "=>" - ├── @ MultiWriteNode (location: (205,0)-(205,20)) + │ │ └── operator_loc: (197,11)-(197,13) = "=>" + │ └── operator_loc: (197,4)-(197,6) = "=>" + ├── @ MultiWriteNode (location: (199,0)-(199,20)) + │ ├── flags: newline │ ├── lefts: (length: 3) - │ │ ├── @ LocalVariableTargetNode (location: (205,0)-(205,3)) + │ │ ├── @ LocalVariableTargetNode (location: (199,0)-(199,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :foo │ │ │ └── depth: 0 - │ │ ├── @ LocalVariableTargetNode (location: (205,5)-(205,8)) + │ │ ├── @ LocalVariableTargetNode (location: (199,5)-(199,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 - │ │ └── @ LocalVariableTargetNode (location: (205,10)-(205,13)) + │ │ └── @ LocalVariableTargetNode (location: (199,10)-(199,13)) + │ │ ├── flags: ∅ │ │ ├── name: :baz │ │ └── depth: 0 │ ├── rest: ∅ │ ├── rights: (length: 0) │ ├── lparen_loc: ∅ │ ├── rparen_loc: ∅ - │ ├── operator_loc: (205,14)-(205,15) = "=" + │ ├── operator_loc: (199,14)-(199,15) = "=" │ └── value: - │ @ ArrayNode (location: (205,16)-(205,20)) - │ ├── flags: ∅ + │ @ ArrayNode (location: (199,16)-(199,20)) + │ ├── flags: static_literal │ ├── elements: (length: 2) - │ │ ├── @ IntegerNode (location: (205,16)-(205,17)) - │ │ │ ├── flags: decimal + │ │ ├── @ IntegerNode (location: (199,16)-(199,17)) + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 - │ │ └── @ IntegerNode (location: (205,19)-(205,20)) - │ │ ├── flags: decimal + │ │ └── @ IntegerNode (location: (199,19)-(199,20)) + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: ∅ │ └── closing_loc: ∅ - ├── @ CallNode (location: (206,0)-(208,3)) - │ ├── flags: ignore_visibility + ├── @ CallNode (location: (200,0)-(202,3)) + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (206,0)-(206,3) = "foo" + │ ├── message_loc: (200,0)-(200,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: - │ @ BlockNode (location: (206,4)-(208,3)) + │ @ BlockNode (location: (200,4)-(202,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: - │ │ @ StatementsNode (location: (207,2)-(207,29)) + │ │ @ StatementsNode (location: (201,2)-(201,29)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) - │ │ └── @ MatchRequiredNode (location: (207,2)-(207,29)) + │ │ └── @ MatchRequiredNode (location: (201,2)-(201,29)) + │ │ ├── flags: newline │ │ ├── value: - │ │ │ @ ArrayNode (location: (207,2)-(207,8)) - │ │ │ ├── flags: ∅ + │ │ │ @ ArrayNode (location: (201,2)-(201,8)) + │ │ │ ├── flags: static_literal │ │ │ ├── elements: (length: 2) - │ │ │ │ ├── @ IntegerNode (location: (207,3)-(207,4)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ ├── @ IntegerNode (location: (201,3)-(201,4)) + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 - │ │ │ │ └── @ IntegerNode (location: (207,6)-(207,7)) - │ │ │ │ ├── flags: decimal + │ │ │ │ └── @ IntegerNode (location: (201,6)-(201,7)) + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 - │ │ │ ├── opening_loc: (207,2)-(207,3) = "[" - │ │ │ └── closing_loc: (207,7)-(207,8) = "]" + │ │ │ ├── opening_loc: (201,2)-(201,3) = "[" + │ │ │ └── closing_loc: (201,7)-(201,8) = "]" │ │ ├── pattern: - │ │ │ @ CapturePatternNode (location: (207,12)-(207,29)) + │ │ │ @ CapturePatternNode (location: (201,12)-(201,29)) + │ │ │ ├── flags: ∅ │ │ │ ├── value: - │ │ │ │ @ ArrayPatternNode (location: (207,12)-(207,22)) + │ │ │ │ @ ArrayPatternNode (location: (201,12)-(201,22)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── requireds: (length: 2) - │ │ │ │ │ ├── @ LocalVariableTargetNode (location: (207,13)-(207,16)) + │ │ │ │ │ ├── @ LocalVariableTargetNode (location: (201,13)-(201,16)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── name: :foo │ │ │ │ │ │ └── depth: 1 - │ │ │ │ │ └── @ LocalVariableTargetNode (location: (207,18)-(207,21)) + │ │ │ │ │ └── @ LocalVariableTargetNode (location: (201,18)-(201,21)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :bar │ │ │ │ │ └── depth: 1 │ │ │ │ ├── rest: ∅ │ │ │ │ ├── posts: (length: 0) - │ │ │ │ ├── opening_loc: (207,12)-(207,13) = "[" - │ │ │ │ └── closing_loc: (207,21)-(207,22) = "]" + │ │ │ │ ├── opening_loc: (201,12)-(201,13) = "[" + │ │ │ │ └── closing_loc: (201,21)-(201,22) = "]" │ │ │ ├── target: - │ │ │ │ @ LocalVariableTargetNode (location: (207,26)-(207,29)) + │ │ │ │ @ LocalVariableTargetNode (location: (201,26)-(201,29)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ └── depth: 1 - │ │ │ └── operator_loc: (207,23)-(207,25) = "=>" - │ │ └── operator_loc: (207,9)-(207,11) = "=>" - │ ├── opening_loc: (206,4)-(206,6) = "do" - │ └── closing_loc: (208,0)-(208,3) = "end" - ├── @ MatchRequiredNode (location: (210,0)-(210,19)) + │ │ │ └── operator_loc: (201,23)-(201,25) = "=>" + │ │ └── operator_loc: (201,9)-(201,11) = "=>" + │ ├── opening_loc: (200,4)-(200,6) = "do" + │ └── closing_loc: (202,0)-(202,3) = "end" + ├── @ MatchRequiredNode (location: (204,0)-(204,19)) + │ ├── flags: newline │ ├── value: - │ │ @ LocalVariableReadNode (location: (210,0)-(210,3)) + │ │ @ LocalVariableReadNode (location: (204,0)-(204,3)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── depth: 0 │ ├── pattern: - │ │ @ ArrayPatternNode (location: (210,7)-(210,19)) + │ │ @ ArrayPatternNode (location: (204,7)-(204,19)) + │ │ ├── flags: ∅ │ │ ├── constant: - │ │ │ @ ConstantReadNode (location: (210,7)-(210,13)) + │ │ │ @ ConstantReadNode (location: (204,7)-(204,13)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Object │ │ ├── requireds: (length: 1) - │ │ │ └── @ HashPatternNode (location: (210,14)-(210,18)) + │ │ │ └── @ HashPatternNode (location: (204,14)-(204,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── elements: (length: 1) - │ │ │ │ └── @ AssocNode (location: (210,15)-(210,17)) + │ │ │ │ └── @ AssocNode (location: (204,15)-(204,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── key: - │ │ │ │ │ @ SymbolNode (location: (210,15)-(210,17)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ @ SymbolNode (location: (204,15)-(204,17)) + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── value_loc: (210,15)-(210,16) = "x" - │ │ │ │ │ ├── closing_loc: (210,16)-(210,17) = ":" + │ │ │ │ │ ├── value_loc: (204,15)-(204,16) = "x" + │ │ │ │ │ ├── closing_loc: (204,16)-(204,17) = ":" │ │ │ │ │ └── unescaped: "x" │ │ │ │ ├── value: - │ │ │ │ │ @ ImplicitNode (location: (210,15)-(210,16)) + │ │ │ │ │ @ ImplicitNode (location: (204,15)-(204,16)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── value: - │ │ │ │ │ @ LocalVariableTargetNode (location: (210,15)-(210,16)) + │ │ │ │ │ @ LocalVariableTargetNode (location: (204,15)-(204,16)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :x │ │ │ │ │ └── depth: 0 │ │ │ │ └── operator_loc: ∅ │ │ │ ├── rest: ∅ - │ │ │ ├── opening_loc: (210,14)-(210,15) = "{" - │ │ │ └── closing_loc: (210,17)-(210,18) = "}" + │ │ │ ├── opening_loc: (204,14)-(204,15) = "{" + │ │ │ └── closing_loc: (204,17)-(204,18) = "}" │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) - │ │ ├── opening_loc: (210,13)-(210,14) = "[" - │ │ └── closing_loc: (210,18)-(210,19) = "]" - │ └── operator_loc: (210,4)-(210,6) = "=>" - ├── @ CallNode (location: (212,0)-(212,19)) - │ ├── flags: ∅ + │ │ ├── opening_loc: (204,13)-(204,14) = "[" + │ │ └── closing_loc: (204,18)-(204,19) = "]" + │ └── operator_loc: (204,4)-(204,6) = "=>" + ├── @ CallNode (location: (206,0)-(206,19)) + │ ├── flags: newline │ ├── receiver: - │ │ @ IntegerNode (location: (212,0)-(212,1)) - │ │ ├── flags: decimal + │ │ @ IntegerNode (location: (206,0)-(206,1)) + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 - │ ├── call_operator_loc: (212,1)-(212,2) = "." + │ ├── call_operator_loc: (206,1)-(206,2) = "." │ ├── name: :then - │ ├── message_loc: (212,2)-(212,6) = "then" + │ ├── message_loc: (206,2)-(206,6) = "then" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: - │ @ BlockNode (location: (212,7)-(212,19)) + │ @ BlockNode (location: (206,7)-(206,19)) + │ ├── flags: ∅ │ ├── locals: [:_1] │ ├── parameters: - │ │ @ NumberedParametersNode (location: (212,7)-(212,19)) + │ │ @ NumberedParametersNode (location: (206,7)-(206,19)) + │ │ ├── flags: ∅ │ │ └── maximum: 1 │ ├── body: - │ │ @ StatementsNode (location: (212,9)-(212,17)) + │ │ @ StatementsNode (location: (206,9)-(206,17)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) - │ │ └── @ MatchPredicateNode (location: (212,9)-(212,17)) + │ │ └── @ MatchPredicateNode (location: (206,9)-(206,17)) + │ │ ├── flags: newline │ │ ├── value: - │ │ │ @ IntegerNode (location: (212,9)-(212,10)) - │ │ │ ├── flags: decimal + │ │ │ @ IntegerNode (location: (206,9)-(206,10)) + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── pattern: - │ │ │ @ PinnedVariableNode (location: (212,14)-(212,17)) + │ │ │ @ PinnedVariableNode (location: (206,14)-(206,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── variable: - │ │ │ │ @ LocalVariableReadNode (location: (212,15)-(212,17)) + │ │ │ │ @ LocalVariableReadNode (location: (206,15)-(206,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :_1 │ │ │ │ └── depth: 0 - │ │ │ └── operator_loc: (212,14)-(212,15) = "^" - │ │ └── operator_loc: (212,11)-(212,13) = "in" - │ ├── opening_loc: (212,7)-(212,8) = "{" - │ └── closing_loc: (212,18)-(212,19) = "}" - └── @ MultiWriteNode (location: (214,0)-(217,5)) - ├── lefts: (length: 2) - │ ├── @ LocalVariableTargetNode (location: (215,2)-(215,3)) - │ │ ├── name: :a - │ │ └── depth: 0 - │ └── @ LocalVariableTargetNode (location: (216,2)-(216,3)) - │ ├── name: :b - │ └── depth: 0 - ├── rest: ∅ - ├── rights: (length: 0) - ├── lparen_loc: (214,0)-(214,1) = "(" - ├── rparen_loc: (217,0)-(217,1) = ")" - ├── operator_loc: (217,2)-(217,3) = "=" - └── value: - @ CallNode (location: (217,4)-(217,5)) - ├── flags: variable_call, ignore_visibility - ├── receiver: ∅ - ├── call_operator_loc: ∅ - ├── name: :c - ├── message_loc: (217,4)-(217,5) = "c" - ├── opening_loc: ∅ - ├── arguments: ∅ - ├── closing_loc: ∅ - └── block: ∅ + │ │ │ └── operator_loc: (206,14)-(206,15) = "^" + │ │ └── operator_loc: (206,11)-(206,13) = "in" + │ ├── opening_loc: (206,7)-(206,8) = "{" + │ └── closing_loc: (206,18)-(206,19) = "}" + ├── @ MultiWriteNode (location: (208,0)-(211,5)) + │ ├── flags: newline + │ ├── lefts: (length: 2) + │ │ ├── @ LocalVariableTargetNode (location: (209,2)-(209,3)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :a + │ │ │ └── depth: 0 + │ │ └── @ LocalVariableTargetNode (location: (210,2)-(210,3)) + │ │ ├── flags: ∅ + │ │ ├── name: :b + │ │ └── depth: 0 + │ ├── rest: ∅ + │ ├── rights: (length: 0) + │ ├── lparen_loc: (208,0)-(208,1) = "(" + │ ├── rparen_loc: (211,0)-(211,1) = ")" + │ ├── operator_loc: (211,2)-(211,3) = "=" + │ └── value: + │ @ CallNode (location: (211,4)-(211,5)) + │ ├── flags: variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :c + │ ├── message_loc: (211,4)-(211,5) = "c" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ CaseMatchNode (location: (213,0)-(213,25)) + │ ├── flags: newline + │ ├── predicate: + │ │ @ ParenthesesNode (location: (213,5)-(213,7)) + │ │ ├── flags: ∅ + │ │ ├── body: ∅ + │ │ ├── opening_loc: (213,5)-(213,6) = "(" + │ │ └── closing_loc: (213,6)-(213,7) = ")" + │ ├── conditions: (length: 1) + │ │ └── @ InNode (location: (213,9)-(213,20)) + │ │ ├── flags: ∅ + │ │ ├── pattern: + │ │ │ @ ArrayPatternNode (location: (213,12)-(213,20)) + │ │ │ ├── flags: ∅ + │ │ │ ├── constant: ∅ + │ │ │ ├── requireds: (length: 2) + │ │ │ │ ├── @ LocalVariableTargetNode (location: (213,13)-(213,15)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── name: :_a + │ │ │ │ │ └── depth: 0 + │ │ │ │ └── @ LocalVariableTargetNode (location: (213,17)-(213,19)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── name: :_a + │ │ │ │ └── depth: 0 + │ │ │ ├── rest: ∅ + │ │ │ ├── posts: (length: 0) + │ │ │ ├── opening_loc: (213,12)-(213,13) = "[" + │ │ │ └── closing_loc: (213,19)-(213,20) = "]" + │ │ ├── statements: ∅ + │ │ ├── in_loc: (213,9)-(213,11) = "in" + │ │ └── then_loc: ∅ + │ ├── else_clause: ∅ + │ ├── case_keyword_loc: (213,0)-(213,4) = "case" + │ └── end_keyword_loc: (213,22)-(213,25) = "end" + └── @ CaseMatchNode (location: (214,0)-(214,31)) + ├── flags: newline + ├── predicate: + │ @ ParenthesesNode (location: (214,5)-(214,7)) + │ ├── flags: ∅ + │ ├── body: ∅ + │ ├── opening_loc: (214,5)-(214,6) = "(" + │ └── closing_loc: (214,6)-(214,7) = ")" + ├── conditions: (length: 1) + │ └── @ InNode (location: (214,9)-(214,26)) + │ ├── flags: ∅ + │ ├── pattern: + │ │ @ ArrayPatternNode (location: (214,12)-(214,26)) + │ │ ├── flags: ∅ + │ │ ├── constant: ∅ + │ │ ├── requireds: (length: 2) + │ │ │ ├── @ HashPatternNode (location: (214,13)-(214,18)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── constant: ∅ + │ │ │ │ ├── elements: (length: 1) + │ │ │ │ │ └── @ AssocNode (location: (214,14)-(214,17)) + │ │ │ │ │ ├── flags: static_literal + │ │ │ │ │ ├── key: + │ │ │ │ │ │ @ SymbolNode (location: (214,14)-(214,16)) + │ │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ │ ├── value_loc: (214,14)-(214,15) = "a" + │ │ │ │ │ │ ├── closing_loc: (214,15)-(214,16) = ":" + │ │ │ │ │ │ └── unescaped: "a" + │ │ │ │ │ ├── value: + │ │ │ │ │ │ @ IntegerNode (location: (214,16)-(214,17)) + │ │ │ │ │ │ ├── flags: static_literal, decimal + │ │ │ │ │ │ └── value: 1 + │ │ │ │ │ └── operator_loc: ∅ + │ │ │ │ ├── rest: ∅ + │ │ │ │ ├── opening_loc: (214,13)-(214,14) = "{" + │ │ │ │ └── closing_loc: (214,17)-(214,18) = "}" + │ │ │ └── @ HashPatternNode (location: (214,20)-(214,25)) + │ │ │ ├── flags: ∅ + │ │ │ ├── constant: ∅ + │ │ │ ├── elements: (length: 1) + │ │ │ │ └── @ AssocNode (location: (214,21)-(214,24)) + │ │ │ │ ├── flags: static_literal + │ │ │ │ ├── key: + │ │ │ │ │ @ SymbolNode (location: (214,21)-(214,23)) + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── value_loc: (214,21)-(214,22) = "a" + │ │ │ │ │ ├── closing_loc: (214,22)-(214,23) = ":" + │ │ │ │ │ └── unescaped: "a" + │ │ │ │ ├── value: + │ │ │ │ │ @ IntegerNode (location: (214,23)-(214,24)) + │ │ │ │ │ ├── flags: static_literal, decimal + │ │ │ │ │ └── value: 2 + │ │ │ │ └── operator_loc: ∅ + │ │ │ ├── rest: ∅ + │ │ │ ├── opening_loc: (214,20)-(214,21) = "{" + │ │ │ └── closing_loc: (214,24)-(214,25) = "}" + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── opening_loc: (214,12)-(214,13) = "[" + │ │ └── closing_loc: (214,25)-(214,26) = "]" + │ ├── statements: ∅ + │ ├── in_loc: (214,9)-(214,11) = "in" + │ └── then_loc: ∅ + ├── else_clause: ∅ + ├── case_keyword_loc: (214,0)-(214,4) = "case" + └── end_keyword_loc: (214,28)-(214,31) = "end" diff --git a/test/prism/snapshots/procs.txt b/test/prism/snapshots/procs.txt index 1329ae6a5f2..91a53e98f66 100644 --- a/test/prism/snapshots/procs.txt +++ b/test/prism/snapshots/procs.txt @@ -1,17 +1,22 @@ @ ProgramNode (location: (1,0)-(27,19)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(27,19)) + ├── flags: ∅ └── body: (length: 10) ├── @ LambdaNode (location: (1,0)-(1,21)) + │ ├── flags: newline │ ├── locals: [:a, :b, :c, :d] │ ├── operator_loc: (1,0)-(1,2) = "->" │ ├── opening_loc: (1,16)-(1,17) = "{" │ ├── closing_loc: (1,20)-(1,21) = "}" │ ├── parameters: │ │ @ BlockParametersNode (location: (1,3)-(1,15)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (1,4)-(1,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,4)-(1,5)) │ │ │ │ ├── flags: ∅ @@ -36,11 +41,14 @@ │ │ └── closing_loc: (1,14)-(1,15) = ")" │ └── body: │ @ StatementsNode (location: (1,18)-(1,19)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ LocalVariableReadNode (location: (1,18)-(1,19)) + │ ├── flags: newline │ ├── name: :b │ └── depth: 0 ├── @ LambdaNode (location: (3,0)-(5,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── operator_loc: (3,0)-(3,2) = "->" │ ├── opening_loc: (3,3)-(3,5) = "do" @@ -48,17 +56,20 @@ │ ├── parameters: ∅ │ └── body: │ @ BeginNode (location: (3,3)-(5,3)) + │ ├── flags: ∅ │ ├── begin_keyword_loc: ∅ │ ├── statements: ∅ │ ├── rescue_clause: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: │ │ @ EnsureNode (location: (4,0)-(5,3)) + │ │ ├── flags: ∅ │ │ ├── ensure_keyword_loc: (4,0)-(4,6) = "ensure" │ │ ├── statements: ∅ │ │ └── end_keyword_loc: (5,0)-(5,3) = "end" │ └── end_keyword_loc: (5,0)-(5,3) = "end" ├── @ LambdaNode (location: (7,0)-(11,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── operator_loc: (7,0)-(7,2) = "->" │ ├── opening_loc: (7,3)-(7,5) = "do" @@ -66,28 +77,33 @@ │ ├── parameters: ∅ │ └── body: │ @ BeginNode (location: (7,3)-(11,3)) + │ ├── flags: ∅ │ ├── begin_keyword_loc: ∅ │ ├── statements: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (8,0)-(8,6)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (8,0)-(8,6) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: │ │ @ ElseNode (location: (9,0)-(10,6)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (9,0)-(9,4) = "else" │ │ ├── statements: ∅ │ │ └── end_keyword_loc: (10,0)-(10,6) = "ensure" │ ├── ensure_clause: │ │ @ EnsureNode (location: (10,0)-(11,3)) + │ │ ├── flags: ∅ │ │ ├── ensure_keyword_loc: (10,0)-(10,6) = "ensure" │ │ ├── statements: ∅ │ │ └── end_keyword_loc: (11,0)-(11,3) = "end" │ └── end_keyword_loc: (11,0)-(11,3) = "end" ├── @ LambdaNode (location: (13,0)-(13,10)) + │ ├── flags: newline │ ├── locals: [] │ ├── operator_loc: (13,0)-(13,2) = "->" │ ├── opening_loc: (13,3)-(13,4) = "{" @@ -95,9 +111,10 @@ │ ├── parameters: ∅ │ └── body: │ @ StatementsNode (location: (13,5)-(13,8)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (13,5)-(13,8)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -107,6 +124,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ LambdaNode (location: (15,0)-(15,15)) + │ ├── flags: newline │ ├── locals: [] │ ├── operator_loc: (15,0)-(15,2) = "->" │ ├── opening_loc: (15,3)-(15,5) = "do" @@ -114,9 +132,10 @@ │ ├── parameters: ∅ │ └── body: │ @ StatementsNode (location: (15,7)-(15,10)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (15,7)-(15,10)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -126,14 +145,17 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ LambdaNode (location: (17,0)-(17,29)) + │ ├── flags: newline │ ├── locals: [:a, :b, :c, :d, :e] │ ├── operator_loc: (17,0)-(17,2) = "->" │ ├── opening_loc: (17,24)-(17,25) = "{" │ ├── closing_loc: (17,28)-(17,29) = "}" │ ├── parameters: │ │ @ BlockParametersNode (location: (17,3)-(17,23)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (17,3)-(17,23)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (17,3)-(17,4)) │ │ │ │ ├── flags: ∅ @@ -146,7 +168,7 @@ │ │ │ │ ├── operator_loc: (17,8)-(17,9) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (17,10)-(17,11)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── rest: ∅ │ │ │ ├── posts: (length: 0) @@ -171,19 +193,24 @@ │ │ └── closing_loc: ∅ │ └── body: │ @ StatementsNode (location: (17,26)-(17,27)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ LocalVariableReadNode (location: (17,26)-(17,27)) + │ ├── flags: newline │ ├── name: :a │ └── depth: 0 ├── @ LambdaNode (location: (19,0)-(19,40)) + │ ├── flags: newline │ ├── locals: [:a, :b, :c, :d, :e, :f, :g] │ ├── operator_loc: (19,0)-(19,2) = "->" │ ├── opening_loc: (19,35)-(19,36) = "{" │ ├── closing_loc: (19,39)-(19,40) = "}" │ ├── parameters: │ │ @ BlockParametersNode (location: (19,3)-(19,34)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (19,4)-(19,33)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (19,4)-(19,5)) │ │ │ │ ├── flags: ∅ @@ -196,7 +223,7 @@ │ │ │ │ ├── operator_loc: (19,9)-(19,10) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (19,11)-(19,12)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (19,14)-(19,16)) @@ -231,19 +258,24 @@ │ │ └── closing_loc: (19,33)-(19,34) = ")" │ └── body: │ @ StatementsNode (location: (19,37)-(19,38)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ LocalVariableReadNode (location: (19,37)-(19,38)) + │ ├── flags: newline │ ├── name: :a │ └── depth: 0 ├── @ LambdaNode (location: (21,0)-(23,3)) + │ ├── flags: newline │ ├── locals: [:a, :b, :c, :d, :e, :f, :g] │ ├── operator_loc: (21,0)-(21,2) = "->" │ ├── opening_loc: (21,35)-(21,37) = "do" │ ├── closing_loc: (23,0)-(23,3) = "end" │ ├── parameters: │ │ @ BlockParametersNode (location: (21,3)-(21,34)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (21,4)-(21,33)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (21,4)-(21,5)) │ │ │ │ ├── flags: ∅ @@ -256,7 +288,7 @@ │ │ │ │ ├── operator_loc: (21,9)-(21,10) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (21,11)-(21,12)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (21,14)-(21,16)) @@ -291,19 +323,24 @@ │ │ └── closing_loc: (21,33)-(21,34) = ")" │ └── body: │ @ StatementsNode (location: (22,2)-(22,3)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ LocalVariableReadNode (location: (22,2)-(22,3)) + │ ├── flags: newline │ ├── name: :a │ └── depth: 0 ├── @ LambdaNode (location: (25,0)-(25,25)) + │ ├── flags: newline │ ├── locals: [:a] │ ├── operator_loc: (25,0)-(25,2) = "->" │ ├── opening_loc: (25,7)-(25,8) = "{" │ ├── closing_loc: (25,24)-(25,25) = "}" │ ├── parameters: │ │ @ BlockParametersNode (location: (25,3)-(25,6)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (25,4)-(25,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (25,4)-(25,5)) │ │ │ │ ├── flags: ∅ @@ -319,16 +356,20 @@ │ │ └── closing_loc: (25,5)-(25,6) = ")" │ └── body: │ @ StatementsNode (location: (25,9)-(25,23)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ LambdaNode (location: (25,9)-(25,23)) + │ ├── flags: newline │ ├── locals: [:b] │ ├── operator_loc: (25,9)-(25,11) = "->" │ ├── opening_loc: (25,14)-(25,15) = "{" │ ├── closing_loc: (25,22)-(25,23) = "}" │ ├── parameters: │ │ @ BlockParametersNode (location: (25,12)-(25,13)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (25,12)-(25,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (25,12)-(25,13)) │ │ │ │ ├── flags: ∅ @@ -344,11 +385,13 @@ │ │ └── closing_loc: ∅ │ └── body: │ @ StatementsNode (location: (25,16)-(25,21)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (25,16)-(25,21)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (25,16)-(25,17)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 1 │ ├── call_operator_loc: ∅ @@ -360,21 +403,26 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ LocalVariableReadNode (location: (25,20)-(25,21)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ └── depth: 0 │ ├── closing_loc: ∅ │ └── block: ∅ └── @ LambdaNode (location: (27,0)-(27,19)) + ├── flags: newline ├── locals: [:a, :b, :c] ├── operator_loc: (27,0)-(27,2) = "->" ├── opening_loc: (27,16)-(27,17) = "{" ├── closing_loc: (27,18)-(27,19) = "}" ├── parameters: │ @ BlockParametersNode (location: (27,3)-(27,15)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (27,4)-(27,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ MultiTargetNode (location: (27,4)-(27,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (27,5)-(27,6)) │ │ │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/range_begin_open_exclusive.txt b/test/prism/snapshots/range_begin_open_exclusive.txt index a630b01ef19..e4ca315fc2b 100644 --- a/test/prism/snapshots/range_begin_open_exclusive.txt +++ b/test/prism/snapshots/range_begin_open_exclusive.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,4)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,4)) + ├── flags: ∅ └── body: (length: 1) └── @ RangeNode (location: (1,0)-(1,4)) - ├── flags: exclude_end + ├── flags: newline, static_literal, exclude_end ├── left: ∅ ├── right: │ @ IntegerNode (location: (1,3)-(1,4)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 └── operator_loc: (1,0)-(1,3) = "..." diff --git a/test/prism/snapshots/range_begin_open_inclusive.txt b/test/prism/snapshots/range_begin_open_inclusive.txt index dc8ef0d2dbc..45aa88a5d10 100644 --- a/test/prism/snapshots/range_begin_open_inclusive.txt +++ b/test/prism/snapshots/range_begin_open_inclusive.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,3)) + ├── flags: ∅ └── body: (length: 1) └── @ RangeNode (location: (1,0)-(1,3)) - ├── flags: ∅ + ├── flags: newline, static_literal ├── left: ∅ ├── right: │ @ IntegerNode (location: (1,2)-(1,3)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 └── operator_loc: (1,0)-(1,2) = ".." diff --git a/test/prism/snapshots/range_beginless.txt b/test/prism/snapshots/range_beginless.txt new file mode 100644 index 00000000000..800f087dc10 --- /dev/null +++ b/test/prism/snapshots/range_beginless.txt @@ -0,0 +1,114 @@ +@ ProgramNode (location: (1,0)-(5,18)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(5,18)) + ├── flags: ∅ + └── body: (length: 3) + ├── @ DefNode (location: (1,0)-(1,21)) + │ ├── flags: newline + │ ├── name: :f + │ ├── name_loc: (1,4)-(1,5) = "f" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (1,6)-(1,15)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 0) + │ │ ├── optionals: (length: 1) + │ │ │ └── @ OptionalParameterNode (location: (1,6)-(1,15)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :x + │ │ │ ├── name_loc: (1,6)-(1,7) = "x" + │ │ │ ├── operator_loc: (1,8)-(1,9) = "=" + │ │ │ └── value: + │ │ │ @ RangeNode (location: (1,10)-(1,15)) + │ │ │ ├── flags: exclude_end + │ │ │ ├── left: ∅ + │ │ │ ├── right: + │ │ │ │ @ StringNode (location: (1,13)-(1,15)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: (1,13)-(1,14) = "?" + │ │ │ │ ├── content_loc: (1,14)-(1,15) = "a" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "a" + │ │ │ └── operator_loc: (1,10)-(1,13) = "..." + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:x] + │ ├── def_keyword_loc: (1,0)-(1,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (1,5)-(1,6) = "(" + │ ├── rparen_loc: (1,15)-(1,16) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (1,18)-(1,21) = "end" + ├── @ DefNode (location: (3,0)-(3,20)) + │ ├── flags: newline + │ ├── name: :f + │ ├── name_loc: (3,4)-(3,5) = "f" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (3,6)-(3,14)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 0) + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 1) + │ │ │ └── @ OptionalKeywordParameterNode (location: (3,6)-(3,14)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :x + │ │ │ ├── name_loc: (3,6)-(3,8) = "x:" + │ │ │ └── value: + │ │ │ @ RangeNode (location: (3,9)-(3,14)) + │ │ │ ├── flags: exclude_end + │ │ │ ├── left: ∅ + │ │ │ ├── right: + │ │ │ │ @ StringNode (location: (3,12)-(3,14)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: (3,12)-(3,13) = "?" + │ │ │ │ ├── content_loc: (3,13)-(3,14) = "a" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "a" + │ │ │ └── operator_loc: (3,9)-(3,12) = "..." + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:x] + │ ├── def_keyword_loc: (3,0)-(3,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (3,5)-(3,6) = "(" + │ ├── rparen_loc: (3,14)-(3,15) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (3,17)-(3,20) = "end" + └── @ DefNode (location: (5,0)-(5,18)) + ├── flags: newline + ├── name: :f + ├── name_loc: (5,4)-(5,5) = "f" + ├── receiver: ∅ + ├── parameters: ∅ + ├── body: + │ @ StatementsNode (location: (5,8)-(5,13)) + │ ├── flags: ∅ + │ └── body: (length: 1) + │ └── @ RangeNode (location: (5,8)-(5,13)) + │ ├── flags: newline, exclude_end + │ ├── left: ∅ + │ ├── right: + │ │ @ SymbolNode (location: (5,11)-(5,13)) + │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ ├── opening_loc: (5,11)-(5,12) = ":" + │ │ ├── value_loc: (5,12)-(5,13) = "a" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "a" + │ └── operator_loc: (5,8)-(5,11) = "..." + ├── locals: [] + ├── def_keyword_loc: (5,0)-(5,3) = "def" + ├── operator_loc: ∅ + ├── lparen_loc: (5,5)-(5,6) = "(" + ├── rparen_loc: (5,6)-(5,7) = ")" + ├── equal_loc: ∅ + └── end_keyword_loc: (5,15)-(5,18) = "end" diff --git a/test/prism/snapshots/range_end_open_exclusive.txt b/test/prism/snapshots/range_end_open_exclusive.txt index 17a75f89456..d0d3f810a37 100644 --- a/test/prism/snapshots/range_end_open_exclusive.txt +++ b/test/prism/snapshots/range_end_open_exclusive.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,4)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,4)) + ├── flags: ∅ └── body: (length: 1) └── @ RangeNode (location: (1,0)-(1,4)) - ├── flags: exclude_end + ├── flags: newline, static_literal, exclude_end ├── left: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── right: ∅ └── operator_loc: (1,1)-(1,4) = "..." diff --git a/test/prism/snapshots/range_end_open_inclusive.txt b/test/prism/snapshots/range_end_open_inclusive.txt index b49272d8cd1..8bfee649a3c 100644 --- a/test/prism/snapshots/range_end_open_inclusive.txt +++ b/test/prism/snapshots/range_end_open_inclusive.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,3)) + ├── flags: ∅ └── body: (length: 1) └── @ RangeNode (location: (1,0)-(1,3)) - ├── flags: ∅ + ├── flags: newline, static_literal ├── left: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── right: ∅ └── operator_loc: (1,1)-(1,3) = ".." diff --git a/test/prism/snapshots/ranges.txt b/test/prism/snapshots/ranges.txt index 2fffe805376..81dbe3d901d 100644 --- a/test/prism/snapshots/ranges.txt +++ b/test/prism/snapshots/ranges.txt @@ -1,49 +1,55 @@ @ ProgramNode (location: (1,0)-(49,7)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(49,7)) + ├── flags: ∅ └── body: (length: 25) ├── @ ParenthesesNode (location: (1,0)-(1,6)) + │ ├── flags: newline │ ├── body: │ │ @ StatementsNode (location: (1,1)-(1,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RangeNode (location: (1,1)-(1,5)) - │ │ ├── flags: exclude_end + │ │ ├── flags: newline, static_literal, exclude_end │ │ ├── left: ∅ │ │ ├── right: │ │ │ @ IntegerNode (location: (1,4)-(1,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: (1,1)-(1,4) = "..." │ ├── opening_loc: (1,0)-(1,1) = "(" │ └── closing_loc: (1,5)-(1,6) = ")" ├── @ ParenthesesNode (location: (3,0)-(3,5)) + │ ├── flags: newline │ ├── body: │ │ @ StatementsNode (location: (3,1)-(3,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RangeNode (location: (3,1)-(3,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline, static_literal │ │ ├── left: ∅ │ │ ├── right: │ │ │ @ IntegerNode (location: (3,3)-(3,4)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: (3,1)-(3,3) = ".." │ ├── opening_loc: (3,0)-(3,1) = "(" │ └── closing_loc: (3,4)-(3,5) = ")" ├── @ RangeNode (location: (5,0)-(5,5)) - │ ├── flags: exclude_end + │ ├── flags: newline, static_literal, exclude_end │ ├── left: │ │ @ IntegerNode (location: (5,0)-(5,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (5,4)-(5,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ └── operator_loc: (5,1)-(5,4) = "..." ├── @ CallNode (location: (7,0)-(7,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (7,0)-(7,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -64,22 +70,24 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ RangeNode (location: (7,4)-(7,8)) - │ │ ├── flags: exclude_end + │ │ ├── flags: static_literal, exclude_end │ │ ├── left: ∅ │ │ ├── right: │ │ │ @ IntegerNode (location: (7,7)-(7,8)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: (7,4)-(7,7) = "..." │ ├── closing_loc: (7,8)-(7,9) = "]" │ └── block: ∅ ├── @ HashNode (location: (9,0)-(9,15)) + │ ├── flags: newline │ ├── opening_loc: (9,0)-(9,1) = "{" │ ├── elements: (length: 1) │ │ └── @ AssocNode (location: (9,2)-(9,13)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ SymbolNode (location: (9,2)-(9,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (9,2)-(9,5) = "foo" │ │ │ ├── closing_loc: (9,5)-(9,6) = ":" @@ -103,37 +111,41 @@ │ │ └── operator_loc: ∅ │ └── closing_loc: (9,14)-(9,15) = "}" ├── @ ParenthesesNode (location: (11,0)-(11,6)) + │ ├── flags: newline │ ├── body: │ │ @ StatementsNode (location: (11,1)-(11,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RangeNode (location: (11,1)-(11,5)) - │ │ ├── flags: exclude_end + │ │ ├── flags: newline, static_literal, exclude_end │ │ ├── left: │ │ │ @ IntegerNode (location: (11,1)-(11,2)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (11,2)-(11,5) = "..." │ ├── opening_loc: (11,0)-(11,1) = "(" │ └── closing_loc: (11,5)-(11,6) = ")" ├── @ RangeNode (location: (13,0)-(13,4)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── left: │ │ @ IntegerNode (location: (13,0)-(13,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (13,3)-(13,4)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ └── operator_loc: (13,1)-(13,3) = ".." ├── @ HashNode (location: (15,0)-(15,14)) + │ ├── flags: newline │ ├── opening_loc: (15,0)-(15,1) = "{" │ ├── elements: (length: 1) │ │ └── @ AssocNode (location: (15,2)-(15,12)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ SymbolNode (location: (15,2)-(15,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (15,2)-(15,5) = "foo" │ │ │ ├── closing_loc: (15,5)-(15,6) = ":" @@ -157,58 +169,61 @@ │ │ └── operator_loc: ∅ │ └── closing_loc: (15,13)-(15,14) = "}" ├── @ ParenthesesNode (location: (17,0)-(17,5)) + │ ├── flags: newline │ ├── body: │ │ @ StatementsNode (location: (17,1)-(17,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RangeNode (location: (17,1)-(17,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline, static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (17,1)-(17,2)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (17,2)-(17,4) = ".." │ ├── opening_loc: (17,0)-(17,1) = "(" │ └── closing_loc: (17,4)-(17,5) = ")" ├── @ RangeNode (location: (19,0)-(19,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── left: │ │ @ IntegerNode (location: (19,0)-(19,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── right: │ │ @ RangeNode (location: (19,5)-(19,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: ∅ │ │ ├── right: │ │ │ @ IntegerNode (location: (19,7)-(19,8)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── operator_loc: (19,5)-(19,7) = ".." │ └── operator_loc: (19,2)-(19,4) = ".." ├── @ AndNode (location: (21,0)-(21,8)) + │ ├── flags: newline │ ├── left: │ │ @ RangeNode (location: (21,0)-(21,3)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (21,0)-(21,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (21,1)-(21,3) = ".." │ ├── right: │ │ @ IntegerNode (location: (21,7)-(21,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ └── operator_loc: (21,4)-(21,6) = "&&" ├── @ CallNode (location: (23,0)-(23,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RangeNode (location: (23,0)-(23,3)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (23,0)-(23,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (23,1)-(23,3) = ".." @@ -221,18 +236,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (23,7)-(23,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (25,0)-(25,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RangeNode (location: (25,0)-(25,3)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (25,0)-(25,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (25,1)-(25,3) = ".." @@ -245,18 +260,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (25,7)-(25,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (27,0)-(27,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RangeNode (location: (27,0)-(27,3)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (27,0)-(27,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (27,1)-(27,3) = ".." @@ -269,18 +284,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (27,8)-(27,9)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (29,0)-(29,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RangeNode (location: (29,0)-(29,3)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (29,0)-(29,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (29,1)-(29,3) = ".." @@ -293,18 +308,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (29,8)-(29,9)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (31,0)-(31,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RangeNode (location: (31,0)-(31,3)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (31,0)-(31,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (31,1)-(31,3) = ".." @@ -317,18 +332,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (31,7)-(31,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (33,0)-(33,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RangeNode (location: (33,0)-(33,3)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (33,0)-(33,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (33,1)-(33,3) = ".." @@ -341,18 +356,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (33,7)-(33,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (35,0)-(35,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RangeNode (location: (35,0)-(35,3)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (35,0)-(35,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (35,1)-(35,3) = ".." @@ -365,18 +380,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (35,6)-(35,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (37,0)-(37,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RangeNode (location: (37,0)-(37,3)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (37,0)-(37,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (37,1)-(37,3) = ".." @@ -389,18 +404,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (37,6)-(37,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (39,0)-(39,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RangeNode (location: (39,0)-(39,3)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (39,0)-(39,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (39,1)-(39,3) = ".." @@ -413,18 +428,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (39,7)-(39,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (41,0)-(41,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RangeNode (location: (41,0)-(41,3)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (41,0)-(41,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (41,1)-(41,3) = ".." @@ -437,18 +452,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (41,7)-(41,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (43,0)-(43,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RangeNode (location: (43,0)-(43,3)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (43,0)-(43,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (43,1)-(43,3) = ".." @@ -461,18 +476,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (43,7)-(43,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (45,0)-(45,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RangeNode (location: (45,0)-(45,3)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (45,0)-(45,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (45,1)-(45,3) = ".." @@ -485,22 +500,22 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (45,7)-(45,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ RangeNode (location: (47,0)-(47,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── left: │ │ @ IntegerNode (location: (47,0)-(47,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── right: │ │ @ CallNode (location: (47,4)-(47,7)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (47,6)-(47,7)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :+@ @@ -511,17 +526,17 @@ │ │ └── block: ∅ │ └── operator_loc: (47,1)-(47,3) = ".." └── @ RangeNode (location: (49,0)-(49,7)) - ├── flags: ∅ + ├── flags: newline ├── left: │ @ IntegerNode (location: (49,0)-(49,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── right: │ @ CallNode (location: (49,4)-(49,7)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (49,6)-(49,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── call_operator_loc: ∅ │ ├── name: :-@ diff --git a/test/prism/snapshots/regex.txt b/test/prism/snapshots/regex.txt index d4d153e8d51..c90e6897607 100644 --- a/test/prism/snapshots/regex.txt +++ b/test/prism/snapshots/regex.txt @@ -1,10 +1,12 @@ -@ ProgramNode (location: (1,0)-(46,32)) +@ ProgramNode (location: (1,0)-(48,10)) +├── flags: ∅ ├── locals: [:foo, :ab, :abc, :a] └── statements: - @ StatementsNode (location: (1,0)-(46,32)) - └── body: (length: 25) + @ StatementsNode (location: (1,0)-(48,10)) + ├── flags: ∅ + └── body: (length: 26) ├── @ CallNode (location: (1,0)-(1,9)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -15,7 +17,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ RegularExpressionNode (location: (1,4)-(1,9)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,4)-(1,5) = "/" │ │ ├── content_loc: (1,5)-(1,8) = "bar" │ │ ├── closing_loc: (1,8)-(1,9) = "/" @@ -23,47 +25,51 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ RegularExpressionNode (location: (3,0)-(3,8)) - │ ├── flags: ignore_case, forced_us_ascii_encoding + │ ├── flags: newline, static_literal, ignore_case, forced_us_ascii_encoding │ ├── opening_loc: (3,0)-(3,3) = "%r{" │ ├── content_loc: (3,3)-(3,6) = "abc" │ ├── closing_loc: (3,6)-(3,8) = "}i" │ └── unescaped: "abc" ├── @ RegularExpressionNode (location: (5,0)-(5,5)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (5,0)-(5,1) = "/" │ ├── content_loc: (5,1)-(5,4) = "a\\b" │ ├── closing_loc: (5,4)-(5,5) = "/" │ └── unescaped: "a\\b" ├── @ InterpolatedRegularExpressionNode (location: (7,0)-(7,11)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (7,0)-(7,1) = "/" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (7,1)-(7,5)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (7,1)-(7,5) = "aaa " │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "aaa " │ │ └── @ EmbeddedVariableNode (location: (7,5)-(7,10)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (7,5)-(7,6) = "#" │ │ └── variable: │ │ @ GlobalVariableReadNode (location: (7,6)-(7,10)) + │ │ ├── flags: ∅ │ │ └── name: :$bbb │ └── closing_loc: (7,10)-(7,11) = "/" ├── @ InterpolatedRegularExpressionNode (location: (9,0)-(9,16)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (9,0)-(9,1) = "/" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (9,1)-(9,5)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (9,1)-(9,5) = "aaa " │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "aaa " │ │ ├── @ EmbeddedStatementsNode (location: (9,5)-(9,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (9,5)-(9,7) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (9,7)-(9,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (9,7)-(9,10)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -77,22 +83,23 @@ │ │ │ │ └── block: ∅ │ │ │ └── closing_loc: (9,10)-(9,11) = "}" │ │ └── @ StringNode (location: (9,11)-(9,15)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (9,11)-(9,15) = " ccc" │ │ ├── closing_loc: ∅ │ │ └── unescaped: " ccc" │ └── closing_loc: (9,15)-(9,16) = "/" ├── @ ArrayNode (location: (11,0)-(11,27)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 2) │ │ ├── @ MatchWriteNode (location: (11,1)-(11,21)) + │ │ │ ├── flags: ∅ │ │ │ ├── call: │ │ │ │ @ CallNode (location: (11,1)-(11,21)) │ │ │ │ ├── flags: ∅ │ │ │ │ ├── receiver: │ │ │ │ │ @ RegularExpressionNode (location: (11,1)-(11,14)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (11,1)-(11,2) = "/" │ │ │ │ │ ├── content_loc: (11,2)-(11,13) = "(?bar)" │ │ │ │ │ ├── closing_loc: (11,13)-(11,14) = "/" @@ -119,48 +126,50 @@ │ │ │ │ └── block: ∅ │ │ │ └── targets: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (11,5)-(11,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :foo │ │ │ └── depth: 0 │ │ └── @ LocalVariableReadNode (location: (11,23)-(11,26)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── depth: 0 │ ├── opening_loc: (11,0)-(11,1) = "[" │ └── closing_loc: (11,26)-(11,27) = "]" ├── @ RegularExpressionNode (location: (13,0)-(13,6)) - │ ├── flags: ignore_case, forced_us_ascii_encoding + │ ├── flags: newline, static_literal, ignore_case, forced_us_ascii_encoding │ ├── opening_loc: (13,0)-(13,1) = "/" │ ├── content_loc: (13,1)-(13,4) = "abc" │ ├── closing_loc: (13,4)-(13,6) = "/i" │ └── unescaped: "abc" ├── @ RegularExpressionNode (location: (15,0)-(15,26)) - │ ├── flags: ignore_case, forced_us_ascii_encoding + │ ├── flags: newline, static_literal, ignore_case, forced_us_ascii_encoding │ ├── opening_loc: (15,0)-(15,3) = "%r/" │ ├── content_loc: (15,3)-(15,24) = "[a-z$._?][\\w$.?\#@~]*:" │ ├── closing_loc: (15,24)-(15,26) = "/i" │ └── unescaped: "[a-z$._?][\\w$.?\#@~]*:" ├── @ RegularExpressionNode (location: (17,0)-(17,37)) - │ ├── flags: ignore_case, forced_us_ascii_encoding + │ ├── flags: newline, static_literal, ignore_case, forced_us_ascii_encoding │ ├── opening_loc: (17,0)-(17,3) = "%r/" │ ├── content_loc: (17,3)-(17,35) = "([a-z$._?][\\w$.?\#@~]*)(\\s+)(equ)" │ ├── closing_loc: (17,35)-(17,37) = "/i" │ └── unescaped: "([a-z$._?][\\w$.?\#@~]*)(\\s+)(equ)" ├── @ RegularExpressionNode (location: (19,0)-(19,25)) - │ ├── flags: ignore_case, forced_us_ascii_encoding + │ ├── flags: newline, static_literal, ignore_case, forced_us_ascii_encoding │ ├── opening_loc: (19,0)-(19,3) = "%r/" │ ├── content_loc: (19,3)-(19,23) = "[a-z$._?][\\w$.?\#@~]*" │ ├── closing_loc: (19,23)-(19,25) = "/i" │ └── unescaped: "[a-z$._?][\\w$.?\#@~]*" ├── @ RegularExpressionNode (location: (21,0)-(24,1)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (21,0)-(21,3) = "%r(" │ ├── content_loc: (21,3)-(24,0) = "\n(?:[\#$%_']|\\(\\)|\\(,\\)|\\[\\]|[0-9])*\n (?:[\#$%_']+)\n" │ ├── closing_loc: (24,0)-(24,1) = ")" │ └── unescaped: "\n(?:[\#$%_']|\\(\\)|\\(,\\)|\\[\\]|[0-9])*\n (?:[\#$%_']+)\n" ├── @ CallNode (location: (26,0)-(26,16)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RegularExpressionNode (location: (26,0)-(26,8)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (26,0)-(26,1) = "/" │ │ ├── content_loc: (26,1)-(26,7) = "(?#\\))" │ │ ├── closing_loc: (26,7)-(26,8) = "/" @@ -182,25 +191,27 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ RegularExpressionNode (location: (28,0)-(28,9)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (28,0)-(28,3) = "%r#" │ ├── content_loc: (28,3)-(28,8) = "pound" │ ├── closing_loc: (28,8)-(28,9) = "#" │ └── unescaped: "pound" ├── @ InterpolatedRegularExpressionNode (location: (30,0)-(30,13)) - │ ├── flags: once + │ ├── flags: newline, once │ ├── opening_loc: (30,0)-(30,1) = "/" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (30,1)-(30,5)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (30,1)-(30,5) = "aaa " │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "aaa " │ │ └── @ EmbeddedStatementsNode (location: (30,5)-(30,11)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (30,5)-(30,7) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (30,7)-(30,10)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (30,7)-(30,10)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -215,12 +226,13 @@ │ │ └── closing_loc: (30,10)-(30,11) = "}" │ └── closing_loc: (30,11)-(30,13) = "/o" ├── @ MatchWriteNode (location: (32,0)-(33,10)) + │ ├── flags: newline │ ├── call: │ │ @ CallNode (location: (32,0)-(33,10)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ RegularExpressionNode (location: (32,0)-(33,4)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (32,0)-(32,1) = "/" │ │ │ ├── content_loc: (32,1)-(33,3) = "(?)" │ │ │ ├── closing_loc: (33,3)-(33,4) = "/" @@ -243,18 +255,21 @@ │ │ └── block: ∅ │ └── targets: (length: 1) │ └── @ LocalVariableTargetNode (location: (32,0)-(33,4)) + │ ├── flags: ∅ │ ├── name: :ab │ └── depth: 0 ├── @ LocalVariableReadNode (location: (33,12)-(33,14)) + │ ├── flags: newline │ ├── name: :ab │ └── depth: 0 ├── @ MatchWriteNode (location: (35,0)-(35,24)) + │ ├── flags: newline │ ├── call: │ │ @ CallNode (location: (35,0)-(35,24)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ RegularExpressionNode (location: (35,0)-(35,18)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (35,0)-(35,1) = "/" │ │ │ ├── content_loc: (35,1)-(35,17) = "(?)(?)" │ │ │ ├── closing_loc: (35,17)-(35,18) = "/" @@ -277,16 +292,18 @@ │ │ └── block: ∅ │ └── targets: (length: 1) │ └── @ LocalVariableTargetNode (location: (35,4)-(35,7)) + │ ├── flags: ∅ │ ├── name: :abc │ └── depth: 0 ├── @ LocalVariableReadNode (location: (35,26)-(35,29)) + │ ├── flags: newline │ ├── name: :abc │ └── depth: 0 ├── @ CallNode (location: (37,0)-(37,16)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RegularExpressionNode (location: (37,0)-(37,10)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (37,0)-(37,1) = "/" │ │ ├── content_loc: (37,1)-(37,9) = "(?)" │ │ ├── closing_loc: (37,9)-(37,10) = "/" @@ -308,16 +325,17 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ LocalVariableWriteNode (location: (39,0)-(39,5)) + │ ├── flags: newline │ ├── name: :a │ ├── depth: 0 │ ├── name_loc: (39,0)-(39,1) = "a" │ ├── value: │ │ @ IntegerNode (location: (39,4)-(39,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (39,2)-(39,3) = "=" ├── @ CallNode (location: (40,0)-(40,24)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -327,18 +345,21 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (40,4)-(40,24)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (40,6)-(40,22)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ MatchWriteNode (location: (40,6)-(40,22)) + │ │ ├── flags: newline │ │ ├── call: │ │ │ @ CallNode (location: (40,6)-(40,22)) │ │ │ ├── flags: ∅ │ │ │ ├── receiver: │ │ │ │ @ RegularExpressionNode (location: (40,6)-(40,14)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (40,6)-(40,7) = "/" │ │ │ │ ├── content_loc: (40,7)-(40,13) = "(?)" │ │ │ │ ├── closing_loc: (40,13)-(40,14) = "/" @@ -365,17 +386,19 @@ │ │ │ └── block: ∅ │ │ └── targets: (length: 1) │ │ └── @ LocalVariableTargetNode (location: (40,10)-(40,11)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 1 │ ├── opening_loc: (40,4)-(40,5) = "{" │ └── closing_loc: (40,23)-(40,24) = "}" ├── @ MatchWriteNode (location: (42,0)-(42,16)) + │ ├── flags: newline │ ├── call: │ │ @ CallNode (location: (42,0)-(42,16)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ RegularExpressionNode (location: (42,0)-(42,10)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (42,0)-(42,1) = "/" │ │ │ ├── content_loc: (42,1)-(42,9) = "(?)" │ │ │ ├── closing_loc: (42,9)-(42,10) = "/" @@ -398,13 +421,14 @@ │ │ └── block: ∅ │ └── targets: (length: 1) │ └── @ LocalVariableTargetNode (location: (42,4)-(42,7)) + │ ├── flags: ∅ │ ├── name: :foo │ └── depth: 0 ├── @ CallNode (location: (43,0)-(43,16)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RegularExpressionNode (location: (43,0)-(43,10)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (43,0)-(43,1) = "/" │ │ ├── content_loc: (43,1)-(43,9) = "(?)" │ │ ├── closing_loc: (43,9)-(43,10) = "/" @@ -426,10 +450,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (45,0)-(45,16)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RegularExpressionNode (location: (45,0)-(45,10)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (45,0)-(45,1) = "/" │ │ ├── content_loc: (45,1)-(45,9) = "(?)" │ │ ├── closing_loc: (45,9)-(45,10) = "/" @@ -450,61 +474,72 @@ │ │ └── unescaped: "" │ ├── closing_loc: ∅ │ └── block: ∅ - └── @ DefNode (location: (46,0)-(46,32)) - ├── name: :foo - ├── name_loc: (46,4)-(46,7) = "foo" - ├── receiver: ∅ - ├── parameters: - │ @ ParametersNode (location: (46,8)-(46,12)) - │ ├── requireds: (length: 0) - │ ├── optionals: (length: 0) - │ ├── rest: ∅ - │ ├── posts: (length: 0) - │ ├── keywords: (length: 1) - │ │ └── @ RequiredKeywordParameterNode (location: (46,8)-(46,12)) - │ │ ├── flags: ∅ - │ │ ├── name: :nil - │ │ └── name_loc: (46,8)-(46,12) = "nil:" - │ ├── keyword_rest: ∅ - │ └── block: ∅ - ├── body: - │ @ StatementsNode (location: (46,16)-(46,32)) - │ └── body: (length: 1) - │ └── @ MatchWriteNode (location: (46,16)-(46,32)) - │ ├── call: - │ │ @ CallNode (location: (46,16)-(46,32)) - │ │ ├── flags: ∅ - │ │ ├── receiver: - │ │ │ @ RegularExpressionNode (location: (46,16)-(46,26)) - │ │ │ ├── flags: forced_us_ascii_encoding - │ │ │ ├── opening_loc: (46,16)-(46,17) = "/" - │ │ │ ├── content_loc: (46,17)-(46,25) = "(?)" - │ │ │ ├── closing_loc: (46,25)-(46,26) = "/" - │ │ │ └── unescaped: "(?)" - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :=~ - │ │ ├── message_loc: (46,27)-(46,29) = "=~" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: - │ │ │ @ ArgumentsNode (location: (46,30)-(46,32)) - │ │ │ ├── flags: ∅ - │ │ │ └── arguments: (length: 1) - │ │ │ └── @ StringNode (location: (46,30)-(46,32)) - │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (46,30)-(46,31) = "\"" - │ │ │ ├── content_loc: (46,31)-(46,31) = "" - │ │ │ ├── closing_loc: (46,31)-(46,32) = "\"" - │ │ │ └── unescaped: "" - │ │ ├── closing_loc: ∅ - │ │ └── block: ∅ - │ └── targets: (length: 1) - │ └── @ LocalVariableTargetNode (location: (46,20)-(46,23)) - │ ├── name: :nil - │ └── depth: 0 - ├── locals: [:nil] - ├── def_keyword_loc: (46,0)-(46,3) = "def" - ├── operator_loc: ∅ - ├── lparen_loc: (46,7)-(46,8) = "(" - ├── rparen_loc: (46,12)-(46,13) = ")" - ├── equal_loc: (46,14)-(46,15) = "=" - └── end_keyword_loc: ∅ + ├── @ DefNode (location: (46,0)-(46,32)) + │ ├── flags: newline + │ ├── name: :foo + │ ├── name_loc: (46,4)-(46,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (46,8)-(46,12)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 0) + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 1) + │ │ │ └── @ RequiredKeywordParameterNode (location: (46,8)-(46,12)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :nil + │ │ │ └── name_loc: (46,8)-(46,12) = "nil:" + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: + │ │ @ StatementsNode (location: (46,16)-(46,32)) + │ │ ├── flags: ∅ + │ │ └── body: (length: 1) + │ │ └── @ MatchWriteNode (location: (46,16)-(46,32)) + │ │ ├── flags: ∅ + │ │ ├── call: + │ │ │ @ CallNode (location: (46,16)-(46,32)) + │ │ │ ├── flags: ∅ + │ │ │ ├── receiver: + │ │ │ │ @ RegularExpressionNode (location: (46,16)-(46,26)) + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ │ ├── opening_loc: (46,16)-(46,17) = "/" + │ │ │ │ ├── content_loc: (46,17)-(46,25) = "(?)" + │ │ │ │ ├── closing_loc: (46,25)-(46,26) = "/" + │ │ │ │ └── unescaped: "(?)" + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :=~ + │ │ │ ├── message_loc: (46,27)-(46,29) = "=~" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: + │ │ │ │ @ ArgumentsNode (location: (46,30)-(46,32)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── arguments: (length: 1) + │ │ │ │ └── @ StringNode (location: (46,30)-(46,32)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: (46,30)-(46,31) = "\"" + │ │ │ │ ├── content_loc: (46,31)-(46,31) = "" + │ │ │ │ ├── closing_loc: (46,31)-(46,32) = "\"" + │ │ │ │ └── unescaped: "" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── block: ∅ + │ │ └── targets: (length: 1) + │ │ └── @ LocalVariableTargetNode (location: (46,20)-(46,23)) + │ │ ├── flags: ∅ + │ │ ├── name: :nil + │ │ └── depth: 0 + │ ├── locals: [:nil] + │ ├── def_keyword_loc: (46,0)-(46,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (46,7)-(46,8) = "(" + │ ├── rparen_loc: (46,12)-(46,13) = ")" + │ ├── equal_loc: (46,14)-(46,15) = "=" + │ └── end_keyword_loc: ∅ + └── @ RegularExpressionNode (location: (48,0)-(48,10)) + ├── flags: newline, static_literal, extended, forced_us_ascii_encoding + ├── opening_loc: (48,0)-(48,1) = "/" + ├── content_loc: (48,1)-(48,8) = "(?-x:#)" + ├── closing_loc: (48,8)-(48,10) = "/x" + └── unescaped: "(?-x:#)" diff --git a/test/prism/snapshots/regex_char_width.txt b/test/prism/snapshots/regex_char_width.txt index 6bf2169b2f3..664e4e8850a 100644 --- a/test/prism/snapshots/regex_char_width.txt +++ b/test/prism/snapshots/regex_char_width.txt @@ -1,15 +1,18 @@ @ ProgramNode (location: (2,0)-(3,6)) +├── flags: ∅ ├── locals: [:a, :b] └── statements: @ StatementsNode (location: (2,0)-(3,6)) + ├── flags: ∅ └── body: (length: 2) ├── @ MatchWriteNode (location: (2,0)-(2,36)) + │ ├── flags: newline │ ├── call: │ │ @ CallNode (location: (2,0)-(2,36)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ RegularExpressionNode (location: (2,0)-(2,22)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: static_literal │ │ │ ├── opening_loc: (2,0)-(2,1) = "/" │ │ │ ├── content_loc: (2,1)-(2,21) = "\x{E285}\xA7(?.)\x{E285}\xA9(?.)" │ │ │ ├── closing_loc: (2,21)-(2,22) = "/" @@ -32,18 +35,22 @@ │ │ └── block: ∅ │ └── targets: (length: 2) │ ├── @ LocalVariableTargetNode (location: (2,7)-(2,8)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ └── @ LocalVariableTargetNode (location: (2,17)-(2,18)) + │ ├── flags: ∅ │ ├── name: :b │ └── depth: 0 └── @ ArrayNode (location: (3,0)-(3,6)) - ├── flags: ∅ + ├── flags: newline ├── elements: (length: 2) │ ├── @ LocalVariableReadNode (location: (3,1)-(3,2)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ └── @ LocalVariableReadNode (location: (3,4)-(3,5)) + │ ├── flags: ∅ │ ├── name: :b │ └── depth: 0 ├── opening_loc: (3,0)-(3,1) = "[" diff --git a/test/prism/snapshots/regex_escape_encoding.txt b/test/prism/snapshots/regex_escape_encoding.txt new file mode 100644 index 00000000000..0f2dcc2c54e --- /dev/null +++ b/test/prism/snapshots/regex_escape_encoding.txt @@ -0,0 +1,43 @@ +@ ProgramNode (location: (2,0)-(3,21)) +├── flags: ∅ +├── locals: [:str] +└── statements: + @ StatementsNode (location: (2,0)-(3,21)) + ├── flags: ∅ + └── body: (length: 2) + ├── @ LocalVariableWriteNode (location: (2,0)-(2,18)) + │ ├── flags: newline + │ ├── name: :str + │ ├── depth: 0 + │ ├── name_loc: (2,0)-(2,3) = "str" + │ ├── value: + │ │ @ StringNode (location: (2,6)-(2,18)) + │ │ ├── flags: forced_binary_encoding + │ │ ├── opening_loc: (2,6)-(2,7) = "\"" + │ │ ├── content_loc: (2,7)-(2,17) = "hello \\xFC" + │ │ ├── closing_loc: (2,17)-(2,18) = "\"" + │ │ └── unescaped: "hello \xFC" + │ └── operator_loc: (2,4)-(2,5) = "=" + └── @ CallNode (location: (3,0)-(3,21)) + ├── flags: newline + ├── receiver: + │ @ LocalVariableReadNode (location: (3,0)-(3,3)) + │ ├── flags: ∅ + │ ├── name: :str + │ └── depth: 0 + ├── call_operator_loc: ∅ + ├── name: :=~ + ├── message_loc: (3,4)-(3,6) = "=~" + ├── opening_loc: ∅ + ├── arguments: + │ @ ArgumentsNode (location: (3,7)-(3,21)) + │ ├── flags: ∅ + │ └── arguments: (length: 1) + │ └── @ RegularExpressionNode (location: (3,7)-(3,21)) + │ ├── flags: static_literal, forced_utf8_encoding + │ ├── opening_loc: (3,7)-(3,8) = "/" + │ ├── content_loc: (3,8)-(3,20) = "hello \\u{fc}" + │ ├── closing_loc: (3,20)-(3,21) = "/" + │ └── unescaped: "hello \\u{fc}" + ├── closing_loc: ∅ + └── block: ∅ diff --git a/test/prism/snapshots/repeat_parameters.txt b/test/prism/snapshots/repeat_parameters.txt index fd98294ce61..1dbf120e9cb 100644 --- a/test/prism/snapshots/repeat_parameters.txt +++ b/test/prism/snapshots/repeat_parameters.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(38,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(38,3)) + ├── flags: ∅ └── body: (length: 13) ├── @ DefNode (location: (1,0)-(2,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (1,4)-(1,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,8)-(1,12)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,8)-(1,9)) │ │ │ │ ├── flags: ∅ @@ -31,11 +35,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (2,0)-(2,3) = "end" ├── @ DefNode (location: (4,0)-(5,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (4,4)-(4,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (4,8)-(4,15)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 3) │ │ │ ├── @ RequiredParameterNode (location: (4,8)-(4,9)) │ │ │ │ ├── flags: ∅ @@ -61,11 +67,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (5,0)-(5,3) = "end" ├── @ DefNode (location: (7,0)-(8,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (7,4)-(7,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (7,8)-(7,19)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 4) │ │ │ ├── @ RequiredParameterNode (location: (7,8)-(7,9)) │ │ │ │ ├── flags: ∅ @@ -94,11 +102,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (8,0)-(8,3) = "end" ├── @ DefNode (location: (10,0)-(11,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (10,4)-(10,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (10,8)-(10,23)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 5) │ │ │ ├── @ RequiredParameterNode (location: (10,8)-(10,9)) │ │ │ │ ├── flags: ∅ @@ -130,22 +140,26 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (11,0)-(11,3) = "end" ├── @ DefNode (location: (13,0)-(14,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (13,4)-(13,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (13,8)-(13,35)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 3) │ │ │ ├── @ RequiredParameterNode (location: (13,8)-(13,9)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── @ MultiTargetNode (location: (13,11)-(13,22)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── lefts: (length: 1) │ │ │ │ │ └── @ RequiredParameterNode (location: (13,12)-(13,13)) │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :b │ │ │ │ ├── rest: │ │ │ │ │ @ SplatNode (location: (13,15)-(13,18)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── operator_loc: (13,15)-(13,16) = "*" │ │ │ │ │ └── expression: │ │ │ │ │ @ RequiredParameterNode (location: (13,16)-(13,18)) @@ -158,12 +172,14 @@ │ │ │ │ ├── lparen_loc: (13,11)-(13,12) = "(" │ │ │ │ └── rparen_loc: (13,21)-(13,22) = ")" │ │ │ └── @ MultiTargetNode (location: (13,24)-(13,35)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (13,25)-(13,26)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :e │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (13,28)-(13,31)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (13,28)-(13,29) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (13,29)-(13,31)) @@ -190,11 +206,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (14,0)-(14,3) = "end" ├── @ DefNode (location: (16,0)-(17,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (16,4)-(16,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (16,8)-(16,20)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 4) │ │ │ ├── @ RequiredParameterNode (location: (16,8)-(16,10)) │ │ │ │ ├── flags: ∅ @@ -223,19 +241,23 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (17,0)-(17,3) = "end" ├── @ DefNode (location: (19,0)-(20,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (19,4)-(19,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (19,8)-(19,32)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ MultiTargetNode (location: (19,8)-(19,19)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── lefts: (length: 1) │ │ │ │ │ └── @ RequiredParameterNode (location: (19,9)-(19,10)) │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ ├── rest: │ │ │ │ │ @ SplatNode (location: (19,12)-(19,15)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── operator_loc: (19,12)-(19,13) = "*" │ │ │ │ │ └── expression: │ │ │ │ │ @ RequiredParameterNode (location: (19,13)-(19,15)) @@ -248,12 +270,14 @@ │ │ │ │ ├── lparen_loc: (19,8)-(19,9) = "(" │ │ │ │ └── rparen_loc: (19,18)-(19,19) = ")" │ │ │ └── @ MultiTargetNode (location: (19,21)-(19,32)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (19,22)-(19,23)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :d │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (19,25)-(19,28)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (19,25)-(19,26) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (19,26)-(19,28)) @@ -280,11 +304,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (20,0)-(20,3) = "end" ├── @ DefNode (location: (22,0)-(23,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (22,4)-(22,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (22,8)-(22,22)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 2) │ │ │ ├── @ OptionalParameterNode (location: (22,8)-(22,14)) @@ -294,7 +320,7 @@ │ │ │ │ ├── operator_loc: (22,11)-(22,12) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (22,13)-(22,14)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── @ OptionalParameterNode (location: (22,16)-(22,22)) │ │ │ ├── flags: repeated_parameter @@ -303,7 +329,7 @@ │ │ │ ├── operator_loc: (22,19)-(22,20) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (22,21)-(22,22)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) @@ -319,11 +345,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (23,0)-(23,3) = "end" ├── @ DefNode (location: (25,0)-(26,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (25,4)-(25,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (25,8)-(25,16)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -348,11 +376,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (26,0)-(26,3) = "end" ├── @ DefNode (location: (28,0)-(29,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (28,4)-(28,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (28,8)-(28,20)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -364,7 +394,7 @@ │ │ │ │ ├── name_loc: (28,8)-(28,11) = "_a:" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (28,12)-(28,13)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── @ OptionalKeywordParameterNode (location: (28,15)-(28,20)) │ │ │ ├── flags: repeated_parameter @@ -372,7 +402,7 @@ │ │ │ ├── name_loc: (28,15)-(28,18) = "_a:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (28,19)-(28,20)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ @@ -385,11 +415,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (29,0)-(29,3) = "end" ├── @ DefNode (location: (31,0)-(32,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (31,4)-(31,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (31,8)-(31,16)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (31,8)-(31,10)) │ │ │ ├── flags: ∅ @@ -414,11 +446,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (32,0)-(32,3) = "end" ├── @ DefNode (location: (34,0)-(35,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (34,4)-(34,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (34,8)-(34,15)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (34,8)-(34,10)) │ │ │ ├── flags: ∅ @@ -443,11 +477,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (35,0)-(35,3) = "end" └── @ DefNode (location: (37,0)-(38,3)) + ├── flags: newline ├── name: :foo ├── name_loc: (37,4)-(37,7) = "foo" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (37,8)-(37,15)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (37,8)-(37,10)) │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/rescue.txt b/test/prism/snapshots/rescue.txt index 390b08ae0ef..38f692bbeda 100644 --- a/test/prism/snapshots/rescue.txt +++ b/test/prism/snapshots/rescue.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(35,18)) +├── flags: ∅ ├── locals: [:a, :z] └── statements: @ StatementsNode (location: (1,0)-(35,18)) + ├── flags: ∅ └── body: (length: 14) ├── @ RescueModifierNode (location: (1,0)-(1,14)) + │ ├── flags: newline │ ├── expression: │ │ @ CallNode (location: (1,0)-(1,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -18,7 +21,9 @@ │ ├── keyword_loc: (1,4)-(1,10) = "rescue" │ └── rescue_expression: │ @ NilNode (location: (1,11)-(1,14)) + │ └── flags: static_literal ├── @ RescueModifierNode (location: (3,0)-(4,3)) + │ ├── flags: newline │ ├── expression: │ │ @ CallNode (location: (3,0)-(3,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -33,8 +38,9 @@ │ ├── keyword_loc: (3,4)-(3,10) = "rescue" │ └── rescue_expression: │ @ NilNode (location: (4,0)-(4,3)) + │ └── flags: static_literal ├── @ CallNode (location: (6,0)-(6,24)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -44,23 +50,28 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (6,4)-(6,24)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (6,6)-(6,22)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RescueModifierNode (location: (6,6)-(6,22)) + │ │ ├── flags: newline │ │ ├── expression: │ │ │ @ BreakNode (location: (6,6)-(6,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── arguments: ∅ │ │ │ └── keyword_loc: (6,6)-(6,11) = "break" │ │ ├── keyword_loc: (6,12)-(6,18) = "rescue" │ │ └── rescue_expression: │ │ @ NilNode (location: (6,19)-(6,22)) + │ │ └── flags: static_literal │ ├── opening_loc: (6,4)-(6,5) = "{" │ └── closing_loc: (6,23)-(6,24) = "}" ├── @ CallNode (location: (8,0)-(8,23)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -70,22 +81,28 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (8,4)-(8,23)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (8,6)-(8,21)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RescueModifierNode (location: (8,6)-(8,21)) + │ │ ├── flags: newline │ │ ├── expression: │ │ │ @ NextNode (location: (8,6)-(8,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── arguments: ∅ │ │ │ └── keyword_loc: (8,6)-(8,10) = "next" │ │ ├── keyword_loc: (8,11)-(8,17) = "rescue" │ │ └── rescue_expression: │ │ @ NilNode (location: (8,18)-(8,21)) + │ │ └── flags: static_literal │ ├── opening_loc: (8,4)-(8,5) = "{" │ └── closing_loc: (8,22)-(8,23) = "}" ├── @ RescueModifierNode (location: (10,0)-(10,17)) + │ ├── flags: newline │ ├── expression: │ │ @ ReturnNode (location: (10,0)-(10,6)) │ │ ├── flags: ∅ @@ -94,7 +111,9 @@ │ ├── keyword_loc: (10,7)-(10,13) = "rescue" │ └── rescue_expression: │ @ NilNode (location: (10,14)-(10,17)) + │ └── flags: static_literal ├── @ RescueModifierNode (location: (12,0)-(12,19)) + │ ├── flags: newline │ ├── expression: │ │ @ CallNode (location: (12,0)-(12,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -109,14 +128,17 @@ │ ├── keyword_loc: (12,4)-(12,10) = "rescue" │ └── rescue_expression: │ @ OrNode (location: (12,11)-(12,19)) + │ ├── flags: ∅ │ ├── left: │ │ @ NilNode (location: (12,11)-(12,14)) + │ │ └── flags: static_literal │ ├── right: │ │ @ IntegerNode (location: (12,18)-(12,19)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (12,15)-(12,17) = "||" ├── @ RescueModifierNode (location: (14,0)-(14,22)) + │ ├── flags: newline │ ├── expression: │ │ @ CallNode (location: (14,0)-(14,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -131,34 +153,41 @@ │ ├── keyword_loc: (14,4)-(14,10) = "rescue" │ └── rescue_expression: │ @ IfNode (location: (14,11)-(14,22)) + │ ├── flags: newline │ ├── if_keyword_loc: ∅ │ ├── predicate: │ │ @ NilNode (location: (14,11)-(14,14)) + │ │ └── flags: static_literal │ ├── then_keyword_loc: (14,15)-(14,16) = "?" │ ├── statements: │ │ @ StatementsNode (location: (14,17)-(14,18)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (14,17)-(14,18)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 1 - │ ├── consequent: + │ ├── subsequent: │ │ @ ElseNode (location: (14,19)-(14,22)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (14,19)-(14,20) = ":" │ │ ├── statements: │ │ │ @ StatementsNode (location: (14,21)-(14,22)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (14,21)-(14,22)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: newline, static_literal, decimal │ │ │ └── value: 2 │ │ └── end_keyword_loc: ∅ │ └── end_keyword_loc: ∅ ├── @ BeginNode (location: (16,0)-(16,24)) + │ ├── flags: newline │ ├── begin_keyword_loc: (16,0)-(16,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (16,7)-(16,8)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (16,7)-(16,8)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -169,9 +198,11 @@ │ │ └── block: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (16,10)-(16,19)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (16,10)-(16,16) = "rescue" │ │ ├── exceptions: (length: 1) │ │ │ └── @ SplatNode (location: (16,17)-(16,19)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (16,17)-(16,18) = "*" │ │ │ └── expression: │ │ │ @ CallNode (location: (16,18)-(16,19)) @@ -187,12 +218,12 @@ │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (16,21)-(16,24) = "end" ├── @ CallNode (location: (18,0)-(20,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -202,11 +233,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (18,4)-(20,3)) + │ ├── flags: ∅ │ ├── locals: [:x] │ ├── parameters: │ │ @ BlockParametersNode (location: (18,7)-(18,10)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (18,8)-(18,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (18,8)-(18,9)) │ │ │ │ ├── flags: ∅ @@ -222,8 +256,10 @@ │ │ └── closing_loc: (18,9)-(18,10) = "|" │ ├── body: │ │ @ StatementsNode (location: (19,2)-(19,40)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RescueModifierNode (location: (19,2)-(19,40)) + │ │ ├── flags: newline │ │ ├── expression: │ │ │ @ CallNode (location: (19,2)-(19,8)) │ │ │ ├── flags: ignore_visibility @@ -285,14 +321,17 @@ │ ├── opening_loc: (18,4)-(18,6) = "do" │ └── closing_loc: (20,0)-(20,3) = "end" ├── @ IfNode (location: (22,0)-(24,3)) + │ ├── flags: newline │ ├── if_keyword_loc: (22,0)-(22,2) = "if" │ ├── predicate: │ │ @ LocalVariableWriteNode (location: (22,3)-(22,21)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ ├── depth: 0 │ │ ├── name_loc: (22,3)-(22,4) = "a" │ │ ├── value: │ │ │ @ RescueModifierNode (location: (22,7)-(22,21)) + │ │ │ ├── flags: ∅ │ │ │ ├── expression: │ │ │ │ @ CallNode (location: (22,7)-(22,10)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -307,13 +346,15 @@ │ │ │ ├── keyword_loc: (22,11)-(22,17) = "rescue" │ │ │ └── rescue_expression: │ │ │ @ NilNode (location: (22,18)-(22,21)) + │ │ │ └── flags: static_literal │ │ └── operator_loc: (22,5)-(22,6) = "=" │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (23,2)-(23,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (23,2)-(23,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -322,17 +363,20 @@ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: (24,0)-(24,3) = "end" ├── @ DefNode (location: (26,0)-(26,44)) + │ ├── flags: newline │ ├── name: :some_method │ ├── name_loc: (26,4)-(26,15) = "some_method" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (26,18)-(26,44)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RescueModifierNode (location: (26,18)-(26,44)) + │ │ ├── flags: ∅ │ │ ├── expression: │ │ │ @ CallNode (location: (26,18)-(26,33)) │ │ │ ├── flags: ignore_visibility @@ -346,13 +390,14 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (26,31)-(26,33)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 42 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ ├── keyword_loc: (26,34)-(26,40) = "rescue" │ │ └── rescue_expression: │ │ @ NilNode (location: (26,41)-(26,44)) + │ │ └── flags: static_literal │ ├── locals: [] │ ├── def_keyword_loc: (26,0)-(26,3) = "def" │ ├── operator_loc: ∅ @@ -361,18 +406,21 @@ │ ├── equal_loc: (26,16)-(26,17) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (28,0)-(31,3)) + │ ├── flags: newline │ ├── name: :a │ ├── name_loc: (28,4)-(28,5) = "a" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (28,0)-(31,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (29,2)-(29,6)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (29,2)-(29,6)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :a @@ -386,15 +434,17 @@ │ │ │ │ ├── flags: symbol_keys │ │ │ │ └── elements: (length: 1) │ │ │ │ └── @ AssocNode (location: (29,4)-(29,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (29,4)-(29,6)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (29,4)-(29,5) = "b" │ │ │ │ │ ├── closing_loc: (29,5)-(29,6) = ":" │ │ │ │ │ └── unescaped: "b" │ │ │ │ ├── value: │ │ │ │ │ @ ImplicitNode (location: (29,4)-(29,6)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── value: │ │ │ │ │ @ CallNode (location: (29,4)-(29,6)) │ │ │ │ │ ├── flags: ignore_visibility @@ -411,12 +461,13 @@ │ │ │ └── block: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (30,0)-(30,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (30,0)-(30,6) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (31,0)-(31,3) = "end" @@ -428,8 +479,10 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (31,0)-(31,3) = "end" ├── @ RescueModifierNode (location: (33,0)-(33,21)) + │ ├── flags: newline │ ├── expression: │ │ @ IfNode (location: (33,0)-(33,10)) + │ │ ├── flags: newline │ │ ├── if_keyword_loc: (33,4)-(33,6) = "if" │ │ ├── predicate: │ │ │ @ CallNode (location: (33,7)-(33,10)) @@ -445,9 +498,10 @@ │ │ ├── then_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (33,0)-(33,3)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (33,0)-(33,3)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :foo @@ -456,7 +510,7 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ ├── consequent: ∅ + │ │ ├── subsequent: ∅ │ │ └── end_keyword_loc: ∅ │ ├── keyword_loc: (33,11)-(33,17) = "rescue" │ └── rescue_expression: @@ -471,11 +525,13 @@ │ ├── closing_loc: ∅ │ └── block: ∅ └── @ LocalVariableWriteNode (location: (35,0)-(35,18)) + ├── flags: newline ├── name: :z ├── depth: 0 ├── name_loc: (35,0)-(35,1) = "z" ├── value: │ @ RescueModifierNode (location: (35,4)-(35,18)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (35,4)-(35,7)) │ │ ├── flags: ignore_visibility diff --git a/test/prism/snapshots/return.txt b/test/prism/snapshots/return.txt index 0dd26281c1d..fc2bd70fbc5 100644 --- a/test/prism/snapshots/return.txt +++ b/test/prism/snapshots/return.txt @@ -1,165 +1,179 @@ @ ProgramNode (location: (1,0)-(23,9)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(23,9)) + ├── flags: ∅ └── body: (length: 10) ├── @ ReturnNode (location: (1,0)-(1,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (1,0)-(1,6) = "return" │ └── arguments: ∅ ├── @ ReturnNode (location: (3,0)-(3,20)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (3,0)-(3,6) = "return" │ └── arguments: │ @ ArgumentsNode (location: (3,7)-(3,20)) │ ├── flags: ∅ │ └── arguments: (length: 3) │ ├── @ ParenthesesNode (location: (3,7)-(3,10)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (3,8)-(3,9)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (3,8)-(3,9)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: newline, static_literal, decimal │ │ │ └── value: 1 │ │ ├── opening_loc: (3,7)-(3,8) = "(" │ │ └── closing_loc: (3,9)-(3,10) = ")" │ ├── @ ParenthesesNode (location: (3,12)-(3,15)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (3,13)-(3,14)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (3,13)-(3,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: newline, static_literal, decimal │ │ │ └── value: 2 │ │ ├── opening_loc: (3,12)-(3,13) = "(" │ │ └── closing_loc: (3,14)-(3,15) = ")" │ └── @ ParenthesesNode (location: (3,17)-(3,20)) + │ ├── flags: ∅ │ ├── body: │ │ @ StatementsNode (location: (3,18)-(3,19)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (3,18)-(3,19)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 3 │ ├── opening_loc: (3,17)-(3,18) = "(" │ └── closing_loc: (3,19)-(3,20) = ")" ├── @ ReturnNode (location: (5,0)-(5,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (5,0)-(5,6) = "return" │ └── arguments: │ @ ArgumentsNode (location: (5,7)-(5,9)) - │ ├── flags: ∅ + │ ├── flags: contains_splat │ └── arguments: (length: 1) │ └── @ SplatNode (location: (5,7)-(5,9)) + │ ├── flags: ∅ │ ├── operator_loc: (5,7)-(5,8) = "*" │ └── expression: │ @ IntegerNode (location: (5,8)-(5,9)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ ReturnNode (location: (7,0)-(7,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (7,0)-(7,6) = "return" │ └── arguments: │ @ ArgumentsNode (location: (7,7)-(7,8)) │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (7,7)-(7,8)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ ReturnNode (location: (9,0)-(10,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (9,0)-(9,6) = "return" │ └── arguments: │ @ ArgumentsNode (location: (9,7)-(10,1)) │ ├── flags: ∅ │ └── arguments: (length: 3) │ ├── @ IntegerNode (location: (9,7)-(9,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── @ IntegerNode (location: (9,10)-(9,11)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ └── @ IntegerNode (location: (10,0)-(10,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 3 ├── @ ReturnNode (location: (12,0)-(12,14)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (12,0)-(12,6) = "return" │ └── arguments: │ @ ArgumentsNode (location: (12,7)-(12,14)) │ ├── flags: ∅ │ └── arguments: (length: 3) │ ├── @ IntegerNode (location: (12,7)-(12,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── @ IntegerNode (location: (12,10)-(12,11)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ └── @ IntegerNode (location: (12,13)-(12,14)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 3 ├── @ ReturnNode (location: (14,0)-(14,16)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (14,0)-(14,6) = "return" │ └── arguments: │ @ ArgumentsNode (location: (14,7)-(14,16)) │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ ArrayNode (location: (14,7)-(14,16)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 3) │ │ ├── @ IntegerNode (location: (14,8)-(14,9)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── @ IntegerNode (location: (14,11)-(14,12)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── @ IntegerNode (location: (14,14)-(14,15)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ ├── opening_loc: (14,7)-(14,8) = "[" │ └── closing_loc: (14,15)-(14,16) = "]" ├── @ ReturnNode (location: (16,0)-(19,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (16,0)-(16,6) = "return" │ └── arguments: │ @ ArgumentsNode (location: (16,6)-(19,1)) │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ ParenthesesNode (location: (16,6)-(19,1)) + │ ├── flags: ∅ │ ├── body: │ │ @ StatementsNode (location: (17,2)-(18,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 2) │ │ ├── @ IntegerNode (location: (17,2)-(17,3)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: newline, static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (18,2)-(18,3)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: (16,6)-(16,7) = "(" │ └── closing_loc: (19,0)-(19,1) = ")" ├── @ ReturnNode (location: (21,0)-(21,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (21,0)-(21,6) = "return" │ └── arguments: │ @ ArgumentsNode (location: (21,6)-(21,8)) │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ ParenthesesNode (location: (21,6)-(21,8)) + │ ├── flags: ∅ │ ├── body: ∅ │ ├── opening_loc: (21,6)-(21,7) = "(" │ └── closing_loc: (21,7)-(21,8) = ")" └── @ ReturnNode (location: (23,0)-(23,9)) - ├── flags: ∅ + ├── flags: newline ├── keyword_loc: (23,0)-(23,6) = "return" └── arguments: @ ArgumentsNode (location: (23,6)-(23,9)) ├── flags: ∅ └── arguments: (length: 1) └── @ ParenthesesNode (location: (23,6)-(23,9)) + ├── flags: ∅ ├── body: │ @ StatementsNode (location: (23,7)-(23,8)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ IntegerNode (location: (23,7)-(23,8)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 1 ├── opening_loc: (23,6)-(23,7) = "(" └── closing_loc: (23,8)-(23,9) = ")" diff --git a/test/prism/snapshots/seattlerb/BEGIN.txt b/test/prism/snapshots/seattlerb/BEGIN.txt index 246f39cbba8..a0d73a8039b 100644 --- a/test/prism/snapshots/seattlerb/BEGIN.txt +++ b/test/prism/snapshots/seattlerb/BEGIN.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,12)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,12)) + ├── flags: ∅ └── body: (length: 1) └── @ PreExecutionNode (location: (1,0)-(1,12)) + ├── flags: newline ├── statements: │ @ StatementsNode (location: (1,8)-(1,10)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,8)-(1,10)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 42 ├── keyword_loc: (1,0)-(1,5) = "BEGIN" ├── opening_loc: (1,6)-(1,7) = "{" diff --git a/test/prism/snapshots/seattlerb/TestRubyParserShared.txt b/test/prism/snapshots/seattlerb/TestRubyParserShared.txt index fabc92e4779..7a488a20aab 100644 --- a/test/prism/snapshots/seattlerb/TestRubyParserShared.txt +++ b/test/prism/snapshots/seattlerb/TestRubyParserShared.txt @@ -1,24 +1,26 @@ @ ProgramNode (location: (1,0)-(92,1)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(92,1)) + ├── flags: ∅ └── body: (length: 16) ├── @ ArrayNode (location: (1,0)-(4,1)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 0) │ ├── opening_loc: (1,0)-(1,3) = "%I[" │ └── closing_loc: (4,0)-(4,1) = "]" ├── @ ArrayNode (location: (6,0)-(9,1)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (7,0)-(7,5)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (7,0)-(7,5) = "line2" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "line2" │ │ └── @ SymbolNode (location: (8,0)-(8,5)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (8,0)-(8,5) = "line3" │ │ ├── closing_loc: ∅ @@ -26,12 +28,12 @@ │ ├── opening_loc: (6,0)-(6,3) = "%I[" │ └── closing_loc: (9,0)-(9,1) = "]" ├── @ ArrayNode (location: (11,0)-(14,1)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 0) │ ├── opening_loc: (11,0)-(11,3) = "%W[" │ └── closing_loc: (14,0)-(14,1) = "]" ├── @ ArrayNode (location: (16,0)-(19,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 2) │ │ ├── @ StringNode (location: (17,0)-(17,5)) │ │ │ ├── flags: ∅ @@ -48,21 +50,21 @@ │ ├── opening_loc: (16,0)-(16,3) = "%W[" │ └── closing_loc: (19,0)-(19,1) = "]" ├── @ ArrayNode (location: (21,0)-(24,1)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 0) │ ├── opening_loc: (21,0)-(21,3) = "%i[" │ └── closing_loc: (24,0)-(24,1) = "]" ├── @ ArrayNode (location: (26,0)-(29,1)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (27,0)-(27,5)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (27,0)-(27,5) = "line2" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "line2" │ │ └── @ SymbolNode (location: (28,0)-(28,5)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (28,0)-(28,5) = "line3" │ │ ├── closing_loc: ∅ @@ -70,18 +72,18 @@ │ ├── opening_loc: (26,0)-(26,3) = "%i[" │ └── closing_loc: (29,0)-(29,1) = "]" ├── @ RegularExpressionNode (location: (31,0)-(34,1)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (31,0)-(31,3) = "%r[" │ ├── content_loc: (31,3)-(34,0) = "\n\n\n" │ ├── closing_loc: (34,0)-(34,1) = "]" │ └── unescaped: "\n\n\n" ├── @ ArrayNode (location: (36,0)-(39,1)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 0) │ ├── opening_loc: (36,0)-(36,3) = "%w[" │ └── closing_loc: (39,0)-(39,1) = "]" ├── @ ArrayNode (location: (41,0)-(44,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 2) │ │ ├── @ StringNode (location: (42,0)-(42,5)) │ │ │ ├── flags: ∅ @@ -98,16 +100,16 @@ │ ├── opening_loc: (41,0)-(41,3) = "%w[" │ └── closing_loc: (44,0)-(44,1) = "]" ├── @ ArrayNode (location: (46,0)-(49,1)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (47,0)-(47,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (47,0)-(47,1) = ":" │ │ │ ├── value_loc: (47,1)-(47,6) = "line2" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "line2" │ │ └── @ SymbolNode (location: (48,0)-(48,6)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (48,0)-(48,1) = ":" │ │ ├── value_loc: (48,1)-(48,6) = "line3" │ │ ├── closing_loc: ∅ @@ -115,23 +117,29 @@ │ ├── opening_loc: (46,0)-(46,1) = "[" │ └── closing_loc: (49,0)-(49,1) = "]" ├── @ ClassNode (location: (51,0)-(56,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (51,0)-(51,5) = "class" │ ├── constant_path: │ │ @ ConstantReadNode (location: (51,6)-(51,7)) + │ │ ├── flags: ∅ │ │ └── name: :X │ ├── inheritance_operator_loc: ∅ │ ├── superclass: ∅ │ ├── body: │ │ @ StatementsNode (location: (52,2)-(55,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ DefNode (location: (52,2)-(55,5)) + │ │ ├── flags: newline │ │ ├── name: :y │ │ ├── name_loc: (52,11)-(52,12) = "y" │ │ ├── receiver: │ │ │ @ SelfNode (location: (52,6)-(52,10)) + │ │ │ └── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (52,13)-(53,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (52,13)-(52,14)) │ │ │ │ │ ├── flags: ∅ @@ -147,11 +155,13 @@ │ │ │ └── block: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (54,4)-(54,9)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (54,4)-(54,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ LocalVariableReadNode (location: (54,4)-(54,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ └── depth: 0 │ │ │ ├── call_operator_loc: ∅ @@ -163,6 +173,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ LocalVariableReadNode (location: (54,8)-(54,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :b │ │ │ │ └── depth: 0 │ │ │ ├── closing_loc: ∅ @@ -177,33 +188,40 @@ │ ├── end_keyword_loc: (56,0)-(56,3) = "end" │ └── name: :X ├── @ ClassNode (location: (59,0)-(63,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (59,0)-(59,5) = "class" │ ├── constant_path: │ │ @ ConstantReadNode (location: (59,6)-(59,7)) + │ │ ├── flags: ∅ │ │ └── name: :X │ ├── inheritance_operator_loc: ∅ │ ├── superclass: ∅ │ ├── body: │ │ @ StatementsNode (location: (60,2)-(62,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ ClassNode (location: (60,2)-(62,5)) + │ │ ├── flags: newline │ │ ├── locals: [] │ │ ├── class_keyword_loc: (60,2)-(60,7) = "class" │ │ ├── constant_path: │ │ │ @ ConstantReadNode (location: (60,8)-(60,9)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Y │ │ ├── inheritance_operator_loc: ∅ │ │ ├── superclass: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (61,4)-(61,10)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ ConstantWriteNode (location: (61,4)-(61,10)) + │ │ │ ├── flags: newline │ │ │ ├── name: :Z │ │ │ ├── name_loc: (61,4)-(61,5) = "Z" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (61,8)-(61,10)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 42 │ │ │ └── operator_loc: (61,6)-(61,7) = "=" │ │ ├── end_keyword_loc: (62,2)-(62,5) = "end" @@ -211,22 +229,27 @@ │ ├── end_keyword_loc: (63,0)-(63,3) = "end" │ └── name: :X ├── @ ClassNode (location: (66,0)-(71,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (66,0)-(66,5) = "class" │ ├── constant_path: │ │ @ ConstantReadNode (location: (66,6)-(66,7)) + │ │ ├── flags: ∅ │ │ └── name: :X │ ├── inheritance_operator_loc: ∅ │ ├── superclass: ∅ │ ├── body: │ │ @ StatementsNode (location: (67,2)-(70,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ DefNode (location: (67,2)-(70,5)) + │ │ ├── flags: newline │ │ ├── name: :y │ │ ├── name_loc: (67,6)-(67,7) = "y" │ │ ├── receiver: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (67,8)-(68,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (67,8)-(67,9)) │ │ │ │ │ ├── flags: ∅ @@ -242,11 +265,13 @@ │ │ │ └── block: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (69,4)-(69,9)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (69,4)-(69,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ LocalVariableReadNode (location: (69,4)-(69,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ └── depth: 0 │ │ │ ├── call_operator_loc: ∅ @@ -258,6 +283,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ LocalVariableReadNode (location: (69,8)-(69,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :b │ │ │ │ └── depth: 0 │ │ │ ├── closing_loc: ∅ @@ -272,29 +298,33 @@ │ ├── end_keyword_loc: (71,0)-(71,3) = "end" │ └── name: :X ├── @ ModuleNode (location: (74,0)-(79,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── module_keyword_loc: (74,0)-(74,6) = "module" │ ├── constant_path: │ │ @ ConstantReadNode (location: (74,7)-(74,8)) + │ │ ├── flags: ∅ │ │ └── name: :X │ ├── body: │ │ @ StatementsNode (location: (75,2)-(78,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ ConstantWriteNode (location: (75,2)-(78,3)) + │ │ ├── flags: newline │ │ ├── name: :X │ │ ├── name_loc: (75,2)-(75,3) = "X" │ │ ├── value: │ │ │ @ ArrayNode (location: (75,6)-(78,3)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: static_literal │ │ │ ├── elements: (length: 2) │ │ │ │ ├── @ SymbolNode (location: (76,4)-(76,10)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (76,4)-(76,5) = ":" │ │ │ │ │ ├── value_loc: (76,5)-(76,10) = "line3" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "line3" │ │ │ │ └── @ SymbolNode (location: (77,4)-(77,10)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (77,4)-(77,5) = ":" │ │ │ │ ├── value_loc: (77,5)-(77,10) = "line4" │ │ │ │ ├── closing_loc: ∅ @@ -305,29 +335,36 @@ │ ├── end_keyword_loc: (79,0)-(79,3) = "end" │ └── name: :X ├── @ ModuleNode (location: (82,0)-(86,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── module_keyword_loc: (82,0)-(82,6) = "module" │ ├── constant_path: │ │ @ ConstantReadNode (location: (82,7)-(82,8)) + │ │ ├── flags: ∅ │ │ └── name: :X │ ├── body: │ │ @ StatementsNode (location: (83,2)-(85,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ ModuleNode (location: (83,2)-(85,5)) + │ │ ├── flags: newline │ │ ├── locals: [] │ │ ├── module_keyword_loc: (83,2)-(83,8) = "module" │ │ ├── constant_path: │ │ │ @ ConstantReadNode (location: (83,9)-(83,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Y │ │ ├── body: │ │ │ @ StatementsNode (location: (84,4)-(84,10)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ ConstantWriteNode (location: (84,4)-(84,10)) + │ │ │ ├── flags: newline │ │ │ ├── name: :Z │ │ │ ├── name_loc: (84,4)-(84,5) = "Z" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (84,8)-(84,10)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 42 │ │ │ └── operator_loc: (84,6)-(84,7) = "=" │ │ ├── end_keyword_loc: (85,2)-(85,5) = "end" @@ -335,7 +372,7 @@ │ ├── end_keyword_loc: (86,0)-(86,3) = "end" │ └── name: :X └── @ CallNode (location: (89,0)-(92,1)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :x @@ -346,13 +383,13 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ SymbolNode (location: (90,0)-(90,6)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (90,0)-(90,1) = ":" │ │ ├── value_loc: (90,1)-(90,6) = "line2" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "line2" │ └── @ SymbolNode (location: (91,0)-(91,6)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (91,0)-(91,1) = ":" │ ├── value_loc: (91,1)-(91,6) = "line3" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/__ENCODING__.txt b/test/prism/snapshots/seattlerb/__ENCODING__.txt index 1b223bd8fe7..f04dfb6cb86 100644 --- a/test/prism/snapshots/seattlerb/__ENCODING__.txt +++ b/test/prism/snapshots/seattlerb/__ENCODING__.txt @@ -1,6 +1,9 @@ @ ProgramNode (location: (1,0)-(1,12)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,12)) + ├── flags: ∅ └── body: (length: 1) └── @ SourceEncodingNode (location: (1,0)-(1,12)) + └── flags: newline, static_literal diff --git a/test/prism/snapshots/seattlerb/alias_gvar_backref.txt b/test/prism/snapshots/seattlerb/alias_gvar_backref.txt index a2586423d78..47b0e80b644 100644 --- a/test/prism/snapshots/seattlerb/alias_gvar_backref.txt +++ b/test/prism/snapshots/seattlerb/alias_gvar_backref.txt @@ -1,13 +1,18 @@ @ ProgramNode (location: (1,0)-(1,15)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,15)) + ├── flags: ∅ └── body: (length: 1) └── @ AliasGlobalVariableNode (location: (1,0)-(1,15)) + ├── flags: newline ├── new_name: │ @ GlobalVariableReadNode (location: (1,6)-(1,12)) + │ ├── flags: ∅ │ └── name: :$MATCH ├── old_name: │ @ BackReferenceReadNode (location: (1,13)-(1,15)) + │ ├── flags: ∅ │ └── name: :$& └── keyword_loc: (1,0)-(1,5) = "alias" diff --git a/test/prism/snapshots/seattlerb/alias_resword.txt b/test/prism/snapshots/seattlerb/alias_resword.txt index 99ed696c687..44a4727283e 100644 --- a/test/prism/snapshots/seattlerb/alias_resword.txt +++ b/test/prism/snapshots/seattlerb/alias_resword.txt @@ -1,19 +1,22 @@ @ ProgramNode (location: (1,0)-(1,12)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,12)) + ├── flags: ∅ └── body: (length: 1) └── @ AliasMethodNode (location: (1,0)-(1,12)) + ├── flags: newline ├── new_name: │ @ SymbolNode (location: (1,6)-(1,8)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: ∅ │ ├── value_loc: (1,6)-(1,8) = "in" │ ├── closing_loc: ∅ │ └── unescaped: "in" ├── old_name: │ @ SymbolNode (location: (1,9)-(1,12)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: ∅ │ ├── value_loc: (1,9)-(1,12) = "out" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/and_multi.txt b/test/prism/snapshots/seattlerb/and_multi.txt index b60b131fd2d..f98ad67e102 100644 --- a/test/prism/snapshots/seattlerb/and_multi.txt +++ b/test/prism/snapshots/seattlerb/and_multi.txt @@ -1,18 +1,24 @@ @ ProgramNode (location: (1,0)-(3,4)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,4)) + ├── flags: ∅ └── body: (length: 1) └── @ AndNode (location: (1,0)-(3,4)) + ├── flags: newline ├── left: │ @ AndNode (location: (1,0)-(2,9)) + │ ├── flags: ∅ │ ├── left: │ │ @ TrueNode (location: (1,0)-(1,4)) + │ │ └── flags: static_literal │ ├── right: │ │ @ CallNode (location: (2,0)-(2,9)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ FalseNode (location: (2,4)-(2,9)) + │ │ │ └── flags: static_literal │ │ ├── call_operator_loc: ∅ │ │ ├── name: :! │ │ ├── message_loc: (2,0)-(2,3) = "not" @@ -23,4 +29,5 @@ │ └── operator_loc: (1,5)-(1,8) = "and" ├── right: │ @ TrueNode (location: (3,0)-(3,4)) + │ └── flags: static_literal └── operator_loc: (2,10)-(2,13) = "and" diff --git a/test/prism/snapshots/seattlerb/aref_args_assocs.txt b/test/prism/snapshots/seattlerb/aref_args_assocs.txt index b729186dc5e..cbd07920379 100644 --- a/test/prism/snapshots/seattlerb/aref_args_assocs.txt +++ b/test/prism/snapshots/seattlerb/aref_args_assocs.txt @@ -1,22 +1,25 @@ @ ProgramNode (location: (1,0)-(1,8)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,8)) + ├── flags: ∅ └── body: (length: 1) └── @ ArrayNode (location: (1,0)-(1,8)) - ├── flags: ∅ + ├── flags: newline ├── elements: (length: 1) │ └── @ KeywordHashNode (location: (1,1)-(1,7)) │ ├── flags: ∅ │ └── elements: (length: 1) │ └── @ AssocNode (location: (1,1)-(1,7)) + │ ├── flags: static_literal │ ├── key: │ │ @ IntegerNode (location: (1,1)-(1,2)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── value: │ │ @ IntegerNode (location: (1,6)-(1,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ └── operator_loc: (1,3)-(1,5) = "=>" ├── opening_loc: (1,0)-(1,1) = "[" diff --git a/test/prism/snapshots/seattlerb/aref_args_lit_assocs.txt b/test/prism/snapshots/seattlerb/aref_args_lit_assocs.txt index 0e9454d780b..7302f728e3b 100644 --- a/test/prism/snapshots/seattlerb/aref_args_lit_assocs.txt +++ b/test/prism/snapshots/seattlerb/aref_args_lit_assocs.txt @@ -1,25 +1,28 @@ @ ProgramNode (location: (1,0)-(1,11)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,11)) + ├── flags: ∅ └── body: (length: 1) └── @ ArrayNode (location: (1,0)-(1,11)) - ├── flags: ∅ + ├── flags: newline ├── elements: (length: 2) │ ├── @ IntegerNode (location: (1,1)-(1,2)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── @ KeywordHashNode (location: (1,4)-(1,10)) │ ├── flags: ∅ │ └── elements: (length: 1) │ └── @ AssocNode (location: (1,4)-(1,10)) + │ ├── flags: static_literal │ ├── key: │ │ @ IntegerNode (location: (1,4)-(1,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── value: │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ └── operator_loc: (1,6)-(1,8) = "=>" ├── opening_loc: (1,0)-(1,1) = "[" diff --git a/test/prism/snapshots/seattlerb/args_kw_block.txt b/test/prism/snapshots/seattlerb/args_kw_block.txt index 1ad933c74e3..88081dfa145 100644 --- a/test/prism/snapshots/seattlerb/args_kw_block.txt +++ b/test/prism/snapshots/seattlerb/args_kw_block.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,20)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,20)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,20)) + ├── flags: newline ├── name: :f ├── name_loc: (1,4)-(1,5) = "f" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,14)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -20,7 +24,7 @@ │ │ ├── name_loc: (1,6)-(1,8) = "a:" │ │ └── value: │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── keyword_rest: ∅ │ └── block: diff --git a/test/prism/snapshots/seattlerb/array_line_breaks.txt b/test/prism/snapshots/seattlerb/array_line_breaks.txt index 880fedf9330..a2d21e90ad6 100644 --- a/test/prism/snapshots/seattlerb/array_line_breaks.txt +++ b/test/prism/snapshots/seattlerb/array_line_breaks.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(4,1)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,1)) + ├── flags: ∅ └── body: (length: 2) ├── @ ArrayNode (location: (1,0)-(3,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 2) │ │ ├── @ StringNode (location: (2,0)-(2,3)) │ │ │ ├── flags: ∅ @@ -21,5 +23,5 @@ │ ├── opening_loc: (1,0)-(1,1) = "[" │ └── closing_loc: (3,3)-(3,4) = "]" └── @ IntegerNode (location: (4,0)-(4,1)) - ├── flags: decimal + ├── flags: newline, static_literal, decimal └── value: 1 diff --git a/test/prism/snapshots/seattlerb/array_lits_trailing_calls.txt b/test/prism/snapshots/seattlerb/array_lits_trailing_calls.txt index d46a181fc76..2de5a054a66 100644 --- a/test/prism/snapshots/seattlerb/array_lits_trailing_calls.txt +++ b/test/prism/snapshots/seattlerb/array_lits_trailing_calls.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(3,4)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,4)) + ├── flags: ∅ └── body: (length: 2) ├── @ CallNode (location: (1,0)-(1,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ArrayNode (location: (1,0)-(1,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── elements: (length: 0) │ │ ├── opening_loc: (1,0)-(1,3) = "%w[" │ │ └── closing_loc: (1,3)-(1,4) = "]" @@ -19,10 +21,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ └── @ CallNode (location: (3,0)-(3,4)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ ArrayNode (location: (3,0)-(3,2)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 0) │ ├── opening_loc: (3,0)-(3,1) = "[" │ └── closing_loc: (3,1)-(3,2) = "]" diff --git a/test/prism/snapshots/seattlerb/assoc__bare.txt b/test/prism/snapshots/seattlerb/assoc__bare.txt index 28e4f713c51..530360ef66f 100644 --- a/test/prism/snapshots/seattlerb/assoc__bare.txt +++ b/test/prism/snapshots/seattlerb/assoc__bare.txt @@ -1,21 +1,26 @@ @ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ └── body: (length: 1) └── @ HashNode (location: (1,0)-(1,6)) + ├── flags: newline ├── opening_loc: (1,0)-(1,1) = "{" ├── elements: (length: 1) │ └── @ AssocNode (location: (1,2)-(1,4)) + │ ├── flags: ∅ │ ├── key: │ │ @ SymbolNode (location: (1,2)-(1,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,2)-(1,3) = "y" │ │ ├── closing_loc: (1,3)-(1,4) = ":" │ │ └── unescaped: "y" │ ├── value: │ │ @ ImplicitNode (location: (1,2)-(1,4)) + │ │ ├── flags: ∅ │ │ └── value: │ │ @ CallNode (location: (1,2)-(1,4)) │ │ ├── flags: ignore_visibility diff --git a/test/prism/snapshots/seattlerb/assoc_label.txt b/test/prism/snapshots/seattlerb/assoc_label.txt index 70490c0da4c..91b94bbc1cc 100644 --- a/test/prism/snapshots/seattlerb/assoc_label.txt +++ b/test/prism/snapshots/seattlerb/assoc_label.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,6)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -18,16 +20,17 @@ │ ├── flags: symbol_keys │ └── elements: (length: 1) │ └── @ AssocNode (location: (1,2)-(1,5)) + │ ├── flags: static_literal │ ├── key: │ │ @ SymbolNode (location: (1,2)-(1,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,2)-(1,3) = "b" │ │ ├── closing_loc: (1,3)-(1,4) = ":" │ │ └── unescaped: "b" │ ├── value: │ │ @ IntegerNode (location: (1,4)-(1,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: ∅ ├── closing_loc: (1,5)-(1,6) = ")" diff --git a/test/prism/snapshots/seattlerb/attr_asgn_colon_id.txt b/test/prism/snapshots/seattlerb/attr_asgn_colon_id.txt index 589433eda89..67802fc8a4e 100644 --- a/test/prism/snapshots/seattlerb/attr_asgn_colon_id.txt +++ b/test/prism/snapshots/seattlerb/attr_asgn_colon_id.txt @@ -1,12 +1,15 @@ @ ProgramNode (location: (1,0)-(1,8)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,8)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,8)) - ├── flags: attribute_write + ├── flags: newline, attribute_write ├── receiver: │ @ ConstantReadNode (location: (1,0)-(1,1)) + │ ├── flags: ∅ │ └── name: :A ├── call_operator_loc: (1,1)-(1,3) = "::" ├── name: :b= @@ -17,7 +20,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,7)-(1,8)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/attrasgn_array_arg.txt b/test/prism/snapshots/seattlerb/attrasgn_array_arg.txt index 9b04ae9656e..43853b4ef91 100644 --- a/test/prism/snapshots/seattlerb/attrasgn_array_arg.txt +++ b/test/prism/snapshots/seattlerb/attrasgn_array_arg.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,13)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,13)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,13)) - ├── flags: attribute_write + ├── flags: newline, attribute_write ├── receiver: │ @ CallNode (location: (1,0)-(1,1)) │ ├── flags: variable_call, ignore_visibility @@ -25,18 +27,18 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ ArrayNode (location: (1,2)-(1,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── elements: (length: 2) │ │ │ ├── @ IntegerNode (location: (1,3)-(1,4)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── opening_loc: (1,2)-(1,3) = "[" │ │ └── closing_loc: (1,7)-(1,8) = "]" │ └── @ IntegerNode (location: (1,12)-(1,13)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 3 ├── closing_loc: (1,8)-(1,9) = "]" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/attrasgn_array_lhs.txt b/test/prism/snapshots/seattlerb/attrasgn_array_lhs.txt index 39544e98da2..5729407edc1 100644 --- a/test/prism/snapshots/seattlerb/attrasgn_array_lhs.txt +++ b/test/prism/snapshots/seattlerb/attrasgn_array_lhs.txt @@ -1,25 +1,27 @@ @ ProgramNode (location: (1,0)-(1,42)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,42)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,42)) - ├── flags: attribute_write + ├── flags: newline, attribute_write ├── receiver: │ @ ArrayNode (location: (1,0)-(1,12)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 4) │ │ ├── @ IntegerNode (location: (1,1)-(1,2)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── @ IntegerNode (location: (1,4)-(1,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── @ IntegerNode (location: (1,7)-(1,8)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 4 │ ├── opening_loc: (1,0)-(1,1) = "[" │ └── closing_loc: (1,11)-(1,12) = "]" diff --git a/test/prism/snapshots/seattlerb/attrasgn_primary_dot_constant.txt b/test/prism/snapshots/seattlerb/attrasgn_primary_dot_constant.txt index d4c4fe10705..2c06df2609b 100644 --- a/test/prism/snapshots/seattlerb/attrasgn_primary_dot_constant.txt +++ b/test/prism/snapshots/seattlerb/attrasgn_primary_dot_constant.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,7)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,7)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,7)) - ├── flags: attribute_write + ├── flags: newline, attribute_write ├── receiver: │ @ CallNode (location: (1,0)-(1,1)) │ ├── flags: variable_call, ignore_visibility @@ -25,7 +27,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/backticks_interpolation_line.txt b/test/prism/snapshots/seattlerb/backticks_interpolation_line.txt index 67c8be034eb..8c6a163c48a 100644 --- a/test/prism/snapshots/seattlerb/backticks_interpolation_line.txt +++ b/test/prism/snapshots/seattlerb/backticks_interpolation_line.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,8)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,8)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,8)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :x @@ -15,12 +17,15 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ InterpolatedXStringNode (location: (1,2)-(1,8)) + │ ├── flags: ∅ │ ├── opening_loc: (1,2)-(1,3) = "`" │ ├── parts: (length: 1) │ │ └── @ EmbeddedStatementsNode (location: (1,3)-(1,7)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (1,3)-(1,5) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (1,5)-(1,6)) │ │ │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/seattlerb/bang_eq.txt b/test/prism/snapshots/seattlerb/bang_eq.txt index ec3dd888b27..6bbd4a6ea22 100644 --- a/test/prism/snapshots/seattlerb/bang_eq.txt +++ b/test/prism/snapshots/seattlerb/bang_eq.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,6)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :!= @@ -18,7 +20,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/bdot2.txt b/test/prism/snapshots/seattlerb/bdot2.txt index d4fb86fbe66..b1c05c0fc46 100644 --- a/test/prism/snapshots/seattlerb/bdot2.txt +++ b/test/prism/snapshots/seattlerb/bdot2.txt @@ -1,18 +1,20 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 3) ├── @ RangeNode (location: (1,0)-(1,4)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── left: ∅ │ ├── right: │ │ @ IntegerNode (location: (1,2)-(1,4)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 10 │ └── operator_loc: (1,0)-(1,2) = ".." ├── @ RangeNode (location: (2,2)-(2,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── left: ∅ │ ├── right: │ │ @ CallNode (location: (2,4)-(2,5)) @@ -27,7 +29,7 @@ │ │ └── block: ∅ │ └── operator_loc: (2,2)-(2,4) = ".." └── @ CallNode (location: (3,2)-(3,3)) - ├── flags: variable_call, ignore_visibility + ├── flags: newline, variable_call, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :c diff --git a/test/prism/snapshots/seattlerb/bdot3.txt b/test/prism/snapshots/seattlerb/bdot3.txt index 0c960f04587..0b35268f19a 100644 --- a/test/prism/snapshots/seattlerb/bdot3.txt +++ b/test/prism/snapshots/seattlerb/bdot3.txt @@ -1,18 +1,20 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 3) ├── @ RangeNode (location: (1,0)-(1,5)) - │ ├── flags: exclude_end + │ ├── flags: newline, static_literal, exclude_end │ ├── left: ∅ │ ├── right: │ │ @ IntegerNode (location: (1,3)-(1,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 10 │ └── operator_loc: (1,0)-(1,3) = "..." ├── @ RangeNode (location: (2,2)-(2,6)) - │ ├── flags: exclude_end + │ ├── flags: newline, exclude_end │ ├── left: ∅ │ ├── right: │ │ @ CallNode (location: (2,5)-(2,6)) @@ -27,7 +29,7 @@ │ │ └── block: ∅ │ └── operator_loc: (2,2)-(2,5) = "..." └── @ CallNode (location: (3,2)-(3,3)) - ├── flags: variable_call, ignore_visibility + ├── flags: newline, variable_call, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :c diff --git a/test/prism/snapshots/seattlerb/begin_ensure_no_bodies.txt b/test/prism/snapshots/seattlerb/begin_ensure_no_bodies.txt index e1698d0baef..6ebcc2e0527 100644 --- a/test/prism/snapshots/seattlerb/begin_ensure_no_bodies.txt +++ b/test/prism/snapshots/seattlerb/begin_ensure_no_bodies.txt @@ -1,15 +1,19 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ BeginNode (location: (1,0)-(3,3)) + ├── flags: newline ├── begin_keyword_loc: (1,0)-(1,5) = "begin" ├── statements: ∅ ├── rescue_clause: ∅ ├── else_clause: ∅ ├── ensure_clause: │ @ EnsureNode (location: (2,0)-(3,3)) + │ ├── flags: ∅ │ ├── ensure_keyword_loc: (2,0)-(2,6) = "ensure" │ ├── statements: ∅ │ └── end_keyword_loc: (3,0)-(3,3) = "end" diff --git a/test/prism/snapshots/seattlerb/begin_rescue_else_ensure_bodies.txt b/test/prism/snapshots/seattlerb/begin_rescue_else_ensure_bodies.txt index 6603e5c8945..9fda6c10e60 100644 --- a/test/prism/snapshots/seattlerb/begin_rescue_else_ensure_bodies.txt +++ b/test/prism/snapshots/seattlerb/begin_rescue_else_ensure_bodies.txt @@ -1,47 +1,57 @@ @ ProgramNode (location: (1,0)-(9,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(9,3)) + ├── flags: ∅ └── body: (length: 1) └── @ BeginNode (location: (1,0)-(9,3)) + ├── flags: newline ├── begin_keyword_loc: (1,0)-(1,5) = "begin" ├── statements: │ @ StatementsNode (location: (2,2)-(2,3)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ IntegerNode (location: (2,2)-(2,3)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 1 ├── rescue_clause: │ @ RescueNode (location: (3,0)-(4,3)) + │ ├── flags: ∅ │ ├── keyword_loc: (3,0)-(3,6) = "rescue" │ ├── exceptions: (length: 0) │ ├── operator_loc: ∅ │ ├── reference: ∅ │ ├── statements: │ │ @ StatementsNode (location: (4,2)-(4,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (4,2)-(4,3)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 2 - │ └── consequent: ∅ + │ └── subsequent: ∅ ├── else_clause: │ @ ElseNode (location: (5,0)-(7,6)) + │ ├── flags: ∅ │ ├── else_keyword_loc: (5,0)-(5,4) = "else" │ ├── statements: │ │ @ StatementsNode (location: (6,2)-(6,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (6,2)-(6,3)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 3 │ └── end_keyword_loc: (7,0)-(7,6) = "ensure" ├── ensure_clause: │ @ EnsureNode (location: (7,0)-(9,3)) + │ ├── flags: ∅ │ ├── ensure_keyword_loc: (7,0)-(7,6) = "ensure" │ ├── statements: │ │ @ StatementsNode (location: (8,2)-(8,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (8,2)-(8,3)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 4 │ └── end_keyword_loc: (9,0)-(9,3) = "end" └── end_keyword_loc: (9,0)-(9,3) = "end" diff --git a/test/prism/snapshots/seattlerb/begin_rescue_else_ensure_no_bodies.txt b/test/prism/snapshots/seattlerb/begin_rescue_else_ensure_no_bodies.txt index 02e1f097ac4..356d1ea9ab1 100644 --- a/test/prism/snapshots/seattlerb/begin_rescue_else_ensure_no_bodies.txt +++ b/test/prism/snapshots/seattlerb/begin_rescue_else_ensure_no_bodies.txt @@ -1,26 +1,32 @@ @ ProgramNode (location: (1,0)-(9,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(9,3)) + ├── flags: ∅ └── body: (length: 1) └── @ BeginNode (location: (1,0)-(9,3)) + ├── flags: newline ├── begin_keyword_loc: (1,0)-(1,5) = "begin" ├── statements: ∅ ├── rescue_clause: │ @ RescueNode (location: (3,0)-(3,6)) + │ ├── flags: ∅ │ ├── keyword_loc: (3,0)-(3,6) = "rescue" │ ├── exceptions: (length: 0) │ ├── operator_loc: ∅ │ ├── reference: ∅ │ ├── statements: ∅ - │ └── consequent: ∅ + │ └── subsequent: ∅ ├── else_clause: │ @ ElseNode (location: (5,0)-(7,6)) + │ ├── flags: ∅ │ ├── else_keyword_loc: (5,0)-(5,4) = "else" │ ├── statements: ∅ │ └── end_keyword_loc: (7,0)-(7,6) = "ensure" ├── ensure_clause: │ @ EnsureNode (location: (7,0)-(9,3)) + │ ├── flags: ∅ │ ├── ensure_keyword_loc: (7,0)-(7,6) = "ensure" │ ├── statements: ∅ │ └── end_keyword_loc: (9,0)-(9,3) = "end" diff --git a/test/prism/snapshots/seattlerb/begin_rescue_ensure_no_bodies.txt b/test/prism/snapshots/seattlerb/begin_rescue_ensure_no_bodies.txt index b36fe5c1fef..aa744870e79 100644 --- a/test/prism/snapshots/seattlerb/begin_rescue_ensure_no_bodies.txt +++ b/test/prism/snapshots/seattlerb/begin_rescue_ensure_no_bodies.txt @@ -1,22 +1,27 @@ @ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ └── body: (length: 1) └── @ BeginNode (location: (1,0)-(4,3)) + ├── flags: newline ├── begin_keyword_loc: (1,0)-(1,5) = "begin" ├── statements: ∅ ├── rescue_clause: │ @ RescueNode (location: (2,0)-(2,6)) + │ ├── flags: ∅ │ ├── keyword_loc: (2,0)-(2,6) = "rescue" │ ├── exceptions: (length: 0) │ ├── operator_loc: ∅ │ ├── reference: ∅ │ ├── statements: ∅ - │ └── consequent: ∅ + │ └── subsequent: ∅ ├── else_clause: ∅ ├── ensure_clause: │ @ EnsureNode (location: (3,0)-(4,3)) + │ ├── flags: ∅ │ ├── ensure_keyword_loc: (3,0)-(3,6) = "ensure" │ ├── statements: ∅ │ └── end_keyword_loc: (4,0)-(4,3) = "end" diff --git a/test/prism/snapshots/seattlerb/block_arg__bare.txt b/test/prism/snapshots/seattlerb/block_arg__bare.txt index 165c2980be3..ceafdcebbc5 100644 --- a/test/prism/snapshots/seattlerb/block_arg__bare.txt +++ b/test/prism/snapshots/seattlerb/block_arg__bare.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,13)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,13)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,13)) + ├── flags: newline ├── name: :x ├── name_loc: (1,4)-(1,5) = "x" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,7)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/block_arg_kwsplat.txt b/test/prism/snapshots/seattlerb/block_arg_kwsplat.txt index 392de8559b9..20756c8378c 100644 --- a/test/prism/snapshots/seattlerb/block_arg_kwsplat.txt +++ b/test/prism/snapshots/seattlerb/block_arg_kwsplat.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,11)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,11)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,11)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,11)) + ├── flags: ∅ ├── locals: [:b] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,9)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,8)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/block_arg_opt_arg_block.txt b/test/prism/snapshots/seattlerb/block_arg_opt_arg_block.txt index ee9644d59d8..dd89df907da 100644 --- a/test/prism/snapshots/seattlerb/block_arg_opt_arg_block.txt +++ b/test/prism/snapshots/seattlerb/block_arg_opt_arg_block.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,21)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,21)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,21)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,21)) + ├── flags: ∅ ├── locals: [:b, :c, :d, :e] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,19)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,18)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ ├── flags: ∅ @@ -31,7 +36,7 @@ │ │ │ ├── operator_loc: (1,9)-(1,10) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,10)-(1,11)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) diff --git a/test/prism/snapshots/seattlerb/block_arg_opt_splat.txt b/test/prism/snapshots/seattlerb/block_arg_opt_splat.txt index 799bd21057a..cefc1a85153 100644 --- a/test/prism/snapshots/seattlerb/block_arg_opt_splat.txt +++ b/test/prism/snapshots/seattlerb/block_arg_opt_splat.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,20)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,20)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,20)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,20)) + ├── flags: ∅ ├── locals: [:b, :c, :d] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,18)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,17)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ ├── flags: ∅ @@ -31,7 +36,7 @@ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,12)-(1,13)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,15)-(1,17)) diff --git a/test/prism/snapshots/seattlerb/block_arg_opt_splat_arg_block_omfg.txt b/test/prism/snapshots/seattlerb/block_arg_opt_splat_arg_block_omfg.txt index b5df136a622..bf66e376fd7 100644 --- a/test/prism/snapshots/seattlerb/block_arg_opt_splat_arg_block_omfg.txt +++ b/test/prism/snapshots/seattlerb/block_arg_opt_splat_arg_block_omfg.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,25)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,25)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,25)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,25)) + ├── flags: ∅ ├── locals: [:b, :c, :d, :e, :f] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,23)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,22)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ ├── flags: ∅ @@ -31,7 +36,7 @@ │ │ │ ├── operator_loc: (1,9)-(1,10) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,10)-(1,11)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,13)-(1,15)) diff --git a/test/prism/snapshots/seattlerb/block_arg_optional.txt b/test/prism/snapshots/seattlerb/block_arg_optional.txt index 8a850e9a21a..5fecfc31ab3 100644 --- a/test/prism/snapshots/seattlerb/block_arg_optional.txt +++ b/test/prism/snapshots/seattlerb/block_arg_optional.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,13)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,13)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,13)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,13)) + ├── flags: ∅ ├── locals: [:b] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,11)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,10)) @@ -28,7 +33,7 @@ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) diff --git a/test/prism/snapshots/seattlerb/block_arg_scope.txt b/test/prism/snapshots/seattlerb/block_arg_scope.txt index b99cc5e45ce..e90d6445b2d 100644 --- a/test/prism/snapshots/seattlerb/block_arg_scope.txt +++ b/test/prism/snapshots/seattlerb/block_arg_scope.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,12)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,12)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,12)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,12)) + ├── flags: ∅ ├── locals: [:b, :c] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,10)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,6)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/block_arg_scope2.txt b/test/prism/snapshots/seattlerb/block_arg_scope2.txt index 98b3a7da3aa..c9f7242d8a7 100644 --- a/test/prism/snapshots/seattlerb/block_arg_scope2.txt +++ b/test/prism/snapshots/seattlerb/block_arg_scope2.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,14)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,14)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,14)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,14)) + ├── flags: ∅ ├── locals: [:b, :c, :d] ├── parameters: │ @ BlockParametersNode (location: (1,3)-(1,12)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,4)-(1,5)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,4)-(1,5)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/block_arg_splat_arg.txt b/test/prism/snapshots/seattlerb/block_arg_splat_arg.txt index fd5813c9836..6ae1b1dade7 100644 --- a/test/prism/snapshots/seattlerb/block_arg_splat_arg.txt +++ b/test/prism/snapshots/seattlerb/block_arg_splat_arg.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,16)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,16)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,16)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,16)) + ├── flags: ∅ ├── locals: [:b, :c, :d] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,14)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,13)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/block_args_kwargs.txt b/test/prism/snapshots/seattlerb/block_args_kwargs.txt index 0975ce33679..45876c6dc12 100644 --- a/test/prism/snapshots/seattlerb/block_args_kwargs.txt +++ b/test/prism/snapshots/seattlerb/block_args_kwargs.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,23)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,23)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,23)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,23)) + ├── flags: ∅ ├── locals: [:kwargs] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,14)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,13)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -36,8 +41,10 @@ │ └── closing_loc: (1,13)-(1,14) = "|" ├── body: │ @ StatementsNode (location: (1,15)-(1,21)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ LocalVariableReadNode (location: (1,15)-(1,21)) + │ ├── flags: newline │ ├── name: :kwargs │ └── depth: 0 ├── opening_loc: (1,2)-(1,3) = "{" diff --git a/test/prism/snapshots/seattlerb/block_args_no_kwargs.txt b/test/prism/snapshots/seattlerb/block_args_no_kwargs.txt index d47349defbd..298bc26ce0a 100644 --- a/test/prism/snapshots/seattlerb/block_args_no_kwargs.txt +++ b/test/prism/snapshots/seattlerb/block_args_no_kwargs.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,13)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,13)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,13)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,13)) + ├── flags: ∅ ├── locals: [] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,11)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -26,6 +31,7 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ NoKeywordsParameterNode (location: (1,5)-(1,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (1,5)-(1,7) = "**" │ │ │ └── keyword_loc: (1,7)-(1,10) = "nil" │ │ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/block_args_opt1.txt b/test/prism/snapshots/seattlerb/block_args_opt1.txt index 1f21c0a4773..d23bd5edce0 100644 --- a/test/prism/snapshots/seattlerb/block_args_opt1.txt +++ b/test/prism/snapshots/seattlerb/block_args_opt1.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,24)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,24)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,24)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,24)) + ├── flags: ∅ ├── locals: [:a, :b] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,15)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ ├── flags: ∅ @@ -31,7 +36,7 @@ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,12)-(1,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 42 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) @@ -43,14 +48,17 @@ │ └── closing_loc: (1,14)-(1,15) = "|" ├── body: │ @ StatementsNode (location: (1,16)-(1,22)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ ArrayNode (location: (1,16)-(1,22)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 2) │ │ ├── @ LocalVariableReadNode (location: (1,17)-(1,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ └── @ LocalVariableReadNode (location: (1,20)-(1,21)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ └── depth: 0 │ ├── opening_loc: (1,16)-(1,17) = "[" diff --git a/test/prism/snapshots/seattlerb/block_args_opt2.txt b/test/prism/snapshots/seattlerb/block_args_opt2.txt index a8d736dde73..7170768b1cb 100644 --- a/test/prism/snapshots/seattlerb/block_args_opt2.txt +++ b/test/prism/snapshots/seattlerb/block_args_opt2.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,18)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,18)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,18)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,18)) + ├── flags: ∅ ├── locals: [:b, :c] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,16)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,6)-(1,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 2) │ │ │ ├── @ OptionalParameterNode (location: (1,6)-(1,9)) @@ -28,7 +33,7 @@ │ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (1,8)-(1,9)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── @ OptionalParameterNode (location: (1,11)-(1,14)) │ │ │ ├── flags: ∅ @@ -37,7 +42,7 @@ │ │ │ ├── operator_loc: (1,12)-(1,13) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,13)-(1,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) diff --git a/test/prism/snapshots/seattlerb/block_args_opt2_2.txt b/test/prism/snapshots/seattlerb/block_args_opt2_2.txt index 0403851ed7b..34d04dbe54b 100644 --- a/test/prism/snapshots/seattlerb/block_args_opt2_2.txt +++ b/test/prism/snapshots/seattlerb/block_args_opt2_2.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,35)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,35)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,35)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,35)) + ├── flags: ∅ ├── locals: [:a, :b, :c] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,23)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,22)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ ├── flags: ∅ @@ -31,7 +36,7 @@ │ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (1,12)-(1,14)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 42 │ │ │ └── @ OptionalParameterNode (location: (1,16)-(1,22)) │ │ │ ├── flags: ∅ @@ -40,7 +45,7 @@ │ │ │ ├── operator_loc: (1,18)-(1,19) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,20)-(1,22)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 24 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) @@ -52,17 +57,21 @@ │ └── closing_loc: (1,22)-(1,23) = "|" ├── body: │ @ StatementsNode (location: (1,24)-(1,33)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ ArrayNode (location: (1,24)-(1,33)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 3) │ │ ├── @ LocalVariableReadNode (location: (1,25)-(1,26)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── @ LocalVariableReadNode (location: (1,28)-(1,29)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ └── depth: 0 │ │ └── @ LocalVariableReadNode (location: (1,31)-(1,32)) + │ │ ├── flags: ∅ │ │ ├── name: :c │ │ └── depth: 0 │ ├── opening_loc: (1,24)-(1,25) = "[" diff --git a/test/prism/snapshots/seattlerb/block_args_opt3.txt b/test/prism/snapshots/seattlerb/block_args_opt3.txt index ff4495019c7..508d062ce2e 100644 --- a/test/prism/snapshots/seattlerb/block_args_opt3.txt +++ b/test/prism/snapshots/seattlerb/block_args_opt3.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,42)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,42)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,42)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,42)) + ├── flags: ∅ ├── locals: [:a, :b, :c, :d] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,27)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,26)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ ├── flags: ∅ @@ -31,7 +36,7 @@ │ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (1,12)-(1,14)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 42 │ │ │ └── @ OptionalParameterNode (location: (1,16)-(1,22)) │ │ │ ├── flags: ∅ @@ -40,7 +45,7 @@ │ │ │ ├── operator_loc: (1,18)-(1,19) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,20)-(1,22)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 24 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) @@ -57,20 +62,25 @@ │ └── closing_loc: (1,26)-(1,27) = "|" ├── body: │ @ StatementsNode (location: (1,28)-(1,40)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ ArrayNode (location: (1,28)-(1,40)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 4) │ │ ├── @ LocalVariableReadNode (location: (1,29)-(1,30)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── @ LocalVariableReadNode (location: (1,32)-(1,33)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ └── depth: 0 │ │ ├── @ LocalVariableReadNode (location: (1,35)-(1,36)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ └── depth: 0 │ │ └── @ LocalVariableReadNode (location: (1,38)-(1,39)) + │ │ ├── flags: ∅ │ │ ├── name: :d │ │ └── depth: 0 │ ├── opening_loc: (1,28)-(1,29) = "[" diff --git a/test/prism/snapshots/seattlerb/block_call_defn_call_block_call.txt b/test/prism/snapshots/seattlerb/block_call_defn_call_block_call.txt index 2e634dc937a..4e6ad90afd1 100644 --- a/test/prism/snapshots/seattlerb/block_call_defn_call_block_call.txt +++ b/test/prism/snapshots/seattlerb/block_call_defn_call_block_call.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(4,11)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,11)) + ├── flags: ∅ └── body: (length: 2) ├── @ CallNode (location: (1,0)-(3,4)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a @@ -15,11 +17,13 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ DefNode (location: (1,2)-(3,4)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (1,6)-(1,7) = "b" │ │ ├── receiver: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (1,8)-(1,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,8)-(1,9)) │ │ │ │ ├── flags: ∅ @@ -32,9 +36,10 @@ │ │ │ └── block: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (2,1)-(2,2)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (2,1)-(2,2)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :d @@ -53,7 +58,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ └── @ CallNode (location: (4,1)-(4,11)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (4,1)-(4,2)) │ ├── flags: variable_call, ignore_visibility @@ -73,6 +78,7 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (4,5)-(4,11)) + ├── flags: ∅ ├── locals: [] ├── parameters: ∅ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/block_call_dot_op2_brace_block.txt b/test/prism/snapshots/seattlerb/block_call_dot_op2_brace_block.txt index e46104b868c..5f05b1f6ff4 100644 --- a/test/prism/snapshots/seattlerb/block_call_dot_op2_brace_block.txt +++ b/test/prism/snapshots/seattlerb/block_call_dot_op2_brace_block.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,31)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,31)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,31)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,0)-(1,16)) │ ├── flags: ∅ @@ -40,13 +42,15 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (1,8)-(1,16)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,11)-(1,12)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (1,11)-(1,12)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :d @@ -65,11 +69,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,19)-(1,31)) + ├── flags: ∅ ├── locals: [:f] ├── parameters: │ @ BlockParametersNode (location: (1,22)-(1,25)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,23)-(1,24)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,23)-(1,24)) │ │ │ ├── flags: ∅ @@ -85,9 +92,10 @@ │ └── closing_loc: (1,24)-(1,25) = "|" ├── body: │ @ StatementsNode (location: (1,26)-(1,27)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,26)-(1,27)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :g diff --git a/test/prism/snapshots/seattlerb/block_call_dot_op2_cmd_args_do_block.txt b/test/prism/snapshots/seattlerb/block_call_dot_op2_cmd_args_do_block.txt index 05d076f8d6f..ca141580b7d 100644 --- a/test/prism/snapshots/seattlerb/block_call_dot_op2_cmd_args_do_block.txt +++ b/test/prism/snapshots/seattlerb/block_call_dot_op2_cmd_args_do_block.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,33)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,33)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,33)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,0)-(1,16)) │ ├── flags: ∅ @@ -40,13 +42,15 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (1,8)-(1,16)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,11)-(1,12)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (1,11)-(1,12)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :d @@ -78,11 +82,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,21)-(1,33)) + ├── flags: ∅ ├── locals: [:g] ├── parameters: │ @ BlockParametersNode (location: (1,24)-(1,27)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,25)-(1,26)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,25)-(1,26)) │ │ │ ├── flags: ∅ @@ -98,9 +105,10 @@ │ └── closing_loc: (1,26)-(1,27) = "|" ├── body: │ @ StatementsNode (location: (1,28)-(1,29)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,28)-(1,29)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :h diff --git a/test/prism/snapshots/seattlerb/block_call_operation_colon.txt b/test/prism/snapshots/seattlerb/block_call_operation_colon.txt index 9fd13b0dfcc..cecd4212638 100644 --- a/test/prism/snapshots/seattlerb/block_call_operation_colon.txt +++ b/test/prism/snapshots/seattlerb/block_call_operation_colon.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,15)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,15)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,15)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,0)-(1,12)) │ ├── flags: ∅ @@ -40,6 +42,7 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (1,6)-(1,12)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/block_call_operation_dot.txt b/test/prism/snapshots/seattlerb/block_call_operation_dot.txt index 43c19d33181..5c661fb49a9 100644 --- a/test/prism/snapshots/seattlerb/block_call_operation_dot.txt +++ b/test/prism/snapshots/seattlerb/block_call_operation_dot.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,14)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,14)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,14)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,0)-(1,12)) │ ├── flags: ∅ @@ -40,6 +42,7 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (1,6)-(1,12)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/block_call_paren_call_block_call.txt b/test/prism/snapshots/seattlerb/block_call_paren_call_block_call.txt index 10c1780d374..93c4b05f9bc 100644 --- a/test/prism/snapshots/seattlerb/block_call_paren_call_block_call.txt +++ b/test/prism/snapshots/seattlerb/block_call_paren_call_block_call.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(2,10)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(2,10)) + ├── flags: ∅ └── body: (length: 2) ├── @ CallNode (location: (1,0)-(1,5)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a @@ -15,11 +17,13 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ ParenthesesNode (location: (1,2)-(1,5)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (1,3)-(1,4)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (1,3)-(1,4)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -33,7 +37,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ └── @ CallNode (location: (2,0)-(2,10)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (2,0)-(2,1)) │ ├── flags: variable_call, ignore_visibility @@ -53,6 +57,7 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (2,4)-(2,10)) + ├── flags: ∅ ├── locals: [] ├── parameters: ∅ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/block_command_operation_colon.txt b/test/prism/snapshots/seattlerb/block_command_operation_colon.txt index 30fd6dafa00..c71fbe2f4a0 100644 --- a/test/prism/snapshots/seattlerb/block_command_operation_colon.txt +++ b/test/prism/snapshots/seattlerb/block_command_operation_colon.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,17)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,0)-(1,11)) │ ├── flags: ignore_visibility @@ -18,7 +20,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (1,2)-(1,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,2)-(1,3) = ":" │ │ ├── value_loc: (1,3)-(1,4) = "b" │ │ ├── closing_loc: ∅ @@ -26,6 +28,7 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (1,5)-(1,11)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ @@ -40,7 +43,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ SymbolNode (location: (1,15)-(1,17)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,15)-(1,16) = ":" │ ├── value_loc: (1,16)-(1,17) = "d" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/block_command_operation_dot.txt b/test/prism/snapshots/seattlerb/block_command_operation_dot.txt index e4f69d36045..68d98c99b46 100644 --- a/test/prism/snapshots/seattlerb/block_command_operation_dot.txt +++ b/test/prism/snapshots/seattlerb/block_command_operation_dot.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,16)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,16)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,16)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,0)-(1,11)) │ ├── flags: ignore_visibility @@ -18,7 +20,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (1,2)-(1,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,2)-(1,3) = ":" │ │ ├── value_loc: (1,3)-(1,4) = "b" │ │ ├── closing_loc: ∅ @@ -26,6 +28,7 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (1,5)-(1,11)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ @@ -40,7 +43,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ SymbolNode (location: (1,14)-(1,16)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,14)-(1,15) = ":" │ ├── value_loc: (1,15)-(1,16) = "d" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/block_decomp_anon_splat_arg.txt b/test/prism/snapshots/seattlerb/block_decomp_anon_splat_arg.txt index e309ec1f98f..5628cacc978 100644 --- a/test/prism/snapshots/seattlerb/block_decomp_anon_splat_arg.txt +++ b/test/prism/snapshots/seattlerb/block_decomp_anon_splat_arg.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,14)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,14)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,14)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,16 +16,21 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,14)) + ├── flags: ∅ ├── locals: [:a] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,12)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ MultiTargetNode (location: (1,5)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 0) │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,6)-(1,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (1,6)-(1,7) = "*" │ │ │ │ └── expression: ∅ │ │ │ ├── rights: (length: 1) diff --git a/test/prism/snapshots/seattlerb/block_decomp_arg_splat.txt b/test/prism/snapshots/seattlerb/block_decomp_arg_splat.txt index 8d28fa7e02d..b13e13d167e 100644 --- a/test/prism/snapshots/seattlerb/block_decomp_arg_splat.txt +++ b/test/prism/snapshots/seattlerb/block_decomp_arg_splat.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,14)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,14)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,14)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,19 +16,24 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,14)) + ├── flags: ∅ ├── locals: [:b] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,12)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ MultiTargetNode (location: (1,5)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,9)-(1,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (1,9)-(1,10) = "*" │ │ │ │ └── expression: ∅ │ │ │ ├── rights: (length: 0) diff --git a/test/prism/snapshots/seattlerb/block_decomp_arg_splat_arg.txt b/test/prism/snapshots/seattlerb/block_decomp_arg_splat_arg.txt index 4f4a82acf59..ba0a6202ced 100644 --- a/test/prism/snapshots/seattlerb/block_decomp_arg_splat_arg.txt +++ b/test/prism/snapshots/seattlerb/block_decomp_arg_splat_arg.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,18)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,18)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,18)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,19 +16,24 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,18)) + ├── flags: ∅ ├── locals: [:a, :b, :c] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,16)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,15)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ MultiTargetNode (location: (1,5)-(1,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,9)-(1,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (1,9)-(1,10) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (1,10)-(1,11)) diff --git a/test/prism/snapshots/seattlerb/block_decomp_splat.txt b/test/prism/snapshots/seattlerb/block_decomp_splat.txt index 09d34401264..fd8ad4bda1f 100644 --- a/test/prism/snapshots/seattlerb/block_decomp_splat.txt +++ b/test/prism/snapshots/seattlerb/block_decomp_splat.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,12)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,12)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,12)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,16 +16,21 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,12)) + ├── flags: ∅ ├── locals: [:a] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,10)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,9)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ MultiTargetNode (location: (1,5)-(1,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 0) │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,6)-(1,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (1,6)-(1,7) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (1,7)-(1,8)) diff --git a/test/prism/snapshots/seattlerb/block_kw.txt b/test/prism/snapshots/seattlerb/block_kw.txt index f022637dae6..d76998ecb66 100644 --- a/test/prism/snapshots/seattlerb/block_kw.txt +++ b/test/prism/snapshots/seattlerb/block_kw.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,15)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,15)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,15)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :blah @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,5)-(1,15)) + ├── flags: ∅ ├── locals: [:k] ├── parameters: │ @ BlockParametersNode (location: (1,7)-(1,13)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,8)-(1,12)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -30,7 +35,7 @@ │ │ │ ├── name_loc: (1,8)-(1,10) = "k:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,10)-(1,12)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 42 │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/block_kw__required.txt b/test/prism/snapshots/seattlerb/block_kw__required.txt index 8a49c8bec7e..f04987d854f 100644 --- a/test/prism/snapshots/seattlerb/block_kw__required.txt +++ b/test/prism/snapshots/seattlerb/block_kw__required.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,16)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,16)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,16)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :blah @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,5)-(1,16)) + ├── flags: ∅ ├── locals: [:k] ├── parameters: │ @ BlockParametersNode (location: (1,8)-(1,12)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,9)-(1,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/block_kwarg_lvar.txt b/test/prism/snapshots/seattlerb/block_kwarg_lvar.txt index e77bf90a276..861348f2a2a 100644 --- a/test/prism/snapshots/seattlerb/block_kwarg_lvar.txt +++ b/test/prism/snapshots/seattlerb/block_kwarg_lvar.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,20)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,20)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,20)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :bl @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,3)-(1,20)) + ├── flags: ∅ ├── locals: [:kw] ├── parameters: │ @ BlockParametersNode (location: (1,5)-(1,15)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,6)-(1,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -30,7 +35,7 @@ │ │ │ ├── name_loc: (1,6)-(1,9) = "kw:" │ │ │ └── value: │ │ │ @ SymbolNode (location: (1,10)-(1,14)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,10)-(1,11) = ":" │ │ │ ├── value_loc: (1,11)-(1,14) = "val" │ │ │ ├── closing_loc: ∅ @@ -42,8 +47,10 @@ │ └── closing_loc: (1,14)-(1,15) = "|" ├── body: │ @ StatementsNode (location: (1,16)-(1,18)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ LocalVariableReadNode (location: (1,16)-(1,18)) + │ ├── flags: newline │ ├── name: :kw │ └── depth: 0 ├── opening_loc: (1,3)-(1,4) = "{" diff --git a/test/prism/snapshots/seattlerb/block_kwarg_lvar_multiple.txt b/test/prism/snapshots/seattlerb/block_kwarg_lvar_multiple.txt index a527c8c993d..f1c1fef8a38 100644 --- a/test/prism/snapshots/seattlerb/block_kwarg_lvar_multiple.txt +++ b/test/prism/snapshots/seattlerb/block_kwarg_lvar_multiple.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,33)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,33)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,33)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :bl @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,3)-(1,33)) + ├── flags: ∅ ├── locals: [:kw, :kw2] ├── parameters: │ @ BlockParametersNode (location: (1,5)-(1,28)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,6)-(1,26)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -30,7 +35,7 @@ │ │ │ │ ├── name_loc: (1,6)-(1,9) = "kw:" │ │ │ │ └── value: │ │ │ │ @ SymbolNode (location: (1,10)-(1,14)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (1,10)-(1,11) = ":" │ │ │ │ ├── value_loc: (1,11)-(1,14) = "val" │ │ │ │ ├── closing_loc: ∅ @@ -41,7 +46,7 @@ │ │ │ ├── name_loc: (1,16)-(1,20) = "kw2:" │ │ │ └── value: │ │ │ @ SymbolNode (location: (1,21)-(1,26)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,21)-(1,22) = ":" │ │ │ ├── value_loc: (1,22)-(1,26) = "val2" │ │ │ ├── closing_loc: ∅ @@ -53,8 +58,10 @@ │ └── closing_loc: (1,27)-(1,28) = "|" ├── body: │ @ StatementsNode (location: (1,29)-(1,31)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ LocalVariableReadNode (location: (1,29)-(1,31)) + │ ├── flags: newline │ ├── name: :kw │ └── depth: 0 ├── opening_loc: (1,3)-(1,4) = "{" diff --git a/test/prism/snapshots/seattlerb/block_opt_arg.txt b/test/prism/snapshots/seattlerb/block_opt_arg.txt index 64dc928f14b..39be11ac92d 100644 --- a/test/prism/snapshots/seattlerb/block_opt_arg.txt +++ b/test/prism/snapshots/seattlerb/block_opt_arg.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,14)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,14)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,14)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,14)) + ├── flags: ∅ ├── locals: [:b, :c] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,12)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,8)) @@ -28,7 +33,7 @@ │ │ │ ├── operator_loc: (1,6)-(1,7) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,7)-(1,8)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) diff --git a/test/prism/snapshots/seattlerb/block_opt_splat.txt b/test/prism/snapshots/seattlerb/block_opt_splat.txt index c18df9c27d4..3898212dc00 100644 --- a/test/prism/snapshots/seattlerb/block_opt_splat.txt +++ b/test/prism/snapshots/seattlerb/block_opt_splat.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,17)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,17)) + ├── flags: ∅ ├── locals: [:b, :c] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,15)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,10)) @@ -28,7 +33,7 @@ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,12)-(1,14)) diff --git a/test/prism/snapshots/seattlerb/block_opt_splat_arg_block_omfg.txt b/test/prism/snapshots/seattlerb/block_opt_splat_arg_block_omfg.txt index 3806809d2bd..ed4857ad25a 100644 --- a/test/prism/snapshots/seattlerb/block_opt_splat_arg_block_omfg.txt +++ b/test/prism/snapshots/seattlerb/block_opt_splat_arg_block_omfg.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,22)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,22)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,22)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,22)) + ├── flags: ∅ ├── locals: [:b, :c, :d, :e] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,20)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,19)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,8)) @@ -28,7 +33,7 @@ │ │ │ ├── operator_loc: (1,6)-(1,7) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,7)-(1,8)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,10)-(1,12)) diff --git a/test/prism/snapshots/seattlerb/block_optarg.txt b/test/prism/snapshots/seattlerb/block_optarg.txt index 5da99aec799..2172571eb12 100644 --- a/test/prism/snapshots/seattlerb/block_optarg.txt +++ b/test/prism/snapshots/seattlerb/block_optarg.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,14)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,14)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,14)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,14)) + ├── flags: ∅ ├── locals: [:b] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,12)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,11)) @@ -28,7 +33,7 @@ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ └── value: │ │ │ @ SymbolNode (location: (1,9)-(1,11)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,9)-(1,10) = ":" │ │ │ ├── value_loc: (1,10)-(1,11) = "c" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/block_paren_splat.txt b/test/prism/snapshots/seattlerb/block_paren_splat.txt index ebd937904cc..b6c2da679bb 100644 --- a/test/prism/snapshots/seattlerb/block_paren_splat.txt +++ b/test/prism/snapshots/seattlerb/block_paren_splat.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,15)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,15)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,15)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,19 +16,24 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,15)) + ├── flags: ∅ ├── locals: [:b, :c] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,13)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,12)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ MultiTargetNode (location: (1,5)-(1,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,9)-(1,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (1,9)-(1,10) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (1,10)-(1,11)) diff --git a/test/prism/snapshots/seattlerb/block_reg_optarg.txt b/test/prism/snapshots/seattlerb/block_reg_optarg.txt index 53c43603a7e..0173b92e8f0 100644 --- a/test/prism/snapshots/seattlerb/block_reg_optarg.txt +++ b/test/prism/snapshots/seattlerb/block_reg_optarg.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,17)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,17)) + ├── flags: ∅ ├── locals: [:b, :c] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,15)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ ├── flags: ∅ @@ -31,7 +36,7 @@ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ │ └── value: │ │ │ @ SymbolNode (location: (1,12)-(1,14)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,12)-(1,13) = ":" │ │ │ ├── value_loc: (1,13)-(1,14) = "d" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/block_return.txt b/test/prism/snapshots/seattlerb/block_return.txt index c863b28a22c..0eee33c844e 100644 --- a/test/prism/snapshots/seattlerb/block_return.txt +++ b/test/prism/snapshots/seattlerb/block_return.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,27)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,27)) + ├── flags: ∅ └── body: (length: 1) └── @ ReturnNode (location: (1,0)-(1,27)) - ├── flags: ∅ + ├── flags: newline ├── keyword_loc: (1,0)-(1,6) = "return" └── arguments: @ ArgumentsNode (location: (1,7)-(1,27)) @@ -34,11 +36,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,15)-(1,27)) + ├── flags: ∅ ├── locals: [:bar] ├── parameters: │ @ BlockParametersNode (location: (1,18)-(1,23)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,19)-(1,22)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,19)-(1,22)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/block_scope.txt b/test/prism/snapshots/seattlerb/block_scope.txt index a21a28b9937..ef659bb38eb 100644 --- a/test/prism/snapshots/seattlerb/block_scope.txt +++ b/test/prism/snapshots/seattlerb/block_scope.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,10)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,10)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,10)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,9 +16,11 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,10)) + ├── flags: ∅ ├── locals: [:b] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,8)) + │ ├── flags: ∅ │ ├── parameters: ∅ │ ├── locals: (length: 1) │ │ └── @ BlockLocalVariableNode (location: (1,6)-(1,7)) diff --git a/test/prism/snapshots/seattlerb/block_splat_reg.txt b/test/prism/snapshots/seattlerb/block_splat_reg.txt index 617ff886225..b5eb009c52d 100644 --- a/test/prism/snapshots/seattlerb/block_splat_reg.txt +++ b/test/prism/snapshots/seattlerb/block_splat_reg.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,13)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,13)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,13)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,13)) + ├── flags: ∅ ├── locals: [:b, :c] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,11)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: diff --git a/test/prism/snapshots/seattlerb/bug169.txt b/test/prism/snapshots/seattlerb/bug169.txt index e4fb47a6de9..c55df4257de 100644 --- a/test/prism/snapshots/seattlerb/bug169.txt +++ b/test/prism/snapshots/seattlerb/bug169.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,7)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,7)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,7)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :m @@ -15,12 +17,14 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ ParenthesesNode (location: (1,2)-(1,4)) + │ ├── flags: ∅ │ ├── body: ∅ │ ├── opening_loc: (1,2)-(1,3) = "(" │ └── closing_loc: (1,3)-(1,4) = ")" ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,5)-(1,7)) + ├── flags: ∅ ├── locals: [] ├── parameters: ∅ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/bug179.txt b/test/prism/snapshots/seattlerb/bug179.txt index d7695bc7a74..4392d5ec27c 100644 --- a/test/prism/snapshots/seattlerb/bug179.txt +++ b/test/prism/snapshots/seattlerb/bug179.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,9)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,9)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,9)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :p @@ -18,11 +20,13 @@ │ ├── flags: ∅ │ ├── left: │ │ @ ParenthesesNode (location: (1,2)-(1,4)) + │ │ ├── flags: ∅ │ │ ├── body: ∅ │ │ ├── opening_loc: (1,2)-(1,3) = "(" │ │ └── closing_loc: (1,3)-(1,4) = ")" │ ├── right: │ │ @ NilNode (location: (1,6)-(1,9)) + │ │ └── flags: static_literal │ └── operator_loc: (1,4)-(1,6) = ".." ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/bug190.txt b/test/prism/snapshots/seattlerb/bug190.txt index b261a166cf9..004ca16a60c 100644 --- a/test/prism/snapshots/seattlerb/bug190.txt +++ b/test/prism/snapshots/seattlerb/bug190.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ └── body: (length: 1) └── @ RegularExpressionNode (location: (1,0)-(1,6)) - ├── flags: forced_us_ascii_encoding + ├── flags: newline, static_literal, forced_us_ascii_encoding ├── opening_loc: (1,0)-(1,3) = "%r'" ├── content_loc: (1,3)-(1,5) = "\\'" ├── closing_loc: (1,5)-(1,6) = "'" diff --git a/test/prism/snapshots/seattlerb/bug191.txt b/test/prism/snapshots/seattlerb/bug191.txt index 69835ab1d03..27b7f97f450 100644 --- a/test/prism/snapshots/seattlerb/bug191.txt +++ b/test/prism/snapshots/seattlerb/bug191.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(3,9)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,9)) + ├── flags: ∅ └── body: (length: 2) ├── @ IfNode (location: (1,0)-(1,9)) + │ ├── flags: newline │ ├── if_keyword_loc: ∅ │ ├── predicate: │ │ @ CallNode (location: (1,0)-(1,1)) @@ -19,21 +22,24 @@ │ ├── then_keyword_loc: (1,2)-(1,3) = "?" │ ├── statements: │ │ @ StatementsNode (location: (1,4)-(1,6)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ StringNode (location: (1,4)-(1,6)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── opening_loc: (1,4)-(1,5) = "\"" │ │ ├── content_loc: (1,5)-(1,5) = "" │ │ ├── closing_loc: (1,5)-(1,6) = "\"" │ │ └── unescaped: "" - │ ├── consequent: + │ ├── subsequent: │ │ @ ElseNode (location: (1,6)-(1,9)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (1,6)-(1,7) = ":" │ │ ├── statements: │ │ │ @ StatementsNode (location: (1,8)-(1,9)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (1,8)-(1,9)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -45,6 +51,7 @@ │ │ └── end_keyword_loc: ∅ │ └── end_keyword_loc: ∅ └── @ IfNode (location: (3,0)-(3,9)) + ├── flags: newline ├── if_keyword_loc: ∅ ├── predicate: │ @ CallNode (location: (3,0)-(3,1)) @@ -60,21 +67,24 @@ ├── then_keyword_loc: (3,2)-(3,3) = "?" ├── statements: │ @ StatementsNode (location: (3,4)-(3,6)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ StringNode (location: (3,4)-(3,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (3,4)-(3,5) = "'" │ ├── content_loc: (3,5)-(3,5) = "" │ ├── closing_loc: (3,5)-(3,6) = "'" │ └── unescaped: "" - ├── consequent: + ├── subsequent: │ @ ElseNode (location: (3,6)-(3,9)) + │ ├── flags: ∅ │ ├── else_keyword_loc: (3,6)-(3,7) = ":" │ ├── statements: │ │ @ StatementsNode (location: (3,8)-(3,9)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (3,8)-(3,9)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :b diff --git a/test/prism/snapshots/seattlerb/bug202.txt b/test/prism/snapshots/seattlerb/bug202.txt index 377b53727ed..f907081c208 100644 --- a/test/prism/snapshots/seattlerb/bug202.txt +++ b/test/prism/snapshots/seattlerb/bug202.txt @@ -1,22 +1,26 @@ @ ProgramNode (location: (1,0)-(2,10)) +├── flags: ∅ ├── locals: [:测试] └── statements: @ StatementsNode (location: (1,0)-(2,10)) + ├── flags: ∅ └── body: (length: 2) ├── @ GlobalVariableWriteNode (location: (1,0)-(1,11)) + │ ├── flags: newline │ ├── name: :$测试 │ ├── name_loc: (1,0)-(1,7) = "$测试" │ ├── value: │ │ @ IntegerNode (location: (1,10)-(1,11)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (1,8)-(1,9) = "=" └── @ LocalVariableWriteNode (location: (2,0)-(2,10)) + ├── flags: newline ├── name: :测试 ├── depth: 0 ├── name_loc: (2,0)-(2,6) = "测试" ├── value: │ @ IntegerNode (location: (2,9)-(2,10)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 └── operator_loc: (2,7)-(2,8) = "=" diff --git a/test/prism/snapshots/seattlerb/bug236.txt b/test/prism/snapshots/seattlerb/bug236.txt index 203a39a793a..792020dc78b 100644 --- a/test/prism/snapshots/seattlerb/bug236.txt +++ b/test/prism/snapshots/seattlerb/bug236.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(3,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,6)) + ├── flags: ∅ └── body: (length: 2) ├── @ CallNode (location: (1,0)-(1,7)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :x @@ -14,11 +16,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (1,1)-(1,7)) + │ ├── flags: ∅ │ ├── locals: [:a] │ ├── parameters: │ │ @ BlockParametersNode (location: (1,2)-(1,6)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (1,3)-(1,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,3)-(1,4)) │ │ │ │ ├── flags: ∅ @@ -26,6 +31,7 @@ │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ ImplicitRestNode (location: (1,4)-(1,5)) + │ │ │ │ └── flags: ∅ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 0) │ │ │ ├── keyword_rest: ∅ @@ -37,7 +43,7 @@ │ ├── opening_loc: (1,1)-(1,2) = "{" │ └── closing_loc: (1,6)-(1,7) = "}" └── @ CallNode (location: (3,0)-(3,6)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :x @@ -47,11 +53,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (3,1)-(3,6)) + ├── flags: ∅ ├── locals: [:a] ├── parameters: │ @ BlockParametersNode (location: (3,2)-(3,5)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (3,3)-(3,4)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (3,3)-(3,4)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/bug290.txt b/test/prism/snapshots/seattlerb/bug290.txt index 4f1e673c4b3..85d75c0d161 100644 --- a/test/prism/snapshots/seattlerb/bug290.txt +++ b/test/prism/snapshots/seattlerb/bug290.txt @@ -1,15 +1,19 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ BeginNode (location: (1,0)-(3,3)) + ├── flags: newline ├── begin_keyword_loc: (1,0)-(1,5) = "begin" ├── statements: │ @ StatementsNode (location: (2,2)-(2,5)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (2,2)-(2,5)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo diff --git a/test/prism/snapshots/seattlerb/bug_187.txt b/test/prism/snapshots/seattlerb/bug_187.txt index ae72675e5cf..6a5786e34ab 100644 --- a/test/prism/snapshots/seattlerb/bug_187.txt +++ b/test/prism/snapshots/seattlerb/bug_187.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(3,3)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :private @@ -15,15 +17,17 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ DefNode (location: (1,8)-(3,3)) + │ ├── flags: ∅ │ ├── name: :f │ ├── name_loc: (1,12)-(1,13) = "f" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (2,0)-(2,10)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (2,0)-(2,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ CallNode (location: (2,0)-(2,1)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -43,6 +47,7 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (2,4)-(2,10)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/bug_215.txt b/test/prism/snapshots/seattlerb/bug_215.txt index de7716335e9..ee82b4f1da9 100644 --- a/test/prism/snapshots/seattlerb/bug_215.txt +++ b/test/prism/snapshots/seattlerb/bug_215.txt @@ -1,12 +1,15 @@ @ ProgramNode (location: (1,0)-(1,13)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,13)) + ├── flags: ∅ └── body: (length: 1) └── @ UndefNode (location: (1,0)-(1,13)) + ├── flags: newline ├── names: (length: 1) │ └── @ SymbolNode (location: (1,6)-(1,13)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,6)-(1,9) = "%s(" │ ├── value_loc: (1,9)-(1,12) = "foo" │ ├── closing_loc: (1,12)-(1,13) = ")" diff --git a/test/prism/snapshots/seattlerb/bug_249.txt b/test/prism/snapshots/seattlerb/bug_249.txt index ad61501a076..06daa80e41d 100644 --- a/test/prism/snapshots/seattlerb/bug_249.txt +++ b/test/prism/snapshots/seattlerb/bug_249.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(4,28)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,28)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(4,28)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :mount @@ -18,13 +20,16 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ ParenthesesNode (location: (1,6)-(4,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (1,7)-(4,4)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (1,7)-(4,4)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: newline │ │ │ │ ├── receiver: │ │ │ │ │ @ ConstantReadNode (location: (1,7)-(1,12)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :Class │ │ │ │ ├── call_operator_loc: (1,12)-(1,13) = "." │ │ │ │ ├── name: :new @@ -34,12 +39,15 @@ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: │ │ │ │ @ BlockNode (location: (1,17)-(4,4)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── locals: [] │ │ │ │ ├── parameters: ∅ │ │ │ │ ├── body: │ │ │ │ │ @ StatementsNode (location: (2,0)-(3,3)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ DefNode (location: (2,0)-(3,3)) + │ │ │ │ │ ├── flags: newline │ │ │ │ │ ├── name: :initialize │ │ │ │ │ ├── name_loc: (2,4)-(2,14) = "initialize" │ │ │ │ │ ├── receiver: ∅ @@ -67,9 +75,10 @@ │ ├── flags: symbol_keys │ └── elements: (length: 1) │ └── @ AssocNode (location: (4,11)-(4,28)) + │ ├── flags: ∅ │ ├── key: │ │ @ SymbolNode (location: (4,11)-(4,14)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (4,11)-(4,12) = ":" │ │ ├── value_loc: (4,12)-(4,14) = "at" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/bug_and.txt b/test/prism/snapshots/seattlerb/bug_and.txt index 3daf505e5f1..89eb403b4a8 100644 --- a/test/prism/snapshots/seattlerb/bug_and.txt +++ b/test/prism/snapshots/seattlerb/bug_and.txt @@ -1,20 +1,27 @@ @ ProgramNode (location: (1,0)-(4,11)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,11)) + ├── flags: ∅ └── body: (length: 2) ├── @ AndNode (location: (1,0)-(2,4)) + │ ├── flags: newline │ ├── left: │ │ @ TrueNode (location: (1,0)-(1,4)) + │ │ └── flags: static_literal │ ├── right: │ │ @ TrueNode (location: (2,0)-(2,4)) + │ │ └── flags: static_literal │ └── operator_loc: (1,5)-(1,8) = "and" └── @ AndNode (location: (4,0)-(4,11)) + ├── flags: newline ├── left: │ @ TrueNode (location: (4,0)-(4,4)) + │ └── flags: static_literal ├── right: │ @ ArrayNode (location: (4,9)-(4,11)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 0) │ ├── opening_loc: (4,9)-(4,10) = "[" │ └── closing_loc: (4,10)-(4,11) = "]" diff --git a/test/prism/snapshots/seattlerb/bug_args__19.txt b/test/prism/snapshots/seattlerb/bug_args__19.txt index f451bd01722..5b1d897718a 100644 --- a/test/prism/snapshots/seattlerb/bug_args__19.txt +++ b/test/prism/snapshots/seattlerb/bug_args__19.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,16)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,16)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,16)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,13 +16,17 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,16)) + ├── flags: ∅ ├── locals: [:a, :b] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,12)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ MultiTargetNode (location: (1,5)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (1,6)-(1,7)) │ │ │ │ │ ├── flags: ∅ @@ -43,9 +49,10 @@ │ └── closing_loc: (1,11)-(1,12) = "|" ├── body: │ @ StatementsNode (location: (1,13)-(1,14)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,13)-(1,14)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :d diff --git a/test/prism/snapshots/seattlerb/bug_args_masgn.txt b/test/prism/snapshots/seattlerb/bug_args_masgn.txt index 297979c182c..6456d82ecc3 100644 --- a/test/prism/snapshots/seattlerb/bug_args_masgn.txt +++ b/test/prism/snapshots/seattlerb/bug_args_masgn.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,17)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,13 +16,17 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,17)) + ├── flags: ∅ ├── locals: [:a, :b, :c] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,15)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ MultiTargetNode (location: (1,5)-(1,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ ├── @ RequiredParameterNode (location: (1,6)-(1,7)) │ │ │ │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/bug_args_masgn2.txt b/test/prism/snapshots/seattlerb/bug_args_masgn2.txt index 6bec9187b3b..bd9fc611611 100644 --- a/test/prism/snapshots/seattlerb/bug_args_masgn2.txt +++ b/test/prism/snapshots/seattlerb/bug_args_masgn2.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,22)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,22)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,22)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,15 +16,20 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,22)) + ├── flags: ∅ ├── locals: [:a, :b, :c, :d] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,20)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,19)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ MultiTargetNode (location: (1,5)-(1,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ ├── @ MultiTargetNode (location: (1,6)-(1,12)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ │ │ ├── @ RequiredParameterNode (location: (1,7)-(1,8)) │ │ │ │ │ │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/bug_args_masgn_outer_parens__19.txt b/test/prism/snapshots/seattlerb/bug_args_masgn_outer_parens__19.txt index 42a060d02aa..ad62bd4daa5 100644 --- a/test/prism/snapshots/seattlerb/bug_args_masgn_outer_parens__19.txt +++ b/test/prism/snapshots/seattlerb/bug_args_masgn_outer_parens__19.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,19)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,19)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,19)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,15 +16,20 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,19)) + ├── flags: ∅ ├── locals: [:k, :v, :i] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,17)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,16)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ MultiTargetNode (location: (1,5)-(1,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ MultiTargetNode (location: (1,6)-(1,12)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ │ ├── @ RequiredParameterNode (location: (1,7)-(1,8)) │ │ │ │ │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/bug_call_arglist_parens.txt b/test/prism/snapshots/seattlerb/bug_call_arglist_parens.txt index 53d6f9220b2..6954854baeb 100644 --- a/test/prism/snapshots/seattlerb/bug_call_arglist_parens.txt +++ b/test/prism/snapshots/seattlerb/bug_call_arglist_parens.txt @@ -1,18 +1,22 @@ @ ProgramNode (location: (1,6)-(11,9)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,6)-(11,9)) + ├── flags: ∅ └── body: (length: 3) ├── @ DefNode (location: (1,6)-(3,9)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (1,10)-(1,11) = "f" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (2,8)-(2,17)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (2,8)-(2,17)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :g @@ -23,16 +27,18 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 2) │ │ │ ├── @ ParenthesesNode (location: (2,10)-(2,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── body: │ │ │ │ │ @ StatementsNode (location: (2,12)-(2,13)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (2,12)-(2,13)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── opening_loc: (2,10)-(2,11) = "(" │ │ │ │ └── closing_loc: (2,13)-(2,14) = ")" │ │ │ └── @ IntegerNode (location: (2,16)-(2,17)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ @@ -44,15 +50,17 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (3,6)-(3,9) = "end" ├── @ DefNode (location: (6,6)-(8,9)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (6,10)-(6,11) = "f" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (7,8)-(7,16)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (7,8)-(7,16)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :g @@ -63,16 +71,18 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 2) │ │ │ ├── @ ParenthesesNode (location: (7,10)-(7,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── body: │ │ │ │ │ @ StatementsNode (location: (7,11)-(7,12)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (7,11)-(7,12)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── opening_loc: (7,10)-(7,11) = "(" │ │ │ │ └── closing_loc: (7,12)-(7,13) = ")" │ │ │ └── @ IntegerNode (location: (7,15)-(7,16)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ @@ -84,7 +94,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (8,6)-(8,9) = "end" └── @ CallNode (location: (11,0)-(11,9)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :g @@ -95,16 +105,18 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ ParenthesesNode (location: (11,2)-(11,6)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (11,4)-(11,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (11,4)-(11,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: newline, static_literal, decimal │ │ │ └── value: 1 │ │ ├── opening_loc: (11,2)-(11,3) = "(" │ │ └── closing_loc: (11,5)-(11,6) = ")" │ └── @ IntegerNode (location: (11,8)-(11,9)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/bug_case_when_regexp.txt b/test/prism/snapshots/seattlerb/bug_case_when_regexp.txt index 0cc1ca05e1f..e24a170ad4f 100644 --- a/test/prism/snapshots/seattlerb/bug_case_when_regexp.txt +++ b/test/prism/snapshots/seattlerb/bug_case_when_regexp.txt @@ -1,28 +1,32 @@ @ ProgramNode (location: (1,0)-(1,26)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,26)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseNode (location: (1,0)-(1,26)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "x" │ ├── closing_loc: ∅ │ └── unescaped: "x" ├── conditions: (length: 1) │ └── @ WhenNode (location: (1,9)-(1,22)) + │ ├── flags: ∅ │ ├── keyword_loc: (1,9)-(1,13) = "when" │ ├── conditions: (length: 1) │ │ └── @ RegularExpressionNode (location: (1,14)-(1,17)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,14)-(1,15) = "/" │ │ ├── content_loc: (1,15)-(1,16) = "x" │ │ ├── closing_loc: (1,16)-(1,17) = "/" │ │ └── unescaped: "x" │ ├── then_keyword_loc: (1,18)-(1,22) = "then" │ └── statements: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (1,23)-(1,26) = "end" diff --git a/test/prism/snapshots/seattlerb/bug_comma.txt b/test/prism/snapshots/seattlerb/bug_comma.txt index af886999b5e..d370ea0ac0e 100644 --- a/test/prism/snapshots/seattlerb/bug_comma.txt +++ b/test/prism/snapshots/seattlerb/bug_comma.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(1,24)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,24)) + ├── flags: ∅ └── body: (length: 1) └── @ IfNode (location: (1,0)-(1,24)) + ├── flags: newline ├── if_keyword_loc: (1,0)-(1,2) = "if" ├── predicate: │ @ CallNode (location: (1,3)-(1,15)) @@ -37,5 +40,5 @@ │ └── block: ∅ ├── then_keyword_loc: (1,16)-(1,20) = "then" ├── statements: ∅ - ├── consequent: ∅ + ├── subsequent: ∅ └── end_keyword_loc: (1,21)-(1,24) = "end" diff --git a/test/prism/snapshots/seattlerb/bug_cond_pct.txt b/test/prism/snapshots/seattlerb/bug_cond_pct.txt index cbf3bc3ef02..0b96c5c44e4 100644 --- a/test/prism/snapshots/seattlerb/bug_cond_pct.txt +++ b/test/prism/snapshots/seattlerb/bug_cond_pct.txt @@ -1,22 +1,26 @@ @ ProgramNode (location: (1,0)-(1,28)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,28)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseNode (location: (1,0)-(1,28)) + ├── flags: newline ├── predicate: ∅ ├── conditions: (length: 1) │ └── @ WhenNode (location: (1,6)-(1,23)) + │ ├── flags: ∅ │ ├── keyword_loc: (1,6)-(1,10) = "when" │ ├── conditions: (length: 1) │ │ └── @ RegularExpressionNode (location: (1,11)-(1,23)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,11)-(1,14) = "%r%" │ │ ├── content_loc: (1,14)-(1,22) = "blahblah" │ │ ├── closing_loc: (1,22)-(1,23) = "%" │ │ └── unescaped: "blahblah" │ ├── then_keyword_loc: ∅ │ └── statements: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (1,25)-(1,28) = "end" diff --git a/test/prism/snapshots/seattlerb/bug_hash_args.txt b/test/prism/snapshots/seattlerb/bug_hash_args.txt index e138db4d491..cd90f0ebc60 100644 --- a/test/prism/snapshots/seattlerb/bug_hash_args.txt +++ b/test/prism/snapshots/seattlerb/bug_hash_args.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,19)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,19)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,19)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :foo @@ -15,7 +17,7 @@ │ ├── flags: contains_keywords │ └── arguments: (length: 2) │ ├── @ SymbolNode (location: (1,4)-(1,8)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,4)-(1,5) = ":" │ │ ├── value_loc: (1,5)-(1,8) = "bar" │ │ ├── closing_loc: ∅ @@ -24,15 +26,17 @@ │ ├── flags: symbol_keys │ └── elements: (length: 1) │ └── @ AssocNode (location: (1,10)-(1,18)) + │ ├── flags: static_literal │ ├── key: │ │ @ SymbolNode (location: (1,10)-(1,14)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,10)-(1,13) = "baz" │ │ ├── closing_loc: (1,13)-(1,14) = ":" │ │ └── unescaped: "baz" │ ├── value: │ │ @ NilNode (location: (1,15)-(1,18)) + │ │ └── flags: static_literal │ └── operator_loc: ∅ ├── closing_loc: (1,18)-(1,19) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/bug_hash_args_trailing_comma.txt b/test/prism/snapshots/seattlerb/bug_hash_args_trailing_comma.txt index fe2d7f73c97..8c06cabf1c2 100644 --- a/test/prism/snapshots/seattlerb/bug_hash_args_trailing_comma.txt +++ b/test/prism/snapshots/seattlerb/bug_hash_args_trailing_comma.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,20)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,20)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,20)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :foo @@ -15,7 +17,7 @@ │ ├── flags: contains_keywords │ └── arguments: (length: 2) │ ├── @ SymbolNode (location: (1,4)-(1,8)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,4)-(1,5) = ":" │ │ ├── value_loc: (1,5)-(1,8) = "bar" │ │ ├── closing_loc: ∅ @@ -24,15 +26,17 @@ │ ├── flags: symbol_keys │ └── elements: (length: 1) │ └── @ AssocNode (location: (1,10)-(1,18)) + │ ├── flags: static_literal │ ├── key: │ │ @ SymbolNode (location: (1,10)-(1,14)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,10)-(1,13) = "baz" │ │ ├── closing_loc: (1,13)-(1,14) = ":" │ │ └── unescaped: "baz" │ ├── value: │ │ @ NilNode (location: (1,15)-(1,18)) + │ │ └── flags: static_literal │ └── operator_loc: ∅ ├── closing_loc: (1,19)-(1,20) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/bug_hash_interp_array.txt b/test/prism/snapshots/seattlerb/bug_hash_interp_array.txt index 433fb024115..3d9fc56850b 100644 --- a/test/prism/snapshots/seattlerb/bug_hash_interp_array.txt +++ b/test/prism/snapshots/seattlerb/bug_hash_interp_array.txt @@ -1,24 +1,30 @@ @ ProgramNode (location: (1,0)-(1,13)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,13)) + ├── flags: ∅ └── body: (length: 1) └── @ HashNode (location: (1,0)-(1,13)) + ├── flags: newline ├── opening_loc: (1,0)-(1,1) = "{" ├── elements: (length: 1) │ └── @ AssocNode (location: (1,2)-(1,11)) + │ ├── flags: ∅ │ ├── key: │ │ @ InterpolatedSymbolNode (location: (1,2)-(1,8)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (1,2)-(1,3) = "\"" │ │ ├── parts: (length: 1) │ │ │ └── @ EmbeddedStatementsNode (location: (1,3)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (1,3)-(1,5) = "\#{" │ │ │ ├── statements: ∅ │ │ │ └── closing_loc: (1,5)-(1,6) = "}" │ │ └── closing_loc: (1,6)-(1,8) = "\":" │ ├── value: │ │ @ ArrayNode (location: (1,9)-(1,11)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── elements: (length: 0) │ │ ├── opening_loc: (1,9)-(1,10) = "[" │ │ └── closing_loc: (1,10)-(1,11) = "]" diff --git a/test/prism/snapshots/seattlerb/bug_masgn_right.txt b/test/prism/snapshots/seattlerb/bug_masgn_right.txt index b4c75c4607e..e5b635d802d 100644 --- a/test/prism/snapshots/seattlerb/bug_masgn_right.txt +++ b/test/prism/snapshots/seattlerb/bug_masgn_right.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,17)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,16 +16,20 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,17)) + ├── flags: ∅ ├── locals: [:a, :b, :c] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,15)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (1,9)-(1,10)) │ │ │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/bug_not_parens.txt b/test/prism/snapshots/seattlerb/bug_not_parens.txt index 9e4a416d4aa..163fb79564f 100644 --- a/test/prism/snapshots/seattlerb/bug_not_parens.txt +++ b/test/prism/snapshots/seattlerb/bug_not_parens.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,6)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,4)-(1,5)) │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/seattlerb/bug_op_asgn_rescue.txt b/test/prism/snapshots/seattlerb/bug_op_asgn_rescue.txt index 33016f32f86..9da753aece0 100644 --- a/test/prism/snapshots/seattlerb/bug_op_asgn_rescue.txt +++ b/test/prism/snapshots/seattlerb/bug_op_asgn_rescue.txt @@ -1,13 +1,17 @@ @ ProgramNode (location: (1,0)-(1,18)) +├── flags: ∅ ├── locals: [:a] └── statements: @ StatementsNode (location: (1,0)-(1,18)) + ├── flags: ∅ └── body: (length: 1) └── @ LocalVariableOrWriteNode (location: (1,0)-(1,18)) + ├── flags: newline ├── name_loc: (1,0)-(1,1) = "a" ├── operator_loc: (1,2)-(1,5) = "||=" ├── value: │ @ RescueModifierNode (location: (1,6)-(1,18)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (1,6)-(1,7)) │ │ ├── flags: variable_call, ignore_visibility @@ -22,5 +26,6 @@ │ ├── keyword_loc: (1,8)-(1,14) = "rescue" │ └── rescue_expression: │ @ NilNode (location: (1,15)-(1,18)) + │ └── flags: static_literal ├── name: :a └── depth: 0 diff --git a/test/prism/snapshots/seattlerb/call_and.txt b/test/prism/snapshots/seattlerb/call_and.txt index d3e88b3f9e4..640f355c4a1 100644 --- a/test/prism/snapshots/seattlerb/call_and.txt +++ b/test/prism/snapshots/seattlerb/call_and.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,5)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,5)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,5)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :& @@ -18,7 +20,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_arg_assoc.txt b/test/prism/snapshots/seattlerb/call_arg_assoc.txt index f489bc7f191..b8ec9070317 100644 --- a/test/prism/snapshots/seattlerb/call_arg_assoc.txt +++ b/test/prism/snapshots/seattlerb/call_arg_assoc.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,10)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,10)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,10)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -15,19 +17,20 @@ │ ├── flags: contains_keywords │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (1,2)-(1,3)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── @ KeywordHashNode (location: (1,5)-(1,9)) │ ├── flags: ∅ │ └── elements: (length: 1) │ └── @ AssocNode (location: (1,5)-(1,9)) + │ ├── flags: static_literal │ ├── key: │ │ @ IntegerNode (location: (1,5)-(1,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── value: │ │ @ IntegerNode (location: (1,8)-(1,9)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ └── operator_loc: (1,6)-(1,8) = "=>" ├── closing_loc: (1,9)-(1,10) = ")" diff --git a/test/prism/snapshots/seattlerb/call_arg_assoc_kwsplat.txt b/test/prism/snapshots/seattlerb/call_arg_assoc_kwsplat.txt index 5b191396de5..11142b27219 100644 --- a/test/prism/snapshots/seattlerb/call_arg_assoc_kwsplat.txt +++ b/test/prism/snapshots/seattlerb/call_arg_assoc_kwsplat.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,16)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,16)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,16)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -15,28 +17,30 @@ │ ├── flags: contains_keywords, contains_keyword_splat │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (1,2)-(1,3)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── @ KeywordHashNode (location: (1,5)-(1,15)) │ ├── flags: ∅ │ └── elements: (length: 2) │ ├── @ AssocNode (location: (1,5)-(1,10)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (1,5)-(1,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,5)-(1,7) = "kw" │ │ │ ├── closing_loc: (1,7)-(1,8) = ":" │ │ │ └── unescaped: "kw" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: ∅ │ └── @ AssocSplatNode (location: (1,12)-(1,15)) + │ ├── flags: ∅ │ ├── value: │ │ @ IntegerNode (location: (1,14)-(1,15)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ └── operator_loc: (1,12)-(1,14) = "**" ├── closing_loc: (1,15)-(1,16) = ")" diff --git a/test/prism/snapshots/seattlerb/call_arg_kwsplat.txt b/test/prism/snapshots/seattlerb/call_arg_kwsplat.txt index f95b80cf7db..853f7103e3e 100644 --- a/test/prism/snapshots/seattlerb/call_arg_kwsplat.txt +++ b/test/prism/snapshots/seattlerb/call_arg_kwsplat.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,9)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,9)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,9)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -28,9 +30,10 @@ │ ├── flags: ∅ │ └── elements: (length: 1) │ └── @ AssocSplatNode (location: (1,5)-(1,8)) + │ ├── flags: ∅ │ ├── value: │ │ @ IntegerNode (location: (1,7)-(1,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (1,5)-(1,7) = "**" ├── closing_loc: (1,8)-(1,9) = ")" diff --git a/test/prism/snapshots/seattlerb/call_args_assoc_quoted.txt b/test/prism/snapshots/seattlerb/call_args_assoc_quoted.txt index 8946206a3f5..615bee5b4a9 100644 --- a/test/prism/snapshots/seattlerb/call_args_assoc_quoted.txt +++ b/test/prism/snapshots/seattlerb/call_args_assoc_quoted.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(5,8)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(5,8)) + ├── flags: ∅ └── body: (length: 3) ├── @ CallNode (location: (1,0)-(1,11)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :x @@ -18,14 +20,18 @@ │ │ ├── flags: ∅ │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (1,2)-(1,11)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ InterpolatedSymbolNode (location: (1,2)-(1,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (1,2)-(1,3) = "\"" │ │ │ ├── parts: (length: 1) │ │ │ │ └── @ EmbeddedStatementsNode (location: (1,3)-(1,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: (1,3)-(1,5) = "\#{" │ │ │ │ ├── statements: │ │ │ │ │ @ StatementsNode (location: (1,5)-(1,6)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ CallNode (location: (1,5)-(1,6)) │ │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -41,13 +47,13 @@ │ │ │ └── closing_loc: (1,7)-(1,9) = "\":" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,9)-(1,11)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 42 │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (3,0)-(3,8)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :x @@ -61,22 +67,23 @@ │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (3,2)-(3,8)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (3,2)-(3,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (3,2)-(3,3) = "\"" │ │ │ ├── value_loc: (3,3)-(3,4) = "k" │ │ │ ├── closing_loc: (3,4)-(3,6) = "\":" │ │ │ └── unescaped: "k" │ │ ├── value: │ │ │ @ IntegerNode (location: (3,6)-(3,8)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 42 │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ └── @ CallNode (location: (5,0)-(5,8)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :x @@ -90,16 +97,17 @@ │ ├── flags: symbol_keys │ └── elements: (length: 1) │ └── @ AssocNode (location: (5,2)-(5,8)) + │ ├── flags: static_literal │ ├── key: │ │ @ SymbolNode (location: (5,2)-(5,6)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (5,2)-(5,3) = "'" │ │ ├── value_loc: (5,3)-(5,4) = "k" │ │ ├── closing_loc: (5,4)-(5,6) = "':" │ │ └── unescaped: "k" │ ├── value: │ │ @ IntegerNode (location: (5,6)-(5,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 42 │ └── operator_loc: ∅ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/call_args_assoc_trailing_comma.txt b/test/prism/snapshots/seattlerb/call_args_assoc_trailing_comma.txt index 0ba5891cf6c..00bc620f544 100644 --- a/test/prism/snapshots/seattlerb/call_args_assoc_trailing_comma.txt +++ b/test/prism/snapshots/seattlerb/call_args_assoc_trailing_comma.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,11)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,11)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,11)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -15,19 +17,20 @@ │ ├── flags: contains_keywords │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (1,2)-(1,3)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── @ KeywordHashNode (location: (1,5)-(1,9)) │ ├── flags: ∅ │ └── elements: (length: 1) │ └── @ AssocNode (location: (1,5)-(1,9)) + │ ├── flags: static_literal │ ├── key: │ │ @ IntegerNode (location: (1,5)-(1,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── value: │ │ @ IntegerNode (location: (1,8)-(1,9)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ └── operator_loc: (1,6)-(1,8) = "=>" ├── closing_loc: (1,10)-(1,11) = ")" diff --git a/test/prism/snapshots/seattlerb/call_args_command.txt b/test/prism/snapshots/seattlerb/call_args_command.txt index f4a55ff58c3..6fe112f224a 100644 --- a/test/prism/snapshots/seattlerb/call_args_command.txt +++ b/test/prism/snapshots/seattlerb/call_args_command.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,9)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,9)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,9)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,0)-(1,1)) │ ├── flags: variable_call, ignore_visibility @@ -46,7 +48,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,8)-(1,9)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_array_arg.txt b/test/prism/snapshots/seattlerb/call_array_arg.txt index 95d2f4859d0..cec613bc582 100644 --- a/test/prism/snapshots/seattlerb/call_array_arg.txt +++ b/test/prism/snapshots/seattlerb/call_array_arg.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,13)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,13)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,13)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :== @@ -18,16 +20,16 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ ArrayNode (location: (1,5)-(1,13)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (1,6)-(1,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,6)-(1,7) = ":" │ │ │ ├── value_loc: (1,7)-(1,8) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" │ │ └── @ SymbolNode (location: (1,10)-(1,12)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,10)-(1,11) = ":" │ │ ├── value_loc: (1,11)-(1,12) = "c" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/call_array_block_call.txt b/test/prism/snapshots/seattlerb/call_array_block_call.txt index e02740e7f58..4a044924e9f 100644 --- a/test/prism/snapshots/seattlerb/call_array_block_call.txt +++ b/test/prism/snapshots/seattlerb/call_array_block_call.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,19)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,19)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,19)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -18,6 +20,7 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ NilNode (location: (1,4)-(1,7)) + │ │ │ └── flags: static_literal │ │ └── @ CallNode (location: (1,9)-(1,17)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ @@ -29,6 +32,7 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (1,11)-(1,17)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/call_array_lambda_block_call.txt b/test/prism/snapshots/seattlerb/call_array_lambda_block_call.txt index c6aa7228123..dca64e5f7b2 100644 --- a/test/prism/snapshots/seattlerb/call_array_lambda_block_call.txt +++ b/test/prism/snapshots/seattlerb/call_array_lambda_block_call.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(2,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(2,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(2,3)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -18,12 +20,14 @@ │ ├── flags: ∅ │ ├── elements: (length: 1) │ │ └── @ LambdaNode (location: (1,3)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── operator_loc: (1,3)-(1,5) = "->" │ │ ├── opening_loc: (1,8)-(1,9) = "{" │ │ ├── closing_loc: (1,9)-(1,10) = "}" │ │ ├── parameters: │ │ │ @ BlockParametersNode (location: (1,5)-(1,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── parameters: ∅ │ │ │ ├── locals: (length: 0) │ │ │ ├── opening_loc: (1,5)-(1,6) = "(" @@ -34,6 +38,7 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,12)-(2,3)) + ├── flags: ∅ ├── locals: [] ├── parameters: ∅ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/call_array_lit_inline_hash.txt b/test/prism/snapshots/seattlerb/call_array_lit_inline_hash.txt index 091e21c00a6..f83c7a55e5b 100644 --- a/test/prism/snapshots/seattlerb/call_array_lit_inline_hash.txt +++ b/test/prism/snapshots/seattlerb/call_array_lit_inline_hash.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,16)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,16)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,16)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -18,7 +20,7 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (1,3)-(1,5)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,3)-(1,4) = ":" │ │ │ ├── value_loc: (1,4)-(1,5) = "b" │ │ │ ├── closing_loc: ∅ @@ -27,16 +29,17 @@ │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (1,7)-(1,14)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (1,7)-(1,9)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,7)-(1,8) = ":" │ │ │ ├── value_loc: (1,8)-(1,9) = "c" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "c" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,13)-(1,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── operator_loc: (1,10)-(1,12) = "=>" │ ├── opening_loc: (1,2)-(1,3) = "[" diff --git a/test/prism/snapshots/seattlerb/call_assoc.txt b/test/prism/snapshots/seattlerb/call_assoc.txt index 60784e6095a..a4e4512a082 100644 --- a/test/prism/snapshots/seattlerb/call_assoc.txt +++ b/test/prism/snapshots/seattlerb/call_assoc.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,7)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,7)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,7)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -18,13 +20,14 @@ │ ├── flags: ∅ │ └── elements: (length: 1) │ └── @ AssocNode (location: (1,2)-(1,6)) + │ ├── flags: static_literal │ ├── key: │ │ @ IntegerNode (location: (1,2)-(1,3)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── value: │ │ @ IntegerNode (location: (1,5)-(1,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ └── operator_loc: (1,3)-(1,5) = "=>" ├── closing_loc: (1,6)-(1,7) = ")" diff --git a/test/prism/snapshots/seattlerb/call_assoc_new.txt b/test/prism/snapshots/seattlerb/call_assoc_new.txt index dc25fb24931..6cbc942a6ba 100644 --- a/test/prism/snapshots/seattlerb/call_assoc_new.txt +++ b/test/prism/snapshots/seattlerb/call_assoc_new.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,6)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -18,16 +20,17 @@ │ ├── flags: symbol_keys │ └── elements: (length: 1) │ └── @ AssocNode (location: (1,2)-(1,5)) + │ ├── flags: static_literal │ ├── key: │ │ @ SymbolNode (location: (1,2)-(1,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,2)-(1,3) = "a" │ │ ├── closing_loc: (1,3)-(1,4) = ":" │ │ └── unescaped: "a" │ ├── value: │ │ @ IntegerNode (location: (1,4)-(1,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ └── operator_loc: ∅ ├── closing_loc: (1,5)-(1,6) = ")" diff --git a/test/prism/snapshots/seattlerb/call_assoc_new_if_multiline.txt b/test/prism/snapshots/seattlerb/call_assoc_new_if_multiline.txt index b3d652e879c..a258b734a30 100644 --- a/test/prism/snapshots/seattlerb/call_assoc_new_if_multiline.txt +++ b/test/prism/snapshots/seattlerb/call_assoc_new_if_multiline.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(5,4)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(5,4)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(5,4)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -18,19 +20,21 @@ │ ├── flags: symbol_keys │ └── elements: (length: 1) │ └── @ AssocNode (location: (1,2)-(5,3)) + │ ├── flags: ∅ │ ├── key: │ │ @ SymbolNode (location: (1,2)-(1,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,2)-(1,3) = "b" │ │ ├── closing_loc: (1,3)-(1,4) = ":" │ │ └── unescaped: "b" │ ├── value: │ │ @ IfNode (location: (1,5)-(5,3)) + │ │ ├── flags: newline │ │ ├── if_keyword_loc: (1,5)-(1,7) = "if" │ │ ├── predicate: │ │ │ @ SymbolNode (location: (1,8)-(1,10)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,8)-(1,9) = ":" │ │ │ ├── value_loc: (1,9)-(1,10) = "c" │ │ │ ├── closing_loc: ∅ @@ -38,18 +42,21 @@ │ │ ├── then_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (2,0)-(2,1)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (2,0)-(2,1)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: newline, static_literal, decimal │ │ │ └── value: 1 - │ │ ├── consequent: + │ │ ├── subsequent: │ │ │ @ ElseNode (location: (3,0)-(5,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── else_keyword_loc: (3,0)-(3,4) = "else" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (4,0)-(4,1)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (4,0)-(4,1)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ └── value: 2 │ │ │ └── end_keyword_loc: (5,0)-(5,3) = "end" │ │ └── end_keyword_loc: (5,0)-(5,3) = "end" diff --git a/test/prism/snapshots/seattlerb/call_assoc_trailing_comma.txt b/test/prism/snapshots/seattlerb/call_assoc_trailing_comma.txt index b2012f0f75f..a240775d69b 100644 --- a/test/prism/snapshots/seattlerb/call_assoc_trailing_comma.txt +++ b/test/prism/snapshots/seattlerb/call_assoc_trailing_comma.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,8)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,8)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,8)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -18,13 +20,14 @@ │ ├── flags: ∅ │ └── elements: (length: 1) │ └── @ AssocNode (location: (1,2)-(1,6)) + │ ├── flags: static_literal │ ├── key: │ │ @ IntegerNode (location: (1,2)-(1,3)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── value: │ │ @ IntegerNode (location: (1,5)-(1,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ └── operator_loc: (1,3)-(1,5) = "=>" ├── closing_loc: (1,7)-(1,8) = ")" diff --git a/test/prism/snapshots/seattlerb/call_bang_command_call.txt b/test/prism/snapshots/seattlerb/call_bang_command_call.txt index 5e4e10d953c..e226d652785 100644 --- a/test/prism/snapshots/seattlerb/call_bang_command_call.txt +++ b/test/prism/snapshots/seattlerb/call_bang_command_call.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,7)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,7)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,7)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,2)-(1,7)) │ ├── flags: ∅ @@ -28,7 +30,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_bang_squiggle.txt b/test/prism/snapshots/seattlerb/call_bang_squiggle.txt index bf11bc0136f..5c10841f739 100644 --- a/test/prism/snapshots/seattlerb/call_bang_squiggle.txt +++ b/test/prism/snapshots/seattlerb/call_bang_squiggle.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,6)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :!~ @@ -18,7 +20,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_begin_call_block_call.txt b/test/prism/snapshots/seattlerb/call_begin_call_block_call.txt index 1aa994c8e6d..240a3aaa76b 100644 --- a/test/prism/snapshots/seattlerb/call_begin_call_block_call.txt +++ b/test/prism/snapshots/seattlerb/call_begin_call_block_call.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(3,3)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -15,12 +17,14 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ BeginNode (location: (1,2)-(3,3)) + │ ├── flags: ∅ │ ├── begin_keyword_loc: (1,2)-(1,7) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (2,0)-(2,10)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (2,0)-(2,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ CallNode (location: (2,0)-(2,1)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -40,6 +44,7 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (2,4)-(2,10)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/call_block_arg_named.txt b/test/prism/snapshots/seattlerb/call_block_arg_named.txt index f87c29cf2e1..db6fc7a059a 100644 --- a/test/prism/snapshots/seattlerb/call_block_arg_named.txt +++ b/test/prism/snapshots/seattlerb/call_block_arg_named.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,6)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :x @@ -14,6 +16,7 @@ ├── closing_loc: (1,6)-(1,7) = ")" └── block: @ BlockArgumentNode (location: (1,2)-(1,6)) + ├── flags: ∅ ├── expression: │ @ CallNode (location: (1,3)-(1,6)) │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/seattlerb/call_carat.txt b/test/prism/snapshots/seattlerb/call_carat.txt index 856e9a7847f..88ed832aca9 100644 --- a/test/prism/snapshots/seattlerb/call_carat.txt +++ b/test/prism/snapshots/seattlerb/call_carat.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,5)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,5)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,5)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :^ @@ -18,7 +20,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_colon2.txt b/test/prism/snapshots/seattlerb/call_colon2.txt index 98bfc631260..85e39cd3636 100644 --- a/test/prism/snapshots/seattlerb/call_colon2.txt +++ b/test/prism/snapshots/seattlerb/call_colon2.txt @@ -1,12 +1,15 @@ @ ProgramNode (location: (1,0)-(1,4)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,4)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,4)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ ConstantReadNode (location: (1,0)-(1,1)) + │ ├── flags: ∅ │ └── name: :A ├── call_operator_loc: (1,1)-(1,3) = "::" ├── name: :b diff --git a/test/prism/snapshots/seattlerb/call_colon_parens.txt b/test/prism/snapshots/seattlerb/call_colon_parens.txt index 6d10171a2b1..19141c34133 100644 --- a/test/prism/snapshots/seattlerb/call_colon_parens.txt +++ b/test/prism/snapshots/seattlerb/call_colon_parens.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,5)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,5)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,5)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: (1,1)-(1,3) = "::" ├── name: :call diff --git a/test/prism/snapshots/seattlerb/call_div.txt b/test/prism/snapshots/seattlerb/call_div.txt index ba62fb87bd1..55a410977c3 100644 --- a/test/prism/snapshots/seattlerb/call_div.txt +++ b/test/prism/snapshots/seattlerb/call_div.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,5)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,5)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,5)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :/ @@ -18,7 +20,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_dot_parens.txt b/test/prism/snapshots/seattlerb/call_dot_parens.txt index c9b70846996..29b592a960d 100644 --- a/test/prism/snapshots/seattlerb/call_dot_parens.txt +++ b/test/prism/snapshots/seattlerb/call_dot_parens.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,4)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,4)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,4)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: (1,1)-(1,2) = "." ├── name: :call diff --git a/test/prism/snapshots/seattlerb/call_env.txt b/test/prism/snapshots/seattlerb/call_env.txt index fd1f95388ed..933621594f8 100644 --- a/test/prism/snapshots/seattlerb/call_env.txt +++ b/test/prism/snapshots/seattlerb/call_env.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,7)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,7)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,7)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,0)-(1,1)) │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/seattlerb/call_eq3.txt b/test/prism/snapshots/seattlerb/call_eq3.txt index e636e157257..52e4b00c5ce 100644 --- a/test/prism/snapshots/seattlerb/call_eq3.txt +++ b/test/prism/snapshots/seattlerb/call_eq3.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,7)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,7)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,7)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :=== @@ -18,7 +20,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_gt.txt b/test/prism/snapshots/seattlerb/call_gt.txt index a6f19e5adfe..22371dd8ca0 100644 --- a/test/prism/snapshots/seattlerb/call_gt.txt +++ b/test/prism/snapshots/seattlerb/call_gt.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,5)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,5)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,5)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :> @@ -18,7 +20,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_kwsplat.txt b/test/prism/snapshots/seattlerb/call_kwsplat.txt index e0620dc5f0b..17773e76933 100644 --- a/test/prism/snapshots/seattlerb/call_kwsplat.txt +++ b/test/prism/snapshots/seattlerb/call_kwsplat.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,6)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -18,9 +20,10 @@ │ ├── flags: ∅ │ └── elements: (length: 1) │ └── @ AssocSplatNode (location: (1,2)-(1,5)) + │ ├── flags: ∅ │ ├── value: │ │ @ IntegerNode (location: (1,4)-(1,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (1,2)-(1,4) = "**" ├── closing_loc: (1,5)-(1,6) = ")" diff --git a/test/prism/snapshots/seattlerb/call_leading_dots.txt b/test/prism/snapshots/seattlerb/call_leading_dots.txt index e8435d7e7a1..5562afcd702 100644 --- a/test/prism/snapshots/seattlerb/call_leading_dots.txt +++ b/test/prism/snapshots/seattlerb/call_leading_dots.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(3,2)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,2)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(3,2)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,0)-(2,2)) │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/call_leading_dots_comment.txt b/test/prism/snapshots/seattlerb/call_leading_dots_comment.txt index e5dfb723723..f285e42cbf4 100644 --- a/test/prism/snapshots/seattlerb/call_leading_dots_comment.txt +++ b/test/prism/snapshots/seattlerb/call_leading_dots_comment.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(4,2)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,2)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(4,2)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,0)-(2,2)) │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/call_lt.txt b/test/prism/snapshots/seattlerb/call_lt.txt index 14f50585d93..bec3deddd08 100644 --- a/test/prism/snapshots/seattlerb/call_lt.txt +++ b/test/prism/snapshots/seattlerb/call_lt.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,5)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,5)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,5)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :< @@ -18,7 +20,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_lte.txt b/test/prism/snapshots/seattlerb/call_lte.txt index 665a99d60a8..a71e03ee128 100644 --- a/test/prism/snapshots/seattlerb/call_lte.txt +++ b/test/prism/snapshots/seattlerb/call_lte.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,6)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :<= @@ -18,7 +20,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_not.txt b/test/prism/snapshots/seattlerb/call_not.txt index 86c68923031..e9df80fb9f2 100644 --- a/test/prism/snapshots/seattlerb/call_not.txt +++ b/test/prism/snapshots/seattlerb/call_not.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,6)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,4)-(1,6)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 42 ├── call_operator_loc: ∅ ├── name: :! diff --git a/test/prism/snapshots/seattlerb/call_pipe.txt b/test/prism/snapshots/seattlerb/call_pipe.txt index 855e986ef6f..8cf68211a99 100644 --- a/test/prism/snapshots/seattlerb/call_pipe.txt +++ b/test/prism/snapshots/seattlerb/call_pipe.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,5)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,5)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,5)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :| @@ -18,7 +20,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_rshift.txt b/test/prism/snapshots/seattlerb/call_rshift.txt index 26e593db187..28948a044f9 100644 --- a/test/prism/snapshots/seattlerb/call_rshift.txt +++ b/test/prism/snapshots/seattlerb/call_rshift.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,6)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :>> @@ -18,7 +20,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_self_brackets.txt b/test/prism/snapshots/seattlerb/call_self_brackets.txt index 16ca69b5c29..e4f5e2c4131 100644 --- a/test/prism/snapshots/seattlerb/call_self_brackets.txt +++ b/test/prism/snapshots/seattlerb/call_self_brackets.txt @@ -1,12 +1,15 @@ @ ProgramNode (location: (1,0)-(1,7)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,7)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,7)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: │ @ SelfNode (location: (1,0)-(1,4)) + │ └── flags: ∅ ├── call_operator_loc: ∅ ├── name: :[] ├── message_loc: (1,4)-(1,7) = "[1]" @@ -16,7 +19,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── closing_loc: (1,6)-(1,7) = "]" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_spaceship.txt b/test/prism/snapshots/seattlerb/call_spaceship.txt index 8d43c3f9710..4ea67f2e00b 100644 --- a/test/prism/snapshots/seattlerb/call_spaceship.txt +++ b/test/prism/snapshots/seattlerb/call_spaceship.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,7)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,7)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,7)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :<=> @@ -18,7 +20,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_stabby_do_end_with_block.txt b/test/prism/snapshots/seattlerb/call_stabby_do_end_with_block.txt index 242db9e9cb5..0e83d334cac 100644 --- a/test/prism/snapshots/seattlerb/call_stabby_do_end_with_block.txt +++ b/test/prism/snapshots/seattlerb/call_stabby_do_end_with_block.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,22)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,22)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,22)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -15,6 +17,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ LambdaNode (location: (1,2)-(1,13)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── operator_loc: (1,2)-(1,4) = "->" │ ├── opening_loc: (1,5)-(1,7) = "do" @@ -22,20 +25,23 @@ │ ├── parameters: ∅ │ └── body: │ @ StatementsNode (location: (1,8)-(1,9)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,8)-(1,9)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 1 ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,14)-(1,22)) + ├── flags: ∅ ├── locals: [] ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (1,17)-(1,18)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,17)-(1,18)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 2 ├── opening_loc: (1,14)-(1,16) = "do" └── closing_loc: (1,19)-(1,22) = "end" diff --git a/test/prism/snapshots/seattlerb/call_stabby_with_braces_block.txt b/test/prism/snapshots/seattlerb/call_stabby_with_braces_block.txt index 7c3ab8dad8f..705f8b8d022 100644 --- a/test/prism/snapshots/seattlerb/call_stabby_with_braces_block.txt +++ b/test/prism/snapshots/seattlerb/call_stabby_with_braces_block.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,19)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,19)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,19)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -15,6 +17,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ LambdaNode (location: (1,2)-(1,10)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── operator_loc: (1,2)-(1,4) = "->" │ ├── opening_loc: (1,5)-(1,6) = "{" @@ -22,20 +25,23 @@ │ ├── parameters: ∅ │ └── body: │ @ StatementsNode (location: (1,7)-(1,8)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,7)-(1,8)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 1 ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,11)-(1,19)) + ├── flags: ∅ ├── locals: [] ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (1,14)-(1,15)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,14)-(1,15)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 2 ├── opening_loc: (1,11)-(1,13) = "do" └── closing_loc: (1,16)-(1,19) = "end" diff --git a/test/prism/snapshots/seattlerb/call_star.txt b/test/prism/snapshots/seattlerb/call_star.txt index 49aee1672c7..06bee81f30d 100644 --- a/test/prism/snapshots/seattlerb/call_star.txt +++ b/test/prism/snapshots/seattlerb/call_star.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,5)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,5)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,5)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :* @@ -18,7 +20,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_star2.txt b/test/prism/snapshots/seattlerb/call_star2.txt index cc2532cc7c8..bd367d2e758 100644 --- a/test/prism/snapshots/seattlerb/call_star2.txt +++ b/test/prism/snapshots/seattlerb/call_star2.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,6)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :** @@ -18,7 +20,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_trailing_comma.txt b/test/prism/snapshots/seattlerb/call_trailing_comma.txt index fe28a3ad3eb..01cb77a25a0 100644 --- a/test/prism/snapshots/seattlerb/call_trailing_comma.txt +++ b/test/prism/snapshots/seattlerb/call_trailing_comma.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,5)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,5)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,5)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -15,7 +17,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,2)-(1,3)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── closing_loc: (1,4)-(1,5) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_trailing_dots.txt b/test/prism/snapshots/seattlerb/call_trailing_dots.txt index b0e23eb27b9..73ffd855ad8 100644 --- a/test/prism/snapshots/seattlerb/call_trailing_dots.txt +++ b/test/prism/snapshots/seattlerb/call_trailing_dots.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(3,1)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,1)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(3,1)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,0)-(2,1)) │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/call_unary_bang.txt b/test/prism/snapshots/seattlerb/call_unary_bang.txt index 782cc83b103..b08f0706930 100644 --- a/test/prism/snapshots/seattlerb/call_unary_bang.txt +++ b/test/prism/snapshots/seattlerb/call_unary_bang.txt @@ -1,13 +1,15 @@ @ ProgramNode (location: (1,0)-(1,2)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,2)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,2)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ IntegerNode (location: (1,1)-(1,2)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :! diff --git a/test/prism/snapshots/seattlerb/case_in.txt b/test/prism/snapshots/seattlerb/case_in.txt index 950d66647e6..929cca0d382 100644 --- a/test/prism/snapshots/seattlerb/case_in.txt +++ b/test/prism/snapshots/seattlerb/case_in.txt @@ -1,34 +1,42 @@ @ ProgramNode (location: (1,0)-(111,3)) +├── flags: ∅ ├── locals: [:b, :_, :lhs, :x, :rhs, :c, :e] └── statements: @ StatementsNode (location: (1,0)-(111,3)) + ├── flags: ∅ └── body: (length: 28) ├── @ CaseMatchNode (location: (1,0)-(3,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (1,5)-(1,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,5)-(1,6) = ":" │ │ ├── value_loc: (1,6)-(1,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (2,0)-(2,8)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ HashPatternNode (location: (2,4)-(2,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── elements: (length: 1) │ │ │ │ └── @ AssocNode (location: (2,4)-(2,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (2,4)-(2,8)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (2,4)-(2,5) = "\"" │ │ │ │ │ ├── value_loc: (2,5)-(2,6) = "b" │ │ │ │ │ ├── closing_loc: (2,6)-(2,8) = "\":" │ │ │ │ │ └── unescaped: "b" │ │ │ │ ├── value: │ │ │ │ │ @ ImplicitNode (location: (2,5)-(2,6)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── value: │ │ │ │ │ @ LocalVariableTargetNode (location: (2,5)-(2,6)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :b │ │ │ │ │ └── depth: 0 │ │ │ │ └── operator_loc: ∅ @@ -38,31 +46,33 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (2,0)-(2,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (1,0)-(1,4) = "case" │ └── end_keyword_loc: (3,0)-(3,3) = "end" ├── @ CaseMatchNode (location: (5,0)-(7,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (5,5)-(5,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (5,5)-(5,6) = ":" │ │ ├── value_loc: (5,6)-(5,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (6,0)-(6,10)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayNode (location: (6,3)-(6,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: static_literal │ │ │ ├── elements: (length: 2) │ │ │ │ ├── @ SymbolNode (location: (6,6)-(6,7)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (6,6)-(6,7) = "a" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "a" │ │ │ │ └── @ SymbolNode (location: (6,8)-(6,9)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (6,8)-(6,9) = "b" │ │ │ │ ├── closing_loc: ∅ @@ -72,19 +82,21 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (6,0)-(6,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (5,0)-(5,4) = "case" │ └── end_keyword_loc: (7,0)-(7,3) = "end" ├── @ CaseMatchNode (location: (9,0)-(11,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (9,5)-(9,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (9,5)-(9,6) = ":" │ │ ├── value_loc: (9,6)-(9,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (10,0)-(10,10)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayNode (location: (10,3)-(10,10)) │ │ │ ├── flags: ∅ @@ -106,31 +118,33 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (10,0)-(10,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (9,0)-(9,4) = "case" │ └── end_keyword_loc: (11,0)-(11,3) = "end" ├── @ CaseMatchNode (location: (13,0)-(15,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (13,5)-(13,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (13,5)-(13,6) = ":" │ │ ├── value_loc: (13,6)-(13,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (14,0)-(14,10)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayNode (location: (14,3)-(14,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: static_literal │ │ │ ├── elements: (length: 2) │ │ │ │ ├── @ SymbolNode (location: (14,6)-(14,7)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (14,6)-(14,7) = "a" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "a" │ │ │ │ └── @ SymbolNode (location: (14,8)-(14,9)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (14,8)-(14,9) = "b" │ │ │ │ ├── closing_loc: ∅ @@ -140,19 +154,21 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (14,0)-(14,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (13,0)-(13,4) = "case" │ └── end_keyword_loc: (15,0)-(15,3) = "end" ├── @ CaseMatchNode (location: (17,0)-(19,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (17,5)-(17,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (17,5)-(17,6) = ":" │ │ ├── value_loc: (17,6)-(17,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (18,0)-(18,10)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayNode (location: (18,3)-(18,10)) │ │ │ ├── flags: ∅ @@ -174,28 +190,31 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (18,0)-(18,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (17,0)-(17,4) = "case" │ └── end_keyword_loc: (19,0)-(19,3) = "end" ├── @ CaseMatchNode (location: (21,0)-(23,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (21,5)-(21,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (21,5)-(21,6) = ":" │ │ ├── value_loc: (21,6)-(21,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (22,0)-(22,10)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ParenthesesNode (location: (22,3)-(22,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ RangeNode (location: (22,4)-(22,9)) - │ │ │ │ ├── flags: exclude_end + │ │ │ │ ├── flags: static_literal, exclude_end │ │ │ │ ├── left: ∅ │ │ │ │ ├── right: │ │ │ │ │ @ IntegerNode (location: (22,7)-(22,9)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 10 │ │ │ │ └── operator_loc: (22,4)-(22,7) = "..." │ │ │ ├── opening_loc: (22,3)-(22,4) = "(" @@ -203,28 +222,31 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (22,0)-(22,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (21,0)-(21,4) = "case" │ └── end_keyword_loc: (23,0)-(23,3) = "end" ├── @ CaseMatchNode (location: (25,0)-(27,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (25,5)-(25,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (25,5)-(25,6) = ":" │ │ ├── value_loc: (25,6)-(25,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (26,0)-(26,9)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ParenthesesNode (location: (26,3)-(26,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ RangeNode (location: (26,4)-(26,8)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: static_literal │ │ │ │ ├── left: ∅ │ │ │ │ ├── right: │ │ │ │ │ @ IntegerNode (location: (26,6)-(26,8)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 10 │ │ │ │ └── operator_loc: (26,4)-(26,6) = ".." │ │ │ ├── opening_loc: (26,3)-(26,4) = "(" @@ -232,27 +254,30 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (26,0)-(26,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (25,0)-(25,4) = "case" │ └── end_keyword_loc: (27,0)-(27,3) = "end" ├── @ CaseMatchNode (location: (29,0)-(31,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (29,5)-(29,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (29,5)-(29,6) = ":" │ │ ├── value_loc: (29,6)-(29,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (30,0)-(30,9)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ParenthesesNode (location: (30,3)-(30,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ RangeNode (location: (30,4)-(30,8)) - │ │ │ │ ├── flags: exclude_end + │ │ │ │ ├── flags: static_literal, exclude_end │ │ │ │ ├── left: │ │ │ │ │ @ IntegerNode (location: (30,4)-(30,5)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── right: ∅ │ │ │ │ └── operator_loc: (30,5)-(30,8) = "..." @@ -261,31 +286,34 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (30,0)-(30,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (29,0)-(29,4) = "case" │ └── end_keyword_loc: (31,0)-(31,3) = "end" ├── @ CaseMatchNode (location: (33,0)-(35,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (33,5)-(33,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (33,5)-(33,6) = ":" │ │ ├── value_loc: (33,6)-(33,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (34,0)-(34,10)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ParenthesesNode (location: (34,3)-(34,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ RangeNode (location: (34,4)-(34,9)) - │ │ │ │ ├── flags: exclude_end + │ │ │ │ ├── flags: static_literal, exclude_end │ │ │ │ ├── left: │ │ │ │ │ @ IntegerNode (location: (34,4)-(34,5)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── right: │ │ │ │ │ @ IntegerNode (location: (34,8)-(34,9)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 3 │ │ │ │ └── operator_loc: (34,5)-(34,8) = "..." │ │ │ ├── opening_loc: (34,3)-(34,4) = "(" @@ -293,49 +321,56 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (34,0)-(34,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (33,0)-(33,4) = "case" │ └── end_keyword_loc: (35,0)-(35,3) = "end" ├── @ CaseMatchNode (location: (37,0)-(39,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (37,5)-(37,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (37,5)-(37,6) = ":" │ │ ├── value_loc: (37,6)-(37,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (38,0)-(38,7)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ParenthesesNode (location: (38,3)-(38,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ IntegerNode (location: (38,4)-(38,6)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 42 │ │ │ ├── opening_loc: (38,3)-(38,4) = "(" │ │ │ └── closing_loc: (38,6)-(38,7) = ")" │ │ ├── statements: ∅ │ │ ├── in_loc: (38,0)-(38,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (37,0)-(37,4) = "case" │ └── end_keyword_loc: (39,0)-(39,3) = "end" ├── @ CaseMatchNode (location: (41,0)-(43,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (41,5)-(41,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (41,5)-(41,6) = ":" │ │ ├── value_loc: (41,6)-(41,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (42,0)-(42,8)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ HashPatternNode (location: (42,3)-(42,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── elements: (length: 0) │ │ │ ├── rest: │ │ │ │ @ NoKeywordsParameterNode (location: (42,3)-(42,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (42,3)-(42,5) = "**" │ │ │ │ └── keyword_loc: (42,5)-(42,8) = "nil" │ │ │ ├── opening_loc: ∅ @@ -343,22 +378,24 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (42,0)-(42,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (41,0)-(41,4) = "case" │ └── end_keyword_loc: (43,0)-(43,3) = "end" ├── @ CaseMatchNode (location: (45,0)-(47,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (45,5)-(45,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (45,5)-(45,6) = ":" │ │ ├── value_loc: (45,6)-(45,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (46,0)-(46,11)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ RegularExpressionNode (location: (46,3)-(46,11)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (46,3)-(46,4) = "/" │ │ │ ├── content_loc: (46,4)-(46,10) = "regexp" │ │ │ ├── closing_loc: (46,10)-(46,11) = "/" @@ -366,39 +403,44 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (46,0)-(46,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (45,0)-(45,4) = "case" │ └── end_keyword_loc: (47,0)-(47,3) = "end" ├── @ CaseMatchNode (location: (49,0)-(51,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (49,5)-(49,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (49,5)-(49,6) = ":" │ │ ├── value_loc: (49,6)-(49,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (50,0)-(50,13)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayPatternNode (location: (50,3)-(50,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ SymbolNode (location: (50,3)-(50,5)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (50,3)-(50,4) = ":" │ │ │ │ ├── value_loc: (50,4)-(50,5) = "b" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "b" │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (50,7)-(50,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (50,7)-(50,8) = "*" │ │ │ │ └── expression: │ │ │ │ @ LocalVariableTargetNode (location: (50,8)-(50,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :_ │ │ │ │ └── depth: 0 │ │ │ ├── posts: (length: 1) │ │ │ │ └── @ SymbolNode (location: (50,11)-(50,13)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (50,11)-(50,12) = ":" │ │ │ │ ├── value_loc: (50,12)-(50,13) = "c" │ │ │ │ ├── closing_loc: ∅ @@ -408,34 +450,38 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (50,0)-(50,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (49,0)-(49,4) = "case" │ └── end_keyword_loc: (51,0)-(51,3) = "end" ├── @ CaseMatchNode (location: (53,0)-(55,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (53,5)-(53,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (53,5)-(53,6) = ":" │ │ ├── value_loc: (53,6)-(53,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (54,0)-(54,11)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayPatternNode (location: (54,3)-(54,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ SymbolNode (location: (54,3)-(54,5)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (54,3)-(54,4) = ":" │ │ │ │ │ ├── value_loc: (54,4)-(54,5) = "b" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "b" │ │ │ │ └── @ ArrayPatternNode (location: (54,7)-(54,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ └── @ SymbolNode (location: (54,8)-(54,10)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (54,8)-(54,9) = ":" │ │ │ │ │ ├── value_loc: (54,9)-(54,10) = "c" │ │ │ │ │ ├── closing_loc: ∅ @@ -451,23 +497,27 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (54,0)-(54,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (53,0)-(53,4) = "case" │ └── end_keyword_loc: (55,0)-(55,3) = "end" ├── @ CaseMatchNode (location: (57,0)-(59,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (57,5)-(57,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (57,5)-(57,6) = ":" │ │ ├── value_loc: (57,6)-(57,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (58,0)-(58,11)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayPatternNode (location: (58,3)-(58,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: │ │ │ │ @ ConstantReadNode (location: (58,3)-(58,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :Symbol │ │ │ ├── requireds: (length: 0) │ │ │ ├── rest: ∅ @@ -477,40 +527,49 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (58,0)-(58,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (57,0)-(57,4) = "case" │ └── end_keyword_loc: (59,0)-(59,3) = "end" ├── @ CaseMatchNode (location: (61,0)-(63,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (61,5)-(61,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (61,5)-(61,6) = ":" │ │ ├── value_loc: (61,6)-(61,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (62,0)-(62,24)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ FindPatternNode (location: (62,3)-(62,24)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: │ │ │ │ @ ConstantReadNode (location: (62,3)-(62,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :Symbol │ │ │ ├── left: │ │ │ │ @ SplatNode (location: (62,10)-(62,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (62,10)-(62,11) = "*" │ │ │ │ └── expression: │ │ │ │ @ LocalVariableTargetNode (location: (62,11)-(62,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :lhs │ │ │ │ └── depth: 0 │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ LocalVariableTargetNode (location: (62,16)-(62,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :x │ │ │ │ └── depth: 0 │ │ │ ├── right: │ │ │ │ @ SplatNode (location: (62,19)-(62,23)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (62,19)-(62,20) = "*" │ │ │ │ └── expression: │ │ │ │ @ LocalVariableTargetNode (location: (62,20)-(62,23)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :rhs │ │ │ │ └── depth: 0 │ │ │ ├── opening_loc: (62,9)-(62,10) = "(" @@ -518,40 +577,49 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (62,0)-(62,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (61,0)-(61,4) = "case" │ └── end_keyword_loc: (63,0)-(63,3) = "end" ├── @ CaseMatchNode (location: (65,0)-(67,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (65,5)-(65,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (65,5)-(65,6) = ":" │ │ ├── value_loc: (65,6)-(65,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (66,0)-(66,24)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ FindPatternNode (location: (66,3)-(66,24)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: │ │ │ │ @ ConstantReadNode (location: (66,3)-(66,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :Symbol │ │ │ ├── left: │ │ │ │ @ SplatNode (location: (66,10)-(66,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (66,10)-(66,11) = "*" │ │ │ │ └── expression: │ │ │ │ @ LocalVariableTargetNode (location: (66,11)-(66,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :lhs │ │ │ │ └── depth: 0 │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ LocalVariableTargetNode (location: (66,16)-(66,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :x │ │ │ │ └── depth: 0 │ │ │ ├── right: │ │ │ │ @ SplatNode (location: (66,19)-(66,23)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (66,19)-(66,20) = "*" │ │ │ │ └── expression: │ │ │ │ @ LocalVariableTargetNode (location: (66,20)-(66,23)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :rhs │ │ │ │ └── depth: 0 │ │ │ ├── opening_loc: (66,9)-(66,10) = "[" @@ -559,32 +627,38 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (66,0)-(66,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (65,0)-(65,4) = "case" │ └── end_keyword_loc: (67,0)-(67,3) = "end" ├── @ CaseMatchNode (location: (69,0)-(71,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (69,5)-(69,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (69,5)-(69,6) = ":" │ │ ├── value_loc: (69,6)-(69,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (70,0)-(70,22)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayPatternNode (location: (70,3)-(70,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ LambdaNode (location: (70,4)-(70,18)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── locals: [:b] │ │ │ │ │ ├── operator_loc: (70,4)-(70,6) = "->" │ │ │ │ │ ├── opening_loc: (70,10)-(70,11) = "{" │ │ │ │ │ ├── closing_loc: (70,17)-(70,18) = "}" │ │ │ │ │ ├── parameters: │ │ │ │ │ │ @ BlockParametersNode (location: (70,6)-(70,9)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── parameters: │ │ │ │ │ │ │ @ ParametersNode (location: (70,7)-(70,8)) + │ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ │ │ │ └── @ RequiredParameterNode (location: (70,7)-(70,8)) │ │ │ │ │ │ │ │ ├── flags: ∅ @@ -600,9 +674,12 @@ │ │ │ │ │ │ └── closing_loc: (70,8)-(70,9) = ")" │ │ │ │ │ └── body: │ │ │ │ │ @ StatementsNode (location: (70,12)-(70,16)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ TrueNode (location: (70,12)-(70,16)) + │ │ │ │ │ └── flags: newline, static_literal │ │ │ │ └── @ LocalVariableTargetNode (location: (70,20)-(70,21)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :c │ │ │ │ └── depth: 0 │ │ │ ├── rest: ∅ @@ -612,53 +689,62 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (70,0)-(70,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (69,0)-(69,4) = "case" │ └── end_keyword_loc: (71,0)-(71,3) = "end" ├── @ CaseMatchNode (location: (73,0)-(75,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (73,5)-(73,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (73,5)-(73,6) = ":" │ │ ├── value_loc: (73,6)-(73,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (74,0)-(74,28)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayPatternNode (location: (74,3)-(74,28)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── requireds: (length: 4) │ │ │ │ ├── @ SymbolNode (location: (74,4)-(74,6)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (74,4)-(74,5) = ":" │ │ │ │ │ ├── value_loc: (74,5)-(74,6) = "a" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "a" │ │ │ │ ├── @ LocalVariableTargetNode (location: (74,8)-(74,9)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :b │ │ │ │ │ └── depth: 0 │ │ │ │ ├── @ LocalVariableTargetNode (location: (74,11)-(74,12)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :c │ │ │ │ │ └── depth: 0 │ │ │ │ └── @ ArrayPatternNode (location: (74,14)-(74,27)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ └── @ SymbolNode (location: (74,15)-(74,17)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (74,15)-(74,16) = ":" │ │ │ │ │ ├── value_loc: (74,16)-(74,17) = "d" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "d" │ │ │ │ ├── rest: │ │ │ │ │ @ SplatNode (location: (74,19)-(74,21)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── operator_loc: (74,19)-(74,20) = "*" │ │ │ │ │ └── expression: │ │ │ │ │ @ LocalVariableTargetNode (location: (74,20)-(74,21)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :e │ │ │ │ │ └── depth: 0 │ │ │ │ ├── posts: (length: 1) │ │ │ │ │ └── @ NilNode (location: (74,23)-(74,26)) + │ │ │ │ │ └── flags: static_literal │ │ │ │ ├── opening_loc: (74,14)-(74,15) = "[" │ │ │ │ └── closing_loc: (74,26)-(74,27) = "]" │ │ │ ├── rest: ∅ @@ -668,64 +754,75 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (74,0)-(74,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (73,0)-(73,4) = "case" │ └── end_keyword_loc: (75,0)-(75,3) = "end" ├── @ CaseMatchNode (location: (77,0)-(79,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (77,5)-(77,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (77,5)-(77,6) = ":" │ │ ├── value_loc: (77,6)-(77,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (78,0)-(78,12)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayPatternNode (location: (78,3)-(78,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ ConstantReadNode (location: (78,4)-(78,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :A │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (78,7)-(78,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (78,7)-(78,8) = "*" │ │ │ │ └── expression: ∅ │ │ │ ├── posts: (length: 1) │ │ │ │ └── @ ConstantReadNode (location: (78,10)-(78,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :B │ │ │ ├── opening_loc: (78,3)-(78,4) = "[" │ │ │ └── closing_loc: (78,11)-(78,12) = "]" │ │ ├── statements: ∅ │ │ ├── in_loc: (78,0)-(78,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (77,0)-(77,4) = "case" │ └── end_keyword_loc: (79,0)-(79,3) = "end" ├── @ CaseMatchNode (location: (81,0)-(83,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (81,5)-(81,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (81,5)-(81,6) = ":" │ │ ├── value_loc: (81,6)-(81,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (82,0)-(82,22)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayPatternNode (location: (82,3)-(82,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ ArrayPatternNode (location: (82,4)-(82,11)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── constant: ∅ │ │ │ │ │ ├── requireds: (length: 2) │ │ │ │ │ │ ├── @ SymbolNode (location: (82,5)-(82,7)) - │ │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ │ │ ├── opening_loc: (82,5)-(82,6) = ":" │ │ │ │ │ │ │ ├── value_loc: (82,6)-(82,7) = "b" │ │ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ │ │ └── unescaped: "b" │ │ │ │ │ │ └── @ LocalVariableTargetNode (location: (82,9)-(82,10)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── name: :c │ │ │ │ │ │ └── depth: 0 │ │ │ │ │ ├── rest: ∅ @@ -733,17 +830,20 @@ │ │ │ │ │ ├── opening_loc: (82,4)-(82,5) = "[" │ │ │ │ │ └── closing_loc: (82,10)-(82,11) = "]" │ │ │ │ └── @ ArrayPatternNode (location: (82,13)-(82,21)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── requireds: (length: 2) │ │ │ │ │ ├── @ SymbolNode (location: (82,14)-(82,16)) - │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ │ ├── opening_loc: (82,14)-(82,15) = ":" │ │ │ │ │ │ ├── value_loc: (82,15)-(82,16) = "d" │ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ │ └── unescaped: "d" │ │ │ │ │ └── @ PinnedVariableNode (location: (82,18)-(82,20)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── variable: │ │ │ │ │ │ @ LocalVariableReadNode (location: (82,19)-(82,20)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── name: :e │ │ │ │ │ │ └── depth: 0 │ │ │ │ │ └── operator_loc: (82,18)-(82,19) = "^" @@ -758,21 +858,24 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (82,0)-(82,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (81,0)-(81,4) = "case" │ └── end_keyword_loc: (83,0)-(83,3) = "end" ├── @ CaseMatchNode (location: (85,0)-(87,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (85,5)-(85,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (85,5)-(85,6) = ":" │ │ ├── value_loc: (85,6)-(85,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (86,0)-(86,5)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayPatternNode (location: (86,3)-(86,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── requireds: (length: 0) │ │ │ ├── rest: ∅ @@ -782,24 +885,28 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (86,0)-(86,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (85,0)-(85,4) = "case" │ └── end_keyword_loc: (87,0)-(87,3) = "end" ├── @ CaseMatchNode (location: (89,0)-(91,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (89,5)-(89,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (89,5)-(89,6) = ":" │ │ ├── value_loc: (89,6)-(89,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (90,0)-(90,9)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayPatternNode (location: (90,3)-(90,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ PinnedExpressionNode (location: (90,4)-(90,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── expression: │ │ │ │ │ @ CallNode (location: (90,6)-(90,7)) │ │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -821,36 +928,45 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (90,0)-(90,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (89,0)-(89,4) = "case" │ └── end_keyword_loc: (91,0)-(91,3) = "end" ├── @ CaseMatchNode (location: (93,0)-(95,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (93,5)-(93,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (93,5)-(93,6) = ":" │ │ ├── value_loc: (93,6)-(93,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (94,0)-(94,19)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayPatternNode (location: (94,3)-(94,19)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── requireds: (length: 3) │ │ │ │ ├── @ PinnedVariableNode (location: (94,4)-(94,7)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── variable: │ │ │ │ │ │ @ InstanceVariableReadNode (location: (94,5)-(94,7)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :@a │ │ │ │ │ └── operator_loc: (94,4)-(94,5) = "^" │ │ │ │ ├── @ PinnedVariableNode (location: (94,9)-(94,12)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── variable: │ │ │ │ │ │ @ GlobalVariableReadNode (location: (94,10)-(94,12)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :$b │ │ │ │ │ └── operator_loc: (94,9)-(94,10) = "^" │ │ │ │ └── @ PinnedVariableNode (location: (94,14)-(94,18)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── variable: │ │ │ │ │ @ ClassVariableReadNode (location: (94,15)-(94,18)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :@@c │ │ │ │ └── operator_loc: (94,14)-(94,15) = "^" │ │ │ ├── rest: ∅ @@ -860,19 +976,21 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (94,0)-(94,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (93,0)-(93,4) = "case" │ └── end_keyword_loc: (95,0)-(95,3) = "end" ├── @ CaseMatchNode (location: (97,0)-(99,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (97,5)-(97,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (97,5)-(97,6) = ":" │ │ ├── value_loc: (97,6)-(97,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (98,0)-(98,12)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ XStringNode (location: (98,3)-(98,12)) │ │ │ ├── flags: ∅ @@ -883,26 +1001,32 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (98,0)-(98,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (97,0)-(97,4) = "case" │ └── end_keyword_loc: (99,0)-(99,3) = "end" ├── @ CaseMatchNode (location: (101,0)-(103,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (101,5)-(101,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (101,5)-(101,6) = ":" │ │ ├── value_loc: (101,6)-(101,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (102,0)-(102,16)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayPatternNode (location: (102,3)-(102,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── requireds: (length: 3) │ │ │ │ ├── @ NilNode (location: (102,3)-(102,6)) + │ │ │ │ │ └── flags: static_literal │ │ │ │ ├── @ NilNode (location: (102,8)-(102,11)) + │ │ │ │ │ └── flags: static_literal │ │ │ │ └── @ NilNode (location: (102,13)-(102,16)) + │ │ │ │ └── flags: static_literal │ │ │ ├── rest: ∅ │ │ │ ├── posts: (length: 0) │ │ │ ├── opening_loc: ∅ @@ -910,35 +1034,41 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (102,0)-(102,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (101,0)-(101,4) = "case" │ └── end_keyword_loc: (103,0)-(103,3) = "end" ├── @ CaseMatchNode (location: (105,0)-(107,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ SymbolNode (location: (105,5)-(105,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (105,5)-(105,6) = ":" │ │ ├── value_loc: (105,6)-(105,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (106,0)-(106,11)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ HashPatternNode (location: (106,3)-(106,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: ∅ │ │ │ ├── elements: (length: 1) │ │ │ │ └── @ AssocNode (location: (106,5)-(106,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (106,5)-(106,9)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (106,5)-(106,6) = "\"" │ │ │ │ │ ├── value_loc: (106,6)-(106,7) = "b" │ │ │ │ │ ├── closing_loc: (106,7)-(106,9) = "\":" │ │ │ │ │ └── unescaped: "b" │ │ │ │ ├── value: │ │ │ │ │ @ ImplicitNode (location: (106,6)-(106,7)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── value: │ │ │ │ │ @ LocalVariableTargetNode (location: (106,6)-(106,7)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :b │ │ │ │ │ └── depth: 0 │ │ │ │ └── operator_loc: ∅ @@ -948,21 +1078,24 @@ │ │ ├── statements: ∅ │ │ ├── in_loc: (106,0)-(106,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (105,0)-(105,4) = "case" │ └── end_keyword_loc: (107,0)-(107,3) = "end" └── @ CaseMatchNode (location: (109,0)-(111,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (109,5)-(109,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (109,5)-(109,6) = ":" │ ├── value_loc: (109,6)-(109,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (110,0)-(110,5)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ HashPatternNode (location: (110,3)-(110,5)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── elements: (length: 0) │ │ ├── rest: ∅ @@ -971,6 +1104,6 @@ │ ├── statements: ∅ │ ├── in_loc: (110,0)-(110,2) = "in" │ └── then_loc: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (109,0)-(109,4) = "case" └── end_keyword_loc: (111,0)-(111,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_31.txt b/test/prism/snapshots/seattlerb/case_in_31.txt index fdf5ce2a29e..4abddbcdced 100644 --- a/test/prism/snapshots/seattlerb/case_in_31.txt +++ b/test/prism/snapshots/seattlerb/case_in_31.txt @@ -1,33 +1,40 @@ @ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ ├── locals: [:c] └── statements: @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(4,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(3,4)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (2,3)-(2,11)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ SymbolNode (location: (2,4)-(2,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (2,4)-(2,5) = ":" │ │ │ ├── value_loc: (2,5)-(2,6) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" │ │ ├── rest: │ │ │ @ SplatNode (location: (2,8)-(2,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (2,8)-(2,9) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (2,9)-(2,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ └── depth: 0 │ │ ├── posts: (length: 0) @@ -35,15 +42,16 @@ │ │ └── closing_loc: (2,10)-(2,11) = "]" │ ├── statements: │ │ @ StatementsNode (location: (3,2)-(3,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "d" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "d" │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (4,0)-(4,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_37.txt b/test/prism/snapshots/seattlerb/case_in_37.txt index 1a1d887b4fd..5ef6d916af5 100644 --- a/test/prism/snapshots/seattlerb/case_in_37.txt +++ b/test/prism/snapshots/seattlerb/case_in_37.txt @@ -1,38 +1,47 @@ @ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(4,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(3,4)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ HashPatternNode (location: (2,3)-(2,19)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── elements: (length: 1) │ │ │ └── @ AssocNode (location: (2,5)-(2,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,5)-(2,7)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,5)-(2,6) = "b" │ │ │ │ ├── closing_loc: (2,6)-(2,7) = ":" │ │ │ │ └── unescaped: "b" │ │ │ ├── value: │ │ │ │ @ ArrayPatternNode (location: (2,8)-(2,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ └── @ ConstantReadNode (location: (2,9)-(2,13)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :Hash │ │ │ │ ├── rest: │ │ │ │ │ @ SplatNode (location: (2,15)-(2,16)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── operator_loc: (2,15)-(2,16) = "*" │ │ │ │ │ └── expression: ∅ │ │ │ │ ├── posts: (length: 0) @@ -44,15 +53,16 @@ │ │ └── closing_loc: (2,18)-(2,19) = "}" │ ├── statements: │ │ @ StatementsNode (location: (3,2)-(3,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "c" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "c" │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (4,0)-(4,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_42.txt b/test/prism/snapshots/seattlerb/case_in_42.txt index f985d6bc8db..9c6d21c68ef 100644 --- a/test/prism/snapshots/seattlerb/case_in_42.txt +++ b/test/prism/snapshots/seattlerb/case_in_42.txt @@ -1,33 +1,40 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [:_] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(3,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(2,18)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (2,3)-(2,9)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ SymbolNode (location: (2,3)-(2,5)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (2,3)-(2,4) = ":" │ │ │ ├── value_loc: (2,4)-(2,5) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" │ │ ├── rest: │ │ │ @ SplatNode (location: (2,7)-(2,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (2,7)-(2,8) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (2,8)-(2,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :_ │ │ │ └── depth: 0 │ │ ├── posts: (length: 0) @@ -35,10 +42,12 @@ │ │ └── closing_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (2,15)-(2,18)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NilNode (location: (2,15)-(2,18)) + │ │ └── flags: newline, static_literal │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: (2,10)-(2,14) = "then" - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (3,0)-(3,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_42_2.txt b/test/prism/snapshots/seattlerb/case_in_42_2.txt index c399ba1bfa4..e16df21fa27 100644 --- a/test/prism/snapshots/seattlerb/case_in_42_2.txt +++ b/test/prism/snapshots/seattlerb/case_in_42_2.txt @@ -1,29 +1,37 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [:list] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(3,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(2,20)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (2,3)-(2,11)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (2,3)-(2,4)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── requireds: (length: 0) │ │ ├── rest: │ │ │ @ SplatNode (location: (2,5)-(2,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (2,5)-(2,6) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (2,6)-(2,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :list │ │ │ └── depth: 0 │ │ ├── posts: (length: 0) @@ -31,10 +39,12 @@ │ │ └── closing_loc: (2,10)-(2,11) = ")" │ ├── statements: │ │ @ StatementsNode (location: (2,17)-(2,20)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NilNode (location: (2,17)-(2,20)) + │ │ └── flags: newline, static_literal │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: (2,12)-(2,16) = "then" - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (3,0)-(3,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_47.txt b/test/prism/snapshots/seattlerb/case_in_47.txt index 99baebce05a..ee11204f615 100644 --- a/test/prism/snapshots/seattlerb/case_in_47.txt +++ b/test/prism/snapshots/seattlerb/case_in_47.txt @@ -1,35 +1,41 @@ @ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(4,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(3,4)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (2,3)-(2,14)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 0) │ │ ├── rest: │ │ │ @ SplatNode (location: (2,4)-(2,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (2,4)-(2,5) = "*" │ │ │ └── expression: ∅ │ │ ├── posts: (length: 2) │ │ │ ├── @ SymbolNode (location: (2,7)-(2,9)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (2,7)-(2,8) = ":" │ │ │ │ ├── value_loc: (2,8)-(2,9) = "b" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "b" │ │ │ └── @ SymbolNode (location: (2,11)-(2,13)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (2,11)-(2,12) = ":" │ │ │ ├── value_loc: (2,12)-(2,13) = "c" │ │ │ ├── closing_loc: ∅ @@ -38,15 +44,16 @@ │ │ └── closing_loc: (2,13)-(2,14) = "]" │ ├── statements: │ │ @ StatementsNode (location: (3,2)-(3,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "d" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "d" │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (4,0)-(4,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_67.txt b/test/prism/snapshots/seattlerb/case_in_67.txt index 4bab417d578..103277a39d9 100644 --- a/test/prism/snapshots/seattlerb/case_in_67.txt +++ b/test/prism/snapshots/seattlerb/case_in_67.txt @@ -1,33 +1,39 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(3,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(2,15)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ RangeNode (location: (2,3)-(2,6)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (2,3)-(2,4)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (2,4)-(2,6) = ".." │ ├── statements: │ │ @ StatementsNode (location: (2,12)-(2,15)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NilNode (location: (2,12)-(2,15)) + │ │ └── flags: newline, static_literal │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: (2,7)-(2,11) = "then" - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (3,0)-(3,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_86.txt b/test/prism/snapshots/seattlerb/case_in_86.txt index 082aa74ecac..b163ae64e4f 100644 --- a/test/prism/snapshots/seattlerb/case_in_86.txt +++ b/test/prism/snapshots/seattlerb/case_in_86.txt @@ -1,21 +1,24 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(3,3)) + ├── flags: newline ├── predicate: │ @ ArrayNode (location: (1,5)-(1,13)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (1,6)-(1,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,6)-(1,7) = ":" │ │ │ ├── value_loc: (1,7)-(1,8) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (1,10)-(1,12)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,10)-(1,11) = ":" │ │ ├── value_loc: (1,11)-(1,12) = "b" │ │ ├── closing_loc: ∅ @@ -24,17 +27,21 @@ │ └── closing_loc: (1,12)-(1,13) = "]" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(2,25)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (2,3)-(2,16)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ ConstantPathNode (location: (2,3)-(2,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── parent: ∅ │ │ │ ├── name: :NilClass │ │ │ ├── delimiter_loc: (2,3)-(2,5) = "::" │ │ │ └── name_loc: (2,5)-(2,13) = "NilClass" │ │ ├── rest: │ │ │ @ SplatNode (location: (2,15)-(2,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (2,15)-(2,16) = "*" │ │ │ └── expression: ∅ │ │ ├── posts: (length: 0) @@ -42,10 +49,12 @@ │ │ └── closing_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (2,22)-(2,25)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NilNode (location: (2,22)-(2,25)) + │ │ └── flags: newline, static_literal │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: (2,17)-(2,21) = "then" - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (3,0)-(3,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_86_2.txt b/test/prism/snapshots/seattlerb/case_in_86_2.txt index 346264f9071..bf6b2ff53da 100644 --- a/test/prism/snapshots/seattlerb/case_in_86_2.txt +++ b/test/prism/snapshots/seattlerb/case_in_86_2.txt @@ -1,21 +1,24 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(3,3)) + ├── flags: newline ├── predicate: │ @ ArrayNode (location: (1,5)-(1,13)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (1,6)-(1,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,6)-(1,7) = ":" │ │ │ ├── value_loc: (1,7)-(1,8) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (1,10)-(1,12)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,10)-(1,11) = ":" │ │ ├── value_loc: (1,11)-(1,12) = "b" │ │ ├── closing_loc: ∅ @@ -24,16 +27,20 @@ │ └── closing_loc: (1,12)-(1,13) = "]" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(2,25)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (2,3)-(2,16)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 0) │ │ ├── rest: │ │ │ @ SplatNode (location: (2,3)-(2,4)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (2,3)-(2,4) = "*" │ │ │ └── expression: ∅ │ │ ├── posts: (length: 1) │ │ │ └── @ ConstantPathNode (location: (2,6)-(2,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── parent: ∅ │ │ │ ├── name: :NilClass │ │ │ ├── delimiter_loc: (2,6)-(2,8) = "::" @@ -42,10 +49,12 @@ │ │ └── closing_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (2,22)-(2,25)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NilNode (location: (2,22)-(2,25)) + │ │ └── flags: newline, static_literal │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: (2,17)-(2,21) = "then" - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (3,0)-(3,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_array_pat_const.txt b/test/prism/snapshots/seattlerb/case_in_array_pat_const.txt index f361e8d4589..c0aae6a723b 100644 --- a/test/prism/snapshots/seattlerb/case_in_array_pat_const.txt +++ b/test/prism/snapshots/seattlerb/case_in_array_pat_const.txt @@ -1,25 +1,32 @@ @ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ ├── locals: [:c] └── statements: @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(4,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(3,4)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (2,3)-(2,7)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (2,3)-(2,4)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :B │ │ ├── requireds: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (2,5)-(2,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ └── depth: 0 │ │ ├── rest: ∅ @@ -28,15 +35,16 @@ │ │ └── closing_loc: (2,6)-(2,7) = "]" │ ├── statements: │ │ @ StatementsNode (location: (3,2)-(3,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "d" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "d" │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (4,0)-(4,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_array_pat_const2.txt b/test/prism/snapshots/seattlerb/case_in_array_pat_const2.txt index d6fb80ef908..7739dde6287 100644 --- a/test/prism/snapshots/seattlerb/case_in_array_pat_const2.txt +++ b/test/prism/snapshots/seattlerb/case_in_array_pat_const2.txt @@ -1,30 +1,38 @@ @ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ ├── locals: [:d] └── statements: @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(4,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(3,4)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (2,3)-(2,10)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantPathNode (location: (2,3)-(2,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── parent: │ │ │ │ @ ConstantReadNode (location: (2,3)-(2,4)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :B │ │ │ ├── name: :C │ │ │ ├── delimiter_loc: (2,4)-(2,6) = "::" │ │ │ └── name_loc: (2,6)-(2,7) = "C" │ │ ├── requireds: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (2,8)-(2,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :d │ │ │ └── depth: 0 │ │ ├── rest: ∅ @@ -33,15 +41,16 @@ │ │ └── closing_loc: (2,9)-(2,10) = "]" │ ├── statements: │ │ @ StatementsNode (location: (3,2)-(3,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "e" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "e" │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (4,0)-(4,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_array_pat_paren_assign.txt b/test/prism/snapshots/seattlerb/case_in_array_pat_paren_assign.txt index 8d185b250a7..e34cac73c4e 100644 --- a/test/prism/snapshots/seattlerb/case_in_array_pat_paren_assign.txt +++ b/test/prism/snapshots/seattlerb/case_in_array_pat_paren_assign.txt @@ -1,30 +1,39 @@ @ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ ├── locals: [:d] └── statements: @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(4,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(3,4)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ ArrayPatternNode (location: (2,3)-(2,12)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (2,3)-(2,4)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :B │ │ ├── requireds: (length: 1) │ │ │ └── @ CapturePatternNode (location: (2,5)-(2,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── value: │ │ │ │ @ ConstantReadNode (location: (2,5)-(2,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :C │ │ │ ├── target: │ │ │ │ @ LocalVariableTargetNode (location: (2,10)-(2,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :d │ │ │ │ └── depth: 0 │ │ │ └── operator_loc: (2,7)-(2,9) = "=>" @@ -34,15 +43,16 @@ │ │ └── closing_loc: (2,11)-(2,12) = ")" │ ├── statements: │ │ @ StatementsNode (location: (3,2)-(3,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "d" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "d" │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (4,0)-(4,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_const.txt b/test/prism/snapshots/seattlerb/case_in_const.txt index c4b838aa1d5..49097d26dfd 100644 --- a/test/prism/snapshots/seattlerb/case_in_const.txt +++ b/test/prism/snapshots/seattlerb/case_in_const.txt @@ -1,28 +1,35 @@ @ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(4,3)) + ├── flags: newline ├── predicate: │ @ ConstantReadNode (location: (1,5)-(1,10)) + │ ├── flags: ∅ │ └── name: :Array ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(3,4)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ ConstantReadNode (location: (2,3)-(2,8)) + │ │ ├── flags: ∅ │ │ └── name: :Class │ ├── statements: │ │ @ StatementsNode (location: (3,2)-(3,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "b" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b" │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (4,0)-(4,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_else.txt b/test/prism/snapshots/seattlerb/case_in_else.txt index 5eae7fc1ea2..e0cdf5125c0 100644 --- a/test/prism/snapshots/seattlerb/case_in_else.txt +++ b/test/prism/snapshots/seattlerb/case_in_else.txt @@ -1,36 +1,45 @@ @ ProgramNode (location: (1,0)-(6,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(6,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(6,3)) + ├── flags: newline ├── predicate: │ @ ConstantReadNode (location: (1,5)-(1,10)) + │ ├── flags: ∅ │ └── name: :Array ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(3,4)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ ConstantReadNode (location: (2,3)-(2,8)) + │ │ ├── flags: ∅ │ │ └── name: :Class │ ├── statements: │ │ @ StatementsNode (location: (3,2)-(3,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "b" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b" │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: ∅ - ├── consequent: + ├── else_clause: │ @ ElseNode (location: (4,0)-(6,3)) + │ ├── flags: ∅ │ ├── else_keyword_loc: (4,0)-(4,4) = "else" │ ├── statements: │ │ @ StatementsNode (location: (5,2)-(5,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (5,2)-(5,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (5,2)-(5,3) = ":" │ │ ├── value_loc: (5,3)-(5,4) = "c" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_find.txt b/test/prism/snapshots/seattlerb/case_in_find.txt index f84c4c30d0d..c6337d7c850 100644 --- a/test/prism/snapshots/seattlerb/case_in_find.txt +++ b/test/prism/snapshots/seattlerb/case_in_find.txt @@ -1,40 +1,49 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [:a, :b] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(3,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,2)-(2,15)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ FindPatternNode (location: (2,5)-(2,15)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── left: │ │ │ @ SplatNode (location: (2,5)-(2,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (2,5)-(2,6) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (2,6)-(2,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── requireds: (length: 1) │ │ │ └── @ SymbolNode (location: (2,9)-(2,11)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (2,9)-(2,10) = ":" │ │ │ ├── value_loc: (2,10)-(2,11) = "+" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "+" │ │ ├── right: │ │ │ @ SplatNode (location: (2,13)-(2,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (2,13)-(2,14) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (2,14)-(2,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ └── depth: 0 │ │ ├── opening_loc: ∅ @@ -42,6 +51,6 @@ │ ├── statements: ∅ │ ├── in_loc: (2,2)-(2,4) = "in" │ └── then_loc: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (3,0)-(3,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_find_array.txt b/test/prism/snapshots/seattlerb/case_in_find_array.txt index a757f803460..986925904f4 100644 --- a/test/prism/snapshots/seattlerb/case_in_find_array.txt +++ b/test/prism/snapshots/seattlerb/case_in_find_array.txt @@ -1,37 +1,45 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [:c] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(3,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(2,16)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ FindPatternNode (location: (2,3)-(2,16)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── left: │ │ │ @ SplatNode (location: (2,4)-(2,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (2,4)-(2,5) = "*" │ │ │ └── expression: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ SymbolNode (location: (2,7)-(2,9)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (2,7)-(2,8) = ":" │ │ │ │ ├── value_loc: (2,8)-(2,9) = "b" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "b" │ │ │ └── @ LocalVariableTargetNode (location: (2,11)-(2,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ └── depth: 0 │ │ ├── right: │ │ │ @ SplatNode (location: (2,14)-(2,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (2,14)-(2,15) = "*" │ │ │ └── expression: ∅ │ │ ├── opening_loc: (2,3)-(2,4) = "[" @@ -39,6 +47,6 @@ │ ├── statements: ∅ │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (3,0)-(3,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_hash_pat.txt b/test/prism/snapshots/seattlerb/case_in_hash_pat.txt index e813efa9ee5..e3f62d026e7 100644 --- a/test/prism/snapshots/seattlerb/case_in_hash_pat.txt +++ b/test/prism/snapshots/seattlerb/case_in_hash_pat.txt @@ -1,26 +1,32 @@ @ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(4,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(3,4)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ HashPatternNode (location: (2,3)-(2,21)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── elements: (length: 2) │ │ │ ├── @ AssocNode (location: (2,5)-(2,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (2,5)-(2,7)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (2,5)-(2,6) = "b" │ │ │ │ │ ├── closing_loc: (2,6)-(2,7) = ":" @@ -34,9 +40,10 @@ │ │ │ │ │ └── unescaped: "c" │ │ │ │ └── operator_loc: ∅ │ │ │ └── @ AssocNode (location: (2,13)-(2,19)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,13)-(2,15)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,13)-(2,14) = "d" │ │ │ │ ├── closing_loc: (2,14)-(2,15) = ":" @@ -54,15 +61,16 @@ │ │ └── closing_loc: (2,20)-(2,21) = "}" │ ├── statements: │ │ @ StatementsNode (location: (3,2)-(3,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "f" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "f" │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: (2,22)-(2,26) = "then" - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (4,0)-(4,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_hash_pat_assign.txt b/test/prism/snapshots/seattlerb/case_in_hash_pat_assign.txt index 790d9d63ffb..483c9326809 100644 --- a/test/prism/snapshots/seattlerb/case_in_hash_pat_assign.txt +++ b/test/prism/snapshots/seattlerb/case_in_hash_pat_assign.txt @@ -1,45 +1,55 @@ @ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ ├── locals: [:x, :f] └── statements: @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(4,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(3,4)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ HashPatternNode (location: (2,3)-(2,34)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── elements: (length: 3) │ │ │ ├── @ AssocNode (location: (2,5)-(2,20)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (2,5)-(2,7)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (2,5)-(2,6) = "b" │ │ │ │ │ ├── closing_loc: (2,6)-(2,7) = ":" │ │ │ │ │ └── unescaped: "b" │ │ │ │ ├── value: │ │ │ │ │ @ CapturePatternNode (location: (2,8)-(2,20)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── value: │ │ │ │ │ │ @ ConstantReadNode (location: (2,8)-(2,15)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :Integer │ │ │ │ │ ├── target: │ │ │ │ │ │ @ LocalVariableTargetNode (location: (2,19)-(2,20)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── name: :x │ │ │ │ │ │ └── depth: 0 │ │ │ │ │ └── operator_loc: (2,16)-(2,18) = "=>" │ │ │ │ └── operator_loc: ∅ │ │ │ ├── @ AssocNode (location: (2,22)-(2,28)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (2,22)-(2,24)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (2,22)-(2,23) = "d" │ │ │ │ │ ├── closing_loc: (2,23)-(2,24) = ":" @@ -53,17 +63,20 @@ │ │ │ │ │ └── unescaped: "e" │ │ │ │ └── operator_loc: ∅ │ │ │ └── @ AssocNode (location: (2,30)-(2,32)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,30)-(2,32)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,30)-(2,31) = "f" │ │ │ │ ├── closing_loc: (2,31)-(2,32) = ":" │ │ │ │ └── unescaped: "f" │ │ │ ├── value: │ │ │ │ @ ImplicitNode (location: (2,30)-(2,31)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── value: │ │ │ │ @ LocalVariableTargetNode (location: (2,30)-(2,31)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :f │ │ │ │ └── depth: 0 │ │ │ └── operator_loc: ∅ @@ -72,15 +85,16 @@ │ │ └── closing_loc: (2,33)-(2,34) = "}" │ ├── statements: │ │ @ StatementsNode (location: (3,2)-(3,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "g" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "g" │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: (2,35)-(2,39) = "then" - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (4,0)-(4,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_assign.txt b/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_assign.txt index 4c8cfd0e544..b6e809326a1 100644 --- a/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_assign.txt +++ b/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_assign.txt @@ -1,35 +1,42 @@ @ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(4,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(3,4)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ HashPatternNode (location: (2,3)-(2,11)) + │ │ ├── flags: ∅ │ │ ├── constant: │ │ │ @ ConstantReadNode (location: (2,3)-(2,4)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :B │ │ ├── elements: (length: 1) │ │ │ └── @ AssocNode (location: (2,5)-(2,10)) + │ │ │ ├── flags: static_literal │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,5)-(2,7)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,5)-(2,6) = "a" │ │ │ │ ├── closing_loc: (2,6)-(2,7) = ":" │ │ │ │ └── unescaped: "a" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (2,8)-(2,10)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 42 │ │ │ └── operator_loc: ∅ │ │ ├── rest: ∅ @@ -37,15 +44,16 @@ │ │ └── closing_loc: (2,10)-(2,11) = ")" │ ├── statements: │ │ @ StatementsNode (location: (3,2)-(3,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "d" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "d" │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (4,0)-(4,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_true.txt b/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_true.txt index 8ff95a161f3..a5440210308 100644 --- a/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_true.txt +++ b/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_true.txt @@ -1,47 +1,55 @@ @ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(4,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(3,4)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ HashPatternNode (location: (2,3)-(2,10)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── elements: (length: 1) │ │ │ └── @ AssocNode (location: (2,3)-(2,10)) + │ │ │ ├── flags: static_literal │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,3)-(2,5)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,3)-(2,4) = "b" │ │ │ │ ├── closing_loc: (2,4)-(2,5) = ":" │ │ │ │ └── unescaped: "b" │ │ │ ├── value: │ │ │ │ @ TrueNode (location: (2,6)-(2,10)) + │ │ │ │ └── flags: static_literal │ │ │ └── operator_loc: ∅ │ │ ├── rest: ∅ │ │ ├── opening_loc: ∅ │ │ └── closing_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (3,2)-(3,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "c" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "c" │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: (2,11)-(2,15) = "then" - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (4,0)-(4,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_hash_pat_rest.txt b/test/prism/snapshots/seattlerb/case_in_hash_pat_rest.txt index b93b889ec5f..71f7e126bc1 100644 --- a/test/prism/snapshots/seattlerb/case_in_hash_pat_rest.txt +++ b/test/prism/snapshots/seattlerb/case_in_hash_pat_rest.txt @@ -1,39 +1,48 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [:c, :rest] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(3,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(2,23)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ HashPatternNode (location: (2,3)-(2,15)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── elements: (length: 1) │ │ │ └── @ AssocNode (location: (2,3)-(2,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,3)-(2,5)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,3)-(2,4) = "b" │ │ │ │ ├── closing_loc: (2,4)-(2,5) = ":" │ │ │ │ └── unescaped: "b" │ │ │ ├── value: │ │ │ │ @ LocalVariableTargetNode (location: (2,6)-(2,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :c │ │ │ │ └── depth: 0 │ │ │ └── operator_loc: ∅ │ │ ├── rest: │ │ │ @ AssocSplatNode (location: (2,9)-(2,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── value: │ │ │ │ @ LocalVariableTargetNode (location: (2,11)-(2,15)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :rest │ │ │ │ └── depth: 0 │ │ │ └── operator_loc: (2,9)-(2,11) = "**" @@ -41,15 +50,16 @@ │ │ └── closing_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (2,21)-(2,23)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (2,21)-(2,23)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (2,21)-(2,22) = ":" │ │ ├── value_loc: (2,22)-(2,23) = "d" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "d" │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: (2,16)-(2,20) = "then" - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (3,0)-(3,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_hash_pat_rest_solo.txt b/test/prism/snapshots/seattlerb/case_in_hash_pat_rest_solo.txt index 956e93faa02..01b324e086c 100644 --- a/test/prism/snapshots/seattlerb/case_in_hash_pat_rest_solo.txt +++ b/test/prism/snapshots/seattlerb/case_in_hash_pat_rest_solo.txt @@ -1,26 +1,33 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [:rest] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(3,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(2,17)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ HashPatternNode (location: (2,3)-(2,9)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── elements: (length: 0) │ │ ├── rest: │ │ │ @ AssocSplatNode (location: (2,3)-(2,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── value: │ │ │ │ @ LocalVariableTargetNode (location: (2,5)-(2,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :rest │ │ │ │ └── depth: 0 │ │ │ └── operator_loc: (2,3)-(2,5) = "**" @@ -28,15 +35,16 @@ │ │ └── closing_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (2,15)-(2,17)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (2,15)-(2,17)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (2,15)-(2,16) = ":" │ │ ├── value_loc: (2,16)-(2,17) = "d" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "d" │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: (2,10)-(2,14) = "then" - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (3,0)-(3,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_if_unless_post_mod.txt b/test/prism/snapshots/seattlerb/case_in_if_unless_post_mod.txt index a21d3e15dd4..3da03ffbc3f 100644 --- a/test/prism/snapshots/seattlerb/case_in_if_unless_post_mod.txt +++ b/test/prism/snapshots/seattlerb/case_in_if_unless_post_mod.txt @@ -1,36 +1,45 @@ @ ProgramNode (location: (1,0)-(6,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(6,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(6,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 2) │ ├── @ InNode (location: (2,0)-(3,4)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ IfNode (location: (2,3)-(2,12)) + │ │ │ ├── flags: newline │ │ │ ├── if_keyword_loc: (2,5)-(2,7) = "if" │ │ │ ├── predicate: │ │ │ │ @ TrueNode (location: (2,8)-(2,12)) + │ │ │ │ └── flags: static_literal │ │ │ ├── then_keyword_loc: ∅ │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (2,3)-(2,4)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ ConstantReadNode (location: (2,3)-(2,4)) + │ │ │ │ ├── flags: newline │ │ │ │ └── name: :A - │ │ │ ├── consequent: ∅ + │ │ │ ├── subsequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (3,2)-(3,4)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ │ ├── value_loc: (3,3)-(3,4) = "C" │ │ │ ├── closing_loc: ∅ @@ -38,30 +47,36 @@ │ │ ├── in_loc: (2,0)-(2,2) = "in" │ │ └── then_loc: ∅ │ └── @ InNode (location: (4,0)-(5,4)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ UnlessNode (location: (4,3)-(4,17)) + │ │ ├── flags: newline │ │ ├── keyword_loc: (4,5)-(4,11) = "unless" │ │ ├── predicate: │ │ │ @ FalseNode (location: (4,12)-(4,17)) + │ │ │ └── flags: static_literal │ │ ├── then_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (4,3)-(4,4)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ ConstantReadNode (location: (4,3)-(4,4)) + │ │ │ ├── flags: newline │ │ │ └── name: :D - │ │ ├── consequent: ∅ + │ │ ├── else_clause: ∅ │ │ └── end_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (5,2)-(5,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (5,2)-(5,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (5,2)-(5,3) = ":" │ │ ├── value_loc: (5,3)-(5,4) = "E" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "E" │ ├── in_loc: (4,0)-(4,2) = "in" │ └── then_loc: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (6,0)-(6,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_multiple.txt b/test/prism/snapshots/seattlerb/case_in_multiple.txt index eba0084f969..173136fc6fb 100644 --- a/test/prism/snapshots/seattlerb/case_in_multiple.txt +++ b/test/prism/snapshots/seattlerb/case_in_multiple.txt @@ -1,31 +1,38 @@ @ ProgramNode (location: (1,0)-(6,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(6,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(6,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 2) │ ├── @ InNode (location: (2,0)-(3,4)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ConstantPathNode (location: (2,3)-(2,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── parent: │ │ │ │ @ ConstantReadNode (location: (2,3)-(2,4)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :A │ │ │ ├── name: :B │ │ │ ├── delimiter_loc: (2,4)-(2,6) = "::" │ │ │ └── name_loc: (2,6)-(2,7) = "B" │ │ ├── statements: │ │ │ @ StatementsNode (location: (3,2)-(3,4)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ │ ├── value_loc: (3,3)-(3,4) = "C" │ │ │ ├── closing_loc: ∅ @@ -33,25 +40,29 @@ │ │ ├── in_loc: (2,0)-(2,2) = "in" │ │ └── then_loc: ∅ │ └── @ InNode (location: (4,0)-(5,4)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ ConstantPathNode (location: (4,3)-(4,7)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantReadNode (location: (4,3)-(4,4)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :D │ │ ├── name: :E │ │ ├── delimiter_loc: (4,4)-(4,6) = "::" │ │ └── name_loc: (4,6)-(4,7) = "E" │ ├── statements: │ │ @ StatementsNode (location: (5,2)-(5,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (5,2)-(5,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (5,2)-(5,3) = ":" │ │ ├── value_loc: (5,3)-(5,4) = "F" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "F" │ ├── in_loc: (4,0)-(4,2) = "in" │ └── then_loc: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (6,0)-(6,3) = "end" diff --git a/test/prism/snapshots/seattlerb/case_in_or.txt b/test/prism/snapshots/seattlerb/case_in_or.txt index 7ac66176082..7bcf50293d1 100644 --- a/test/prism/snapshots/seattlerb/case_in_or.txt +++ b/test/prism/snapshots/seattlerb/case_in_or.txt @@ -1,38 +1,46 @@ @ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ └── body: (length: 1) └── @ CaseMatchNode (location: (1,0)-(4,3)) + ├── flags: newline ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ │ └── unescaped: "a" ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(3,4)) + │ ├── flags: ∅ │ ├── pattern: │ │ @ AlternationPatternNode (location: (2,3)-(2,8)) + │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ ConstantReadNode (location: (2,3)-(2,4)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :B │ │ ├── right: │ │ │ @ ConstantReadNode (location: (2,7)-(2,8)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :C │ │ └── operator_loc: (2,5)-(2,6) = "|" │ ├── statements: │ │ @ StatementsNode (location: (3,2)-(3,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "d" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "d" │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (4,0)-(4,3) = "end" diff --git a/test/prism/snapshots/seattlerb/class_comments.txt b/test/prism/snapshots/seattlerb/class_comments.txt index 5ac05b6be68..75350722a1a 100644 --- a/test/prism/snapshots/seattlerb/class_comments.txt +++ b/test/prism/snapshots/seattlerb/class_comments.txt @@ -1,20 +1,26 @@ @ ProgramNode (location: (4,0)-(9,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (4,0)-(9,3)) + ├── flags: ∅ └── body: (length: 1) └── @ ClassNode (location: (4,0)-(9,3)) + ├── flags: newline ├── locals: [] ├── class_keyword_loc: (4,0)-(4,5) = "class" ├── constant_path: │ @ ConstantReadNode (location: (4,6)-(4,7)) + │ ├── flags: ∅ │ └── name: :X ├── inheritance_operator_loc: ∅ ├── superclass: ∅ ├── body: │ @ StatementsNode (location: (6,2)-(8,5)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ DefNode (location: (6,2)-(8,5)) + │ ├── flags: newline │ ├── name: :blah │ ├── name_loc: (6,6)-(6,10) = "blah" │ ├── receiver: ∅ diff --git a/test/prism/snapshots/seattlerb/cond_unary_minus.txt b/test/prism/snapshots/seattlerb/cond_unary_minus.txt index b6e12dfb15c..69a998475e5 100644 --- a/test/prism/snapshots/seattlerb/cond_unary_minus.txt +++ b/test/prism/snapshots/seattlerb/cond_unary_minus.txt @@ -1,15 +1,18 @@ @ ProgramNode (location: (1,0)-(1,10)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,10)) + ├── flags: ∅ └── body: (length: 1) └── @ IfNode (location: (1,0)-(1,10)) + ├── flags: newline ├── if_keyword_loc: (1,0)-(1,2) = "if" ├── predicate: │ @ IntegerNode (location: (1,3)-(1,5)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: -1 ├── then_keyword_loc: ∅ ├── statements: ∅ - ├── consequent: ∅ + ├── subsequent: ∅ └── end_keyword_loc: (1,7)-(1,10) = "end" diff --git a/test/prism/snapshots/seattlerb/const_2_op_asgn_or2.txt b/test/prism/snapshots/seattlerb/const_2_op_asgn_or2.txt index e09eed7d2ff..25d77dac2d5 100644 --- a/test/prism/snapshots/seattlerb/const_2_op_asgn_or2.txt +++ b/test/prism/snapshots/seattlerb/const_2_op_asgn_or2.txt @@ -1,13 +1,18 @@ @ ProgramNode (location: (1,0)-(1,12)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,12)) + ├── flags: ∅ └── body: (length: 1) └── @ ConstantPathOrWriteNode (location: (1,0)-(1,12)) + ├── flags: newline ├── target: │ @ ConstantPathNode (location: (1,0)-(1,6)) + │ ├── flags: ∅ │ ├── parent: │ │ @ ConstantPathNode (location: (1,0)-(1,3)) + │ │ ├── flags: ∅ │ │ ├── parent: ∅ │ │ ├── name: :X │ │ ├── delimiter_loc: (1,0)-(1,2) = "::" @@ -18,5 +23,5 @@ ├── operator_loc: (1,7)-(1,10) = "||=" └── value: @ IntegerNode (location: (1,11)-(1,12)) - ├── flags: decimal + ├── flags: static_literal, decimal └── value: 1 diff --git a/test/prism/snapshots/seattlerb/const_3_op_asgn_or.txt b/test/prism/snapshots/seattlerb/const_3_op_asgn_or.txt index 398af888a89..dc098bcf23c 100644 --- a/test/prism/snapshots/seattlerb/const_3_op_asgn_or.txt +++ b/test/prism/snapshots/seattlerb/const_3_op_asgn_or.txt @@ -1,11 +1,15 @@ @ ProgramNode (location: (1,0)-(1,9)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,9)) + ├── flags: ∅ └── body: (length: 1) └── @ ConstantPathOrWriteNode (location: (1,0)-(1,9)) + ├── flags: newline ├── target: │ @ ConstantPathNode (location: (1,0)-(1,3)) + │ ├── flags: ∅ │ ├── parent: ∅ │ ├── name: :X │ ├── delimiter_loc: (1,0)-(1,2) = "::" @@ -13,5 +17,5 @@ ├── operator_loc: (1,4)-(1,7) = "||=" └── value: @ IntegerNode (location: (1,8)-(1,9)) - ├── flags: decimal + ├── flags: static_literal, decimal └── value: 1 diff --git a/test/prism/snapshots/seattlerb/const_op_asgn_and1.txt b/test/prism/snapshots/seattlerb/const_op_asgn_and1.txt index b5acfa1d8bc..63b8bc190b1 100644 --- a/test/prism/snapshots/seattlerb/const_op_asgn_and1.txt +++ b/test/prism/snapshots/seattlerb/const_op_asgn_and1.txt @@ -1,18 +1,22 @@ @ ProgramNode (location: (1,0)-(1,8)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,8)) + ├── flags: ∅ └── body: (length: 1) └── @ ConstantPathOperatorWriteNode (location: (1,0)-(1,8)) + ├── flags: newline ├── target: │ @ ConstantPathNode (location: (1,0)-(1,3)) + │ ├── flags: ∅ │ ├── parent: ∅ │ ├── name: :X │ ├── delimiter_loc: (1,0)-(1,2) = "::" │ └── name_loc: (1,2)-(1,3) = "X" - ├── operator_loc: (1,4)-(1,6) = "&=" + ├── binary_operator_loc: (1,4)-(1,6) = "&=" ├── value: │ @ IntegerNode (location: (1,7)-(1,8)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 - └── operator: :& + └── binary_operator: :& diff --git a/test/prism/snapshots/seattlerb/const_op_asgn_and2.txt b/test/prism/snapshots/seattlerb/const_op_asgn_and2.txt index 146455d3271..c1ac2bcf526 100644 --- a/test/prism/snapshots/seattlerb/const_op_asgn_and2.txt +++ b/test/prism/snapshots/seattlerb/const_op_asgn_and2.txt @@ -1,11 +1,15 @@ @ ProgramNode (location: (1,0)-(1,9)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,9)) + ├── flags: ∅ └── body: (length: 1) └── @ ConstantPathAndWriteNode (location: (1,0)-(1,9)) + ├── flags: newline ├── target: │ @ ConstantPathNode (location: (1,0)-(1,3)) + │ ├── flags: ∅ │ ├── parent: ∅ │ ├── name: :X │ ├── delimiter_loc: (1,0)-(1,2) = "::" @@ -13,5 +17,5 @@ ├── operator_loc: (1,4)-(1,7) = "&&=" └── value: @ IntegerNode (location: (1,8)-(1,9)) - ├── flags: decimal + ├── flags: static_literal, decimal └── value: 1 diff --git a/test/prism/snapshots/seattlerb/const_op_asgn_or.txt b/test/prism/snapshots/seattlerb/const_op_asgn_or.txt index 5e9dd396043..0a53593d123 100644 --- a/test/prism/snapshots/seattlerb/const_op_asgn_or.txt +++ b/test/prism/snapshots/seattlerb/const_op_asgn_or.txt @@ -1,13 +1,18 @@ @ ProgramNode (location: (1,0)-(1,10)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,10)) + ├── flags: ∅ └── body: (length: 1) └── @ ConstantPathOrWriteNode (location: (1,0)-(1,10)) + ├── flags: newline ├── target: │ @ ConstantPathNode (location: (1,0)-(1,4)) + │ ├── flags: ∅ │ ├── parent: │ │ @ ConstantReadNode (location: (1,0)-(1,1)) + │ │ ├── flags: ∅ │ │ └── name: :X │ ├── name: :Y │ ├── delimiter_loc: (1,1)-(1,3) = "::" @@ -15,5 +20,5 @@ ├── operator_loc: (1,5)-(1,8) = "||=" └── value: @ IntegerNode (location: (1,9)-(1,10)) - ├── flags: decimal + ├── flags: static_literal, decimal └── value: 1 diff --git a/test/prism/snapshots/seattlerb/dasgn_icky2.txt b/test/prism/snapshots/seattlerb/dasgn_icky2.txt deleted file mode 100644 index e118362f876..00000000000 --- a/test/prism/snapshots/seattlerb/dasgn_icky2.txt +++ /dev/null @@ -1,61 +0,0 @@ -@ ProgramNode (location: (1,0)-(8,3)) -├── locals: [] -└── statements: - @ StatementsNode (location: (1,0)-(8,3)) - └── body: (length: 1) - └── @ CallNode (location: (1,0)-(8,3)) - ├── flags: ignore_visibility - ├── receiver: ∅ - ├── call_operator_loc: ∅ - ├── name: :a - ├── message_loc: (1,0)-(1,1) = "a" - ├── opening_loc: ∅ - ├── arguments: ∅ - ├── closing_loc: ∅ - └── block: - @ BlockNode (location: (1,2)-(8,3)) - ├── locals: [:v] - ├── parameters: ∅ - ├── body: - │ @ StatementsNode (location: (2,2)-(7,5)) - │ └── body: (length: 2) - │ ├── @ LocalVariableWriteNode (location: (2,2)-(2,9)) - │ │ ├── name: :v - │ │ ├── depth: 0 - │ │ ├── name_loc: (2,2)-(2,3) = "v" - │ │ ├── value: - │ │ │ @ NilNode (location: (2,6)-(2,9)) - │ │ └── operator_loc: (2,4)-(2,5) = "=" - │ └── @ BeginNode (location: (3,2)-(7,5)) - │ ├── begin_keyword_loc: (3,2)-(3,7) = "begin" - │ ├── statements: - │ │ @ StatementsNode (location: (4,4)-(4,9)) - │ │ └── body: (length: 1) - │ │ └── @ YieldNode (location: (4,4)-(4,9)) - │ │ ├── keyword_loc: (4,4)-(4,9) = "yield" - │ │ ├── lparen_loc: ∅ - │ │ ├── arguments: ∅ - │ │ └── rparen_loc: ∅ - │ ├── rescue_clause: - │ │ @ RescueNode (location: (5,2)-(6,9)) - │ │ ├── keyword_loc: (5,2)-(5,8) = "rescue" - │ │ ├── exceptions: (length: 1) - │ │ │ └── @ ConstantReadNode (location: (5,9)-(5,18)) - │ │ │ └── name: :Exception - │ │ ├── operator_loc: (5,19)-(5,21) = "=>" - │ │ ├── reference: - │ │ │ @ LocalVariableTargetNode (location: (5,22)-(5,23)) - │ │ │ ├── name: :v - │ │ │ └── depth: 0 - │ │ ├── statements: - │ │ │ @ StatementsNode (location: (6,4)-(6,9)) - │ │ │ └── body: (length: 1) - │ │ │ └── @ BreakNode (location: (6,4)-(6,9)) - │ │ │ ├── arguments: ∅ - │ │ │ └── keyword_loc: (6,4)-(6,9) = "break" - │ │ └── consequent: ∅ - │ ├── else_clause: ∅ - │ ├── ensure_clause: ∅ - │ └── end_keyword_loc: (7,2)-(7,5) = "end" - ├── opening_loc: (1,2)-(1,4) = "do" - └── closing_loc: (8,0)-(8,3) = "end" diff --git a/test/prism/snapshots/seattlerb/defined_eh_parens.txt b/test/prism/snapshots/seattlerb/defined_eh_parens.txt index 49b577fcd13..7e18a247875 100644 --- a/test/prism/snapshots/seattlerb/defined_eh_parens.txt +++ b/test/prism/snapshots/seattlerb/defined_eh_parens.txt @@ -1,13 +1,16 @@ @ ProgramNode (location: (1,0)-(1,12)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,12)) + ├── flags: ∅ └── body: (length: 1) └── @ DefinedNode (location: (1,0)-(1,12)) + ├── flags: newline ├── lparen_loc: (1,8)-(1,9) = "(" ├── value: │ @ IntegerNode (location: (1,9)-(1,11)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 42 ├── rparen_loc: (1,11)-(1,12) = ")" └── keyword_loc: (1,0)-(1,8) = "defined?" diff --git a/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt b/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt index 3f2bdf44a44..312b0214d6f 100644 --- a/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt +++ b/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,29)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,29)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,29)) + ├── flags: newline ├── name: :call ├── name_loc: (1,4)-(1,8) = "call" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,9)-(1,24)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,9)-(1,15)) │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt b/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt index 4121770c5c2..ababd94b111 100644 --- a/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt +++ b/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,29)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,29)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,29)) + ├── flags: newline ├── name: :a ├── name_loc: (1,4)-(1,5) = "a" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,12)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) │ │ ├── flags: ∅ @@ -19,12 +23,14 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ ForwardingParameterNode (location: (1,9)-(1,12)) + │ │ └── flags: ∅ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (1,15)-(1,24)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,15)-(1,24)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :b @@ -32,12 +38,14 @@ │ ├── opening_loc: (1,16)-(1,17) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (1,17)-(1,23)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_forwarding │ │ └── arguments: (length: 2) │ │ ├── @ LocalVariableReadNode (location: (1,17)-(1,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :x │ │ │ └── depth: 0 │ │ └── @ ForwardingArgumentsNode (location: (1,20)-(1,23)) + │ │ └── flags: ∅ │ ├── closing_loc: (1,23)-(1,24) = ")" │ └── block: ∅ ├── locals: [:x] diff --git a/test/prism/snapshots/seattlerb/defn_args_forward_args.txt b/test/prism/snapshots/seattlerb/defn_args_forward_args.txt index 178b6ccde73..d689049433a 100644 --- a/test/prism/snapshots/seattlerb/defn_args_forward_args.txt +++ b/test/prism/snapshots/seattlerb/defn_args_forward_args.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,41)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,41)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,41)) + ├── flags: newline ├── name: :a ├── name_loc: (1,4)-(1,5) = "a" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,18)) + │ ├── flags: ∅ │ ├── requireds: (length: 3) │ │ ├── @ RequiredParameterNode (location: (1,6)-(1,7)) │ │ │ ├── flags: ∅ @@ -25,12 +29,14 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ ForwardingParameterNode (location: (1,15)-(1,18)) + │ │ └── flags: ∅ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (1,21)-(1,36)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,21)-(1,36)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :b @@ -38,18 +44,20 @@ │ ├── opening_loc: (1,22)-(1,23) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (1,23)-(1,35)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_forwarding │ │ └── arguments: (length: 3) │ │ ├── @ SymbolNode (location: (1,23)-(1,27)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,23)-(1,24) = ":" │ │ │ ├── value_loc: (1,24)-(1,27) = "get" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "get" │ │ ├── @ LocalVariableReadNode (location: (1,29)-(1,30)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :z │ │ │ └── depth: 0 │ │ └── @ ForwardingArgumentsNode (location: (1,32)-(1,35)) + │ │ └── flags: ∅ │ ├── closing_loc: (1,35)-(1,36) = ")" │ └── block: ∅ ├── locals: [:x, :y, :z] diff --git a/test/prism/snapshots/seattlerb/defn_comments.txt b/test/prism/snapshots/seattlerb/defn_comments.txt index 585aa65c9a6..8ea66b77603 100644 --- a/test/prism/snapshots/seattlerb/defn_comments.txt +++ b/test/prism/snapshots/seattlerb/defn_comments.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (4,0)-(5,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (4,0)-(5,3)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (4,0)-(5,3)) + ├── flags: newline ├── name: :blah ├── name_loc: (4,4)-(4,8) = "blah" ├── receiver: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_endless_command.txt b/test/prism/snapshots/seattlerb/defn_endless_command.txt index c3ea59282a7..12149a821cb 100644 --- a/test/prism/snapshots/seattlerb/defn_endless_command.txt +++ b/test/prism/snapshots/seattlerb/defn_endless_command.txt @@ -1,15 +1,19 @@ @ ProgramNode (location: (1,0)-(1,33)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,33)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,33)) + ├── flags: newline ├── name: :some_method ├── name_loc: (1,4)-(1,15) = "some_method" ├── receiver: ∅ ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (1,18)-(1,33)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,18)-(1,33)) │ ├── flags: ignore_visibility @@ -23,7 +27,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,31)-(1,33)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 42 │ ├── closing_loc: ∅ │ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_endless_command_rescue.txt b/test/prism/snapshots/seattlerb/defn_endless_command_rescue.txt index dfd1d01ba82..99194a5ce94 100644 --- a/test/prism/snapshots/seattlerb/defn_endless_command_rescue.txt +++ b/test/prism/snapshots/seattlerb/defn_endless_command_rescue.txt @@ -1,17 +1,22 @@ @ ProgramNode (location: (1,0)-(1,43)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,43)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,43)) + ├── flags: newline ├── name: :some_method ├── name_loc: (1,4)-(1,15) = "some_method" ├── receiver: ∅ ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (1,18)-(1,43)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ RescueModifierNode (location: (1,18)-(1,43)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (1,18)-(1,33)) │ │ ├── flags: ignore_visibility @@ -25,14 +30,14 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (1,31)-(1,33)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 42 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── keyword_loc: (1,34)-(1,40) = "rescue" │ └── rescue_expression: │ @ IntegerNode (location: (1,41)-(1,43)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 24 ├── locals: [] ├── def_keyword_loc: (1,0)-(1,3) = "def" diff --git a/test/prism/snapshots/seattlerb/defn_forward_args.txt b/test/prism/snapshots/seattlerb/defn_forward_args.txt index 71a984c8115..58a97028c6c 100644 --- a/test/prism/snapshots/seattlerb/defn_forward_args.txt +++ b/test/prism/snapshots/seattlerb/defn_forward_args.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,23)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,23)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,23)) + ├── flags: newline ├── name: :a ├── name_loc: (1,4)-(1,5) = "a" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,9)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -16,12 +20,14 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ ForwardingParameterNode (location: (1,6)-(1,9)) + │ │ └── flags: ∅ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (1,12)-(1,18)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,12)-(1,18)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :b @@ -29,9 +35,10 @@ │ ├── opening_loc: (1,13)-(1,14) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (1,14)-(1,17)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_forwarding │ │ └── arguments: (length: 1) │ │ └── @ ForwardingArgumentsNode (location: (1,14)-(1,17)) + │ │ └── flags: ∅ │ ├── closing_loc: (1,17)-(1,18) = ")" │ └── block: ∅ ├── locals: [] diff --git a/test/prism/snapshots/seattlerb/defn_forward_args__no_parens.txt b/test/prism/snapshots/seattlerb/defn_forward_args__no_parens.txt index 4a4d69e4d03..5d8e09f6c04 100644 --- a/test/prism/snapshots/seattlerb/defn_forward_args__no_parens.txt +++ b/test/prism/snapshots/seattlerb/defn_forward_args__no_parens.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(3,3)) + ├── flags: newline ├── name: :f ├── name_loc: (1,4)-(1,5) = "f" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,9)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -16,12 +20,14 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ ForwardingParameterNode (location: (1,6)-(1,9)) + │ │ └── flags: ∅ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (2,2)-(2,8)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (2,2)-(2,8)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :m @@ -29,9 +35,10 @@ │ ├── opening_loc: (2,3)-(2,4) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (2,4)-(2,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_forwarding │ │ └── arguments: (length: 1) │ │ └── @ ForwardingArgumentsNode (location: (2,4)-(2,7)) + │ │ └── flags: ∅ │ ├── closing_loc: (2,7)-(2,8) = ")" │ └── block: ∅ ├── locals: [] diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_env.txt b/test/prism/snapshots/seattlerb/defn_kwarg_env.txt index 2aadedd9646..0df82b5dc2b 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_env.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_env.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,45)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,45)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,45)) + ├── flags: newline ├── name: :test ├── name_loc: (1,4)-(1,8) = "test" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,9)-(1,18)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -23,9 +27,10 @@ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (1,20)-(1,41)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,20)-(1,41)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :test_splat @@ -39,8 +44,10 @@ │ │ ├── flags: ∅ │ │ └── elements: (length: 1) │ │ └── @ AssocSplatNode (location: (1,31)-(1,40)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ LocalVariableReadNode (location: (1,33)-(1,40)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :testing │ │ │ └── depth: 0 │ │ └── operator_loc: (1,31)-(1,33) = "**" diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_kwarg.txt b/test/prism/snapshots/seattlerb/defn_kwarg_kwarg.txt index 8a5022ff37d..ead1437a86f 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_kwarg.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_kwarg.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,24)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,24)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,24)) + ├── flags: newline ├── name: :f ├── name_loc: (1,4)-(1,5) = "f" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,19)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) │ │ ├── flags: ∅ @@ -23,7 +27,7 @@ │ │ │ ├── name_loc: (1,9)-(1,11) = "b:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,12)-(1,13)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ OptionalKeywordParameterNode (location: (1,15)-(1,19)) │ │ ├── flags: ∅ @@ -31,7 +35,7 @@ │ │ ├── name_loc: (1,15)-(1,17) = "c:" │ │ └── value: │ │ @ IntegerNode (location: (1,18)-(1,19)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── keyword_rest: ∅ │ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat.txt b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat.txt index 4c980bc27f8..2b228334604 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,20)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,20)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,20)) + ├── flags: newline ├── name: :a ├── name_loc: (1,4)-(1,5) = "a" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,15)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -20,7 +24,7 @@ │ │ ├── name_loc: (1,6)-(1,8) = "b:" │ │ └── value: │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── keyword_rest: │ │ @ KeywordRestParameterNode (location: (1,12)-(1,15)) diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt index 40afacc2a7d..1e0e1f132e7 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,19)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,19)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,19)) + ├── flags: newline ├── name: :a ├── name_loc: (1,4)-(1,5) = "a" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,14)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -20,7 +24,7 @@ │ │ ├── name_loc: (1,6)-(1,8) = "b:" │ │ └── value: │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── keyword_rest: │ │ @ KeywordRestParameterNode (location: (1,12)-(1,14)) diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_lvar.txt b/test/prism/snapshots/seattlerb/defn_kwarg_lvar.txt index 0eae56924c8..0835d3987db 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_lvar.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_lvar.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,26)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,26)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,26)) + ├── flags: newline ├── name: :fun ├── name_loc: (1,4)-(1,7) = "fun" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,8)-(1,16)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -20,7 +24,7 @@ │ │ ├── name_loc: (1,8)-(1,11) = "kw:" │ │ └── value: │ │ @ SymbolNode (location: (1,12)-(1,16)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,12)-(1,13) = ":" │ │ ├── value_loc: (1,13)-(1,16) = "val" │ │ ├── closing_loc: ∅ @@ -29,8 +33,10 @@ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (1,19)-(1,21)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ LocalVariableReadNode (location: (1,19)-(1,21)) + │ ├── flags: newline │ ├── name: :kw │ └── depth: 0 ├── locals: [:kw] diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_no_parens.txt b/test/prism/snapshots/seattlerb/defn_kwarg_no_parens.txt index bc5747ad02d..3f6af5e0ee4 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_no_parens.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_no_parens.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(2,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(2,3)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(2,3)) + ├── flags: newline ├── name: :f ├── name_loc: (1,4)-(1,5) = "f" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,10)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -20,7 +24,7 @@ │ │ ├── name_loc: (1,6)-(1,8) = "a:" │ │ └── value: │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── keyword_rest: ∅ │ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_val.txt b/test/prism/snapshots/seattlerb/defn_kwarg_val.txt index 82527f7875f..38cb995c093 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_val.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_val.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,17)) + ├── flags: newline ├── name: :f ├── name_loc: (1,4)-(1,5) = "f" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,12)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) │ │ ├── flags: ∅ @@ -23,7 +27,7 @@ │ │ ├── name_loc: (1,9)-(1,11) = "b:" │ │ └── value: │ │ @ IntegerNode (location: (1,11)-(1,12)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── keyword_rest: ∅ │ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_no_kwargs.txt b/test/prism/snapshots/seattlerb/defn_no_kwargs.txt index 0ef0634a537..778b300a4be 100644 --- a/test/prism/snapshots/seattlerb/defn_no_kwargs.txt +++ b/test/prism/snapshots/seattlerb/defn_no_kwargs.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,17)) + ├── flags: newline ├── name: :x ├── name_loc: (1,4)-(1,5) = "x" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,11)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -16,6 +20,7 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ NoKeywordsParameterNode (location: (1,6)-(1,11)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (1,6)-(1,8) = "**" │ │ └── keyword_loc: (1,8)-(1,11) = "nil" │ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_oneliner.txt b/test/prism/snapshots/seattlerb/defn_oneliner.txt index e7004998092..81ca22f010e 100644 --- a/test/prism/snapshots/seattlerb/defn_oneliner.txt +++ b/test/prism/snapshots/seattlerb/defn_oneliner.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,27)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,27)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,27)) + ├── flags: newline ├── name: :exec ├── name_loc: (1,4)-(1,8) = "exec" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,9)-(1,12)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,9)-(1,12)) │ │ ├── flags: ∅ @@ -21,6 +25,7 @@ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (1,16)-(1,27)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,16)-(1,27)) │ ├── flags: ignore_visibility @@ -34,6 +39,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ LocalVariableReadNode (location: (1,23)-(1,26)) + │ │ ├── flags: ∅ │ │ ├── name: :cmd │ │ └── depth: 0 │ ├── closing_loc: (1,26)-(1,27) = ")" diff --git a/test/prism/snapshots/seattlerb/defn_oneliner_eq2.txt b/test/prism/snapshots/seattlerb/defn_oneliner_eq2.txt index 2708351ede4..414ecff4edd 100644 --- a/test/prism/snapshots/seattlerb/defn_oneliner_eq2.txt +++ b/test/prism/snapshots/seattlerb/defn_oneliner_eq2.txt @@ -1,25 +1,32 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ ClassNode (location: (1,0)-(3,3)) + ├── flags: newline ├── locals: [] ├── class_keyword_loc: (1,0)-(1,5) = "class" ├── constant_path: │ @ ConstantReadNode (location: (1,6)-(1,7)) + │ ├── flags: ∅ │ └── name: :X ├── inheritance_operator_loc: ∅ ├── superclass: ∅ ├── body: │ @ StatementsNode (location: (2,2)-(2,16)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ DefNode (location: (2,2)-(2,16)) + │ ├── flags: newline │ ├── name: :== │ ├── name_loc: (2,6)-(2,8) = "==" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (2,9)-(2,10)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (2,9)-(2,10)) │ │ │ ├── flags: ∅ @@ -32,9 +39,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (2,14)-(2,16)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (2,14)-(2,16)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 42 │ ├── locals: [:o] │ ├── def_keyword_loc: (2,2)-(2,5) = "def" diff --git a/test/prism/snapshots/seattlerb/defn_oneliner_noargs.txt b/test/prism/snapshots/seattlerb/defn_oneliner_noargs.txt index 54555b1a238..5928f64179f 100644 --- a/test/prism/snapshots/seattlerb/defn_oneliner_noargs.txt +++ b/test/prism/snapshots/seattlerb/defn_oneliner_noargs.txt @@ -1,15 +1,19 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,17)) + ├── flags: newline ├── name: :exec ├── name_loc: (1,4)-(1,8) = "exec" ├── receiver: ∅ ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (1,11)-(1,17)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,11)-(1,17)) │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/seattlerb/defn_oneliner_noargs_parentheses.txt b/test/prism/snapshots/seattlerb/defn_oneliner_noargs_parentheses.txt index e0fc4636f18..d0cd777039e 100644 --- a/test/prism/snapshots/seattlerb/defn_oneliner_noargs_parentheses.txt +++ b/test/prism/snapshots/seattlerb/defn_oneliner_noargs_parentheses.txt @@ -1,15 +1,19 @@ @ ProgramNode (location: (1,0)-(1,19)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,19)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,19)) + ├── flags: newline ├── name: :exec ├── name_loc: (1,4)-(1,8) = "exec" ├── receiver: ∅ ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (1,13)-(1,19)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,13)-(1,19)) │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/seattlerb/defn_oneliner_rescue.txt b/test/prism/snapshots/seattlerb/defn_oneliner_rescue.txt index b5b5dbe6ac6..d6cfba773d6 100644 --- a/test/prism/snapshots/seattlerb/defn_oneliner_rescue.txt +++ b/test/prism/snapshots/seattlerb/defn_oneliner_rescue.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(13,38)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(13,38)) + ├── flags: ∅ └── body: (length: 3) ├── @ DefNode (location: (1,0)-(5,3)) + │ ├── flags: newline │ ├── name: :exec │ ├── name_loc: (1,4)-(1,8) = "exec" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,9)-(1,12)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,12)) │ │ │ ├── flags: ∅ @@ -21,12 +25,14 @@ │ │ └── block: ∅ │ ├── body: │ │ @ BeginNode (location: (1,0)-(5,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (2,2)-(2,13)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (2,2)-(2,13)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :system @@ -37,21 +43,25 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ LocalVariableReadNode (location: (2,9)-(2,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :cmd │ │ │ │ └── depth: 0 │ │ │ ├── closing_loc: (2,12)-(2,13) = ")" │ │ │ └── block: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (3,0)-(4,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (3,0)-(3,6) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (4,2)-(4,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ NilNode (location: (4,2)-(4,5)) - │ │ │ └── consequent: ∅ + │ │ │ │ └── flags: newline, static_literal + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (5,0)-(5,3) = "end" @@ -63,11 +73,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (5,0)-(5,3) = "end" ├── @ DefNode (location: (8,0)-(10,3)) + │ ├── flags: newline │ ├── name: :exec │ ├── name_loc: (8,4)-(8,8) = "exec" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (8,9)-(8,12)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (8,9)-(8,12)) │ │ │ ├── flags: ∅ @@ -80,8 +92,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (9,2)-(9,24)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RescueModifierNode (location: (9,2)-(9,24)) + │ │ ├── flags: newline │ │ ├── expression: │ │ │ @ CallNode (location: (9,2)-(9,13)) │ │ │ ├── flags: ignore_visibility @@ -95,6 +109,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ LocalVariableReadNode (location: (9,9)-(9,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :cmd │ │ │ │ └── depth: 0 │ │ │ ├── closing_loc: (9,12)-(9,13) = ")" @@ -102,6 +117,7 @@ │ │ ├── keyword_loc: (9,14)-(9,20) = "rescue" │ │ └── rescue_expression: │ │ @ NilNode (location: (9,21)-(9,24)) + │ │ └── flags: static_literal │ ├── locals: [:cmd] │ ├── def_keyword_loc: (8,0)-(8,3) = "def" │ ├── operator_loc: ∅ @@ -110,11 +126,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (10,0)-(10,3) = "end" └── @ DefNode (location: (13,0)-(13,38)) + ├── flags: newline ├── name: :exec ├── name_loc: (13,4)-(13,8) = "exec" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (13,9)-(13,12)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (13,9)-(13,12)) │ │ ├── flags: ∅ @@ -127,8 +145,10 @@ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (13,16)-(13,38)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ RescueModifierNode (location: (13,16)-(13,38)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (13,16)-(13,27)) │ │ ├── flags: ignore_visibility @@ -142,6 +162,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ LocalVariableReadNode (location: (13,23)-(13,26)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :cmd │ │ │ └── depth: 0 │ │ ├── closing_loc: (13,26)-(13,27) = ")" @@ -149,6 +170,7 @@ │ ├── keyword_loc: (13,28)-(13,34) = "rescue" │ └── rescue_expression: │ @ NilNode (location: (13,35)-(13,38)) + │ └── flags: static_literal ├── locals: [:cmd] ├── def_keyword_loc: (13,0)-(13,3) = "def" ├── operator_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_opt_last_arg.txt b/test/prism/snapshots/seattlerb/defn_opt_last_arg.txt index 569bc230783..f7c37e3d457 100644 --- a/test/prism/snapshots/seattlerb/defn_opt_last_arg.txt +++ b/test/prism/snapshots/seattlerb/defn_opt_last_arg.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(2,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(2,3)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(2,3)) + ├── flags: newline ├── name: :m ├── name_loc: (1,4)-(1,5) = "m" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,17)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 1) │ │ └── @ OptionalParameterNode (location: (1,6)-(1,17)) @@ -18,6 +22,7 @@ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ └── value: │ │ @ FalseNode (location: (1,12)-(1,17)) + │ │ └── flags: static_literal │ ├── rest: ∅ │ ├── posts: (length: 0) │ ├── keywords: (length: 0) diff --git a/test/prism/snapshots/seattlerb/defn_opt_reg.txt b/test/prism/snapshots/seattlerb/defn_opt_reg.txt index f86168513ac..9bdd1439050 100644 --- a/test/prism/snapshots/seattlerb/defn_opt_reg.txt +++ b/test/prism/snapshots/seattlerb/defn_opt_reg.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,19)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,19)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,19)) + ├── flags: newline ├── name: :f ├── name_loc: (1,4)-(1,5) = "f" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,14)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 1) │ │ └── @ OptionalParameterNode (location: (1,6)-(1,11)) @@ -18,6 +22,7 @@ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ └── value: │ │ @ NilNode (location: (1,8)-(1,11)) + │ │ └── flags: static_literal │ ├── rest: ∅ │ ├── posts: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,13)-(1,14)) diff --git a/test/prism/snapshots/seattlerb/defn_opt_splat_arg.txt b/test/prism/snapshots/seattlerb/defn_opt_splat_arg.txt index 3019e9b73e3..d90fddc6533 100644 --- a/test/prism/snapshots/seattlerb/defn_opt_splat_arg.txt +++ b/test/prism/snapshots/seattlerb/defn_opt_splat_arg.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,24)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,24)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,24)) + ├── flags: newline ├── name: :f ├── name_loc: (1,4)-(1,5) = "f" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,7)-(1,19)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 1) │ │ └── @ OptionalParameterNode (location: (1,7)-(1,12)) @@ -18,7 +22,7 @@ │ │ ├── operator_loc: (1,9)-(1,10) = "=" │ │ └── value: │ │ @ IntegerNode (location: (1,11)-(1,12)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── rest: │ │ @ RestParameterNode (location: (1,14)-(1,16)) diff --git a/test/prism/snapshots/seattlerb/defn_powarg.txt b/test/prism/snapshots/seattlerb/defn_powarg.txt index bce131ad183..8d4ff4283ac 100644 --- a/test/prism/snapshots/seattlerb/defn_powarg.txt +++ b/test/prism/snapshots/seattlerb/defn_powarg.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,17)) + ├── flags: newline ├── name: :f ├── name_loc: (1,4)-(1,5) = "f" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,12)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_reg_opt_reg.txt b/test/prism/snapshots/seattlerb/defn_reg_opt_reg.txt index d079e1b5f39..0cd1435e8f9 100644 --- a/test/prism/snapshots/seattlerb/defn_reg_opt_reg.txt +++ b/test/prism/snapshots/seattlerb/defn_reg_opt_reg.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,23)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,23)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,23)) + ├── flags: newline ├── name: :f ├── name_loc: (1,4)-(1,5) = "f" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,18)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) │ │ ├── flags: ∅ @@ -21,7 +25,7 @@ │ │ ├── operator_loc: (1,11)-(1,12) = "=" │ │ └── value: │ │ @ SymbolNode (location: (1,13)-(1,15)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,13)-(1,14) = ":" │ │ ├── value_loc: (1,14)-(1,15) = "c" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_splat_arg.txt b/test/prism/snapshots/seattlerb/defn_splat_arg.txt index 109fac495ab..c137e263c44 100644 --- a/test/prism/snapshots/seattlerb/defn_splat_arg.txt +++ b/test/prism/snapshots/seattlerb/defn_splat_arg.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,15)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,15)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,15)) + ├── flags: newline ├── name: :f ├── name_loc: (1,4)-(1,5) = "f" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,10)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: diff --git a/test/prism/snapshots/seattlerb/defn_unary_not.txt b/test/prism/snapshots/seattlerb/defn_unary_not.txt index 231a3c0da9e..0722d3cdca1 100644 --- a/test/prism/snapshots/seattlerb/defn_unary_not.txt +++ b/test/prism/snapshots/seattlerb/defn_unary_not.txt @@ -1,17 +1,22 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,17)) + ├── flags: newline ├── name: :! ├── name_loc: (1,4)-(1,6) = "!@" ├── receiver: ∅ ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (1,8)-(1,12)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ TrueNode (location: (1,8)-(1,12)) + │ └── flags: newline, static_literal ├── locals: [] ├── def_keyword_loc: (1,0)-(1,3) = "def" ├── operator_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/defns_reserved.txt b/test/prism/snapshots/seattlerb/defns_reserved.txt index 96860b49ce0..10361184ac8 100644 --- a/test/prism/snapshots/seattlerb/defns_reserved.txt +++ b/test/prism/snapshots/seattlerb/defns_reserved.txt @@ -1,13 +1,17 @@ @ ProgramNode (location: (1,0)-(1,20)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,20)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,20)) + ├── flags: newline ├── name: :return ├── name_loc: (1,9)-(1,15) = "return" ├── receiver: │ @ SelfNode (location: (1,4)-(1,8)) + │ └── flags: ∅ ├── parameters: ∅ ├── body: ∅ ├── locals: [] diff --git a/test/prism/snapshots/seattlerb/defs_as_arg_with_do_block_inside.txt b/test/prism/snapshots/seattlerb/defs_as_arg_with_do_block_inside.txt index 24bb14f8e14..f9479eb11bd 100644 --- a/test/prism/snapshots/seattlerb/defs_as_arg_with_do_block_inside.txt +++ b/test/prism/snapshots/seattlerb/defs_as_arg_with_do_block_inside.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,30)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,30)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,30)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :p @@ -15,16 +17,19 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ DefNode (location: (1,2)-(1,30)) + │ ├── flags: ∅ │ ├── name: :b │ ├── name_loc: (1,11)-(1,12) = "b" │ ├── receiver: │ │ @ SelfNode (location: (1,6)-(1,10)) + │ │ └── flags: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,14)-(1,25)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (1,14)-(1,25)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ CallNode (location: (1,14)-(1,15)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -44,6 +49,7 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (1,18)-(1,25)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/defs_comments.txt b/test/prism/snapshots/seattlerb/defs_comments.txt index a2976e7ee28..7f94497978b 100644 --- a/test/prism/snapshots/seattlerb/defs_comments.txt +++ b/test/prism/snapshots/seattlerb/defs_comments.txt @@ -1,13 +1,17 @@ @ ProgramNode (location: (4,0)-(5,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (4,0)-(5,3)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (4,0)-(5,3)) + ├── flags: newline ├── name: :blah ├── name_loc: (4,9)-(4,13) = "blah" ├── receiver: │ @ SelfNode (location: (4,4)-(4,8)) + │ └── flags: ∅ ├── parameters: ∅ ├── body: ∅ ├── locals: [] diff --git a/test/prism/snapshots/seattlerb/defs_endless_command.txt b/test/prism/snapshots/seattlerb/defs_endless_command.txt index f3c4e794178..f34d667901c 100644 --- a/test/prism/snapshots/seattlerb/defs_endless_command.txt +++ b/test/prism/snapshots/seattlerb/defs_endless_command.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(1,35)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,35)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,35)) + ├── flags: newline ├── name: :some_method ├── name_loc: (1,6)-(1,17) = "some_method" ├── receiver: @@ -20,6 +23,7 @@ ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (1,20)-(1,35)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,20)-(1,35)) │ ├── flags: ignore_visibility @@ -33,7 +37,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,33)-(1,35)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 42 │ ├── closing_loc: ∅ │ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/defs_endless_command_rescue.txt b/test/prism/snapshots/seattlerb/defs_endless_command_rescue.txt index b0cd34a9c83..fe859369400 100644 --- a/test/prism/snapshots/seattlerb/defs_endless_command_rescue.txt +++ b/test/prism/snapshots/seattlerb/defs_endless_command_rescue.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(1,45)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,45)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,45)) + ├── flags: newline ├── name: :some_method ├── name_loc: (1,6)-(1,17) = "some_method" ├── receiver: @@ -20,8 +23,10 @@ ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (1,20)-(1,45)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ RescueModifierNode (location: (1,20)-(1,45)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (1,20)-(1,35)) │ │ ├── flags: ignore_visibility @@ -35,14 +40,14 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (1,33)-(1,35)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 42 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── keyword_loc: (1,36)-(1,42) = "rescue" │ └── rescue_expression: │ @ IntegerNode (location: (1,43)-(1,45)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 24 ├── locals: [] ├── def_keyword_loc: (1,0)-(1,3) = "def" diff --git a/test/prism/snapshots/seattlerb/defs_kwarg.txt b/test/prism/snapshots/seattlerb/defs_kwarg.txt index 53235c9bb80..86a2d562e3a 100644 --- a/test/prism/snapshots/seattlerb/defs_kwarg.txt +++ b/test/prism/snapshots/seattlerb/defs_kwarg.txt @@ -1,15 +1,20 @@ @ ProgramNode (location: (1,0)-(2,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(2,3)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(2,3)) + ├── flags: newline ├── name: :a ├── name_loc: (1,9)-(1,10) = "a" ├── receiver: │ @ SelfNode (location: (1,4)-(1,8)) + │ └── flags: ∅ ├── parameters: │ @ ParametersNode (location: (1,11)-(1,15)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -21,7 +26,7 @@ │ │ ├── name_loc: (1,11)-(1,13) = "b:" │ │ └── value: │ │ @ IntegerNode (location: (1,14)-(1,15)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── keyword_rest: ∅ │ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/defs_oneliner.txt b/test/prism/snapshots/seattlerb/defs_oneliner.txt index d32975354d9..c99b8108440 100644 --- a/test/prism/snapshots/seattlerb/defs_oneliner.txt +++ b/test/prism/snapshots/seattlerb/defs_oneliner.txt @@ -1,15 +1,20 @@ @ ProgramNode (location: (1,0)-(1,32)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,32)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,32)) + ├── flags: newline ├── name: :exec ├── name_loc: (1,9)-(1,13) = "exec" ├── receiver: │ @ SelfNode (location: (1,4)-(1,8)) + │ └── flags: ∅ ├── parameters: │ @ ParametersNode (location: (1,14)-(1,17)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,14)-(1,17)) │ │ ├── flags: ∅ @@ -22,6 +27,7 @@ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (1,21)-(1,32)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,21)-(1,32)) │ ├── flags: ignore_visibility @@ -35,6 +41,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ LocalVariableReadNode (location: (1,28)-(1,31)) + │ │ ├── flags: ∅ │ │ ├── name: :cmd │ │ └── depth: 0 │ ├── closing_loc: (1,31)-(1,32) = ")" diff --git a/test/prism/snapshots/seattlerb/defs_oneliner_eq2.txt b/test/prism/snapshots/seattlerb/defs_oneliner_eq2.txt index fcc5c63cf06..328ba5d78b2 100644 --- a/test/prism/snapshots/seattlerb/defs_oneliner_eq2.txt +++ b/test/prism/snapshots/seattlerb/defs_oneliner_eq2.txt @@ -1,26 +1,34 @@ @ ProgramNode (location: (1,0)-(3,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,3)) + ├── flags: ∅ └── body: (length: 1) └── @ ClassNode (location: (1,0)-(3,3)) + ├── flags: newline ├── locals: [] ├── class_keyword_loc: (1,0)-(1,5) = "class" ├── constant_path: │ @ ConstantReadNode (location: (1,6)-(1,7)) + │ ├── flags: ∅ │ └── name: :X ├── inheritance_operator_loc: ∅ ├── superclass: ∅ ├── body: │ @ StatementsNode (location: (2,2)-(2,21)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ DefNode (location: (2,2)-(2,21)) + │ ├── flags: newline │ ├── name: :== │ ├── name_loc: (2,11)-(2,13) = "==" │ ├── receiver: │ │ @ SelfNode (location: (2,6)-(2,10)) + │ │ └── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (2,14)-(2,15)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (2,14)-(2,15)) │ │ │ ├── flags: ∅ @@ -33,9 +41,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (2,19)-(2,21)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (2,19)-(2,21)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 42 │ ├── locals: [:o] │ ├── def_keyword_loc: (2,2)-(2,5) = "def" diff --git a/test/prism/snapshots/seattlerb/defs_oneliner_rescue.txt b/test/prism/snapshots/seattlerb/defs_oneliner_rescue.txt index f7762107682..985744d45e9 100644 --- a/test/prism/snapshots/seattlerb/defs_oneliner_rescue.txt +++ b/test/prism/snapshots/seattlerb/defs_oneliner_rescue.txt @@ -1,15 +1,20 @@ @ ProgramNode (location: (1,0)-(13,43)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(13,43)) + ├── flags: ∅ └── body: (length: 3) ├── @ DefNode (location: (1,0)-(5,3)) + │ ├── flags: newline │ ├── name: :exec │ ├── name_loc: (1,9)-(1,13) = "exec" │ ├── receiver: │ │ @ SelfNode (location: (1,4)-(1,8)) + │ │ └── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,14)-(1,17)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,14)-(1,17)) │ │ │ ├── flags: ∅ @@ -22,12 +27,14 @@ │ │ └── block: ∅ │ ├── body: │ │ @ BeginNode (location: (1,0)-(5,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (2,2)-(2,13)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (2,2)-(2,13)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :system @@ -38,21 +45,25 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ LocalVariableReadNode (location: (2,9)-(2,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :cmd │ │ │ │ └── depth: 0 │ │ │ ├── closing_loc: (2,12)-(2,13) = ")" │ │ │ └── block: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (3,0)-(4,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (3,0)-(3,6) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (4,2)-(4,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ NilNode (location: (4,2)-(4,5)) - │ │ │ └── consequent: ∅ + │ │ │ │ └── flags: newline, static_literal + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (5,0)-(5,3) = "end" @@ -64,12 +75,15 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (5,0)-(5,3) = "end" ├── @ DefNode (location: (8,0)-(10,3)) + │ ├── flags: newline │ ├── name: :exec │ ├── name_loc: (8,9)-(8,13) = "exec" │ ├── receiver: │ │ @ SelfNode (location: (8,4)-(8,8)) + │ │ └── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (8,14)-(8,17)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (8,14)-(8,17)) │ │ │ ├── flags: ∅ @@ -82,8 +96,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (9,2)-(9,24)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RescueModifierNode (location: (9,2)-(9,24)) + │ │ ├── flags: newline │ │ ├── expression: │ │ │ @ CallNode (location: (9,2)-(9,13)) │ │ │ ├── flags: ignore_visibility @@ -97,6 +113,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ LocalVariableReadNode (location: (9,9)-(9,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :cmd │ │ │ │ └── depth: 0 │ │ │ ├── closing_loc: (9,12)-(9,13) = ")" @@ -104,6 +121,7 @@ │ │ ├── keyword_loc: (9,14)-(9,20) = "rescue" │ │ └── rescue_expression: │ │ @ NilNode (location: (9,21)-(9,24)) + │ │ └── flags: static_literal │ ├── locals: [:cmd] │ ├── def_keyword_loc: (8,0)-(8,3) = "def" │ ├── operator_loc: (8,8)-(8,9) = "." @@ -112,12 +130,15 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (10,0)-(10,3) = "end" └── @ DefNode (location: (13,0)-(13,43)) + ├── flags: newline ├── name: :exec ├── name_loc: (13,9)-(13,13) = "exec" ├── receiver: │ @ SelfNode (location: (13,4)-(13,8)) + │ └── flags: ∅ ├── parameters: │ @ ParametersNode (location: (13,14)-(13,17)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (13,14)-(13,17)) │ │ ├── flags: ∅ @@ -130,8 +151,10 @@ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (13,21)-(13,43)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ RescueModifierNode (location: (13,21)-(13,43)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (13,21)-(13,32)) │ │ ├── flags: ignore_visibility @@ -145,6 +168,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ LocalVariableReadNode (location: (13,28)-(13,31)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :cmd │ │ │ └── depth: 0 │ │ ├── closing_loc: (13,31)-(13,32) = ")" @@ -152,6 +176,7 @@ │ ├── keyword_loc: (13,33)-(13,39) = "rescue" │ └── rescue_expression: │ @ NilNode (location: (13,40)-(13,43)) + │ └── flags: static_literal ├── locals: [:cmd] ├── def_keyword_loc: (13,0)-(13,3) = "def" ├── operator_loc: (13,8)-(13,9) = "." diff --git a/test/prism/snapshots/seattlerb/difficult0_.txt b/test/prism/snapshots/seattlerb/difficult0_.txt index 8ba30ccf85d..233440b1019 100644 --- a/test/prism/snapshots/seattlerb/difficult0_.txt +++ b/test/prism/snapshots/seattlerb/difficult0_.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(4,8)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,8)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(4,8)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :p @@ -35,17 +37,17 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ InterpolatedStringNode (location: (1,9)-(4,4)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: static_literal │ │ │ ├── opening_loc: (1,9)-(1,10) = "'" │ │ │ ├── parts: (length: 2) │ │ │ │ ├── @ StringNode (location: (1,10)-(2,0)) - │ │ │ │ │ ├── flags: frozen + │ │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── content_loc: (1,10)-(2,0) = "b\n" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "b\n" │ │ │ │ └── @ StringNode (location: (4,0)-(4,3)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (4,0)-(4,3) = " c" │ │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/difficult1_line_numbers.txt b/test/prism/snapshots/seattlerb/difficult1_line_numbers.txt index da2306312c7..c34579e6ac8 100644 --- a/test/prism/snapshots/seattlerb/difficult1_line_numbers.txt +++ b/test/prism/snapshots/seattlerb/difficult1_line_numbers.txt @@ -1,18 +1,23 @@ @ ProgramNode (location: (1,0)-(12,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(12,3)) + ├── flags: ∅ └── body: (length: 1) └── @ IfNode (location: (1,0)-(12,3)) + ├── flags: newline ├── if_keyword_loc: (1,0)-(1,2) = "if" ├── predicate: │ @ TrueNode (location: (1,3)-(1,7)) + │ └── flags: static_literal ├── then_keyword_loc: ∅ ├── statements: │ @ StatementsNode (location: (2,2)-(11,11)) + │ ├── flags: ∅ │ └── body: (length: 10) │ ├── @ CallNode (location: (2,2)-(2,5)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :p @@ -23,12 +28,12 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (2,4)-(2,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── @ CallNode (location: (3,2)-(3,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ CallNode (location: (3,2)-(3,3)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -49,12 +54,12 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (3,6)-(3,7)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── @ CallNode (location: (4,2)-(4,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ CallNode (location: (4,2)-(4,3)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -75,15 +80,15 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 2) │ │ │ ├── @ IntegerNode (location: (4,6)-(4,7)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 3 │ │ │ └── @ IntegerNode (location: (4,9)-(4,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 4 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── @ CallNode (location: (5,2)-(5,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ CallNode (location: (5,2)-(5,3)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -104,12 +109,12 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (5,6)-(5,7)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 5 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── @ CallNode (location: (6,2)-(6,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ CallNode (location: (6,2)-(6,3)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -130,15 +135,15 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 2) │ │ │ ├── @ IntegerNode (location: (6,6)-(6,7)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 6 │ │ │ └── @ IntegerNode (location: (6,9)-(6,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 7 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── @ CallNode (location: (7,2)-(7,6)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :p @@ -149,12 +154,12 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (7,4)-(7,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: (7,5)-(7,6) = ")" │ │ └── block: ∅ │ ├── @ CallNode (location: (8,2)-(8,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ CallNode (location: (8,2)-(8,3)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -175,12 +180,12 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (8,6)-(8,7)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── closing_loc: (8,7)-(8,8) = ")" │ │ └── block: ∅ │ ├── @ CallNode (location: (9,2)-(9,11)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ CallNode (location: (9,2)-(9,3)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -201,15 +206,15 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 2) │ │ │ ├── @ IntegerNode (location: (9,6)-(9,7)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 3 │ │ │ └── @ IntegerNode (location: (9,9)-(9,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 4 │ │ ├── closing_loc: (9,10)-(9,11) = ")" │ │ └── block: ∅ │ ├── @ CallNode (location: (10,2)-(10,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ CallNode (location: (10,2)-(10,3)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -230,12 +235,12 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (10,6)-(10,7)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 5 │ │ ├── closing_loc: (10,7)-(10,8) = ")" │ │ └── block: ∅ │ └── @ CallNode (location: (11,2)-(11,11)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (11,2)-(11,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -256,12 +261,12 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (11,6)-(11,7)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 6 │ │ └── @ IntegerNode (location: (11,9)-(11,10)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 7 │ ├── closing_loc: (11,10)-(11,11) = ")" │ └── block: ∅ - ├── consequent: ∅ + ├── subsequent: ∅ └── end_keyword_loc: (12,0)-(12,3) = "end" diff --git a/test/prism/snapshots/seattlerb/difficult1_line_numbers2.txt b/test/prism/snapshots/seattlerb/difficult1_line_numbers2.txt index f586634c59b..ae710f997f3 100644 --- a/test/prism/snapshots/seattlerb/difficult1_line_numbers2.txt +++ b/test/prism/snapshots/seattlerb/difficult1_line_numbers2.txt @@ -1,18 +1,23 @@ @ ProgramNode (location: (1,0)-(7,1)) +├── flags: ∅ ├── locals: [:b, :c] └── statements: @ StatementsNode (location: (1,0)-(7,1)) + ├── flags: ∅ └── body: (length: 2) ├── @ IfNode (location: (1,0)-(6,3)) + │ ├── flags: newline │ ├── if_keyword_loc: (1,0)-(1,2) = "if" │ ├── predicate: │ │ @ TrueNode (location: (1,3)-(1,7)) + │ │ └── flags: static_literal │ ├── then_keyword_loc: (1,8)-(1,12) = "then" │ ├── statements: │ │ @ StatementsNode (location: (2,2)-(5,6)) + │ │ ├── flags: ∅ │ │ └── body: (length: 4) │ │ ├── @ CallNode (location: (2,2)-(2,8)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :p @@ -31,16 +36,17 @@ │ │ │ ├── closing_loc: (2,7)-(2,8) = ")" │ │ │ └── block: ∅ │ │ ├── @ LocalVariableWriteNode (location: (3,2)-(3,7)) + │ │ │ ├── flags: newline │ │ │ ├── name: :b │ │ │ ├── depth: 0 │ │ │ ├── name_loc: (3,2)-(3,3) = "b" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (3,6)-(3,7)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── operator_loc: (3,4)-(3,5) = "=" │ │ ├── @ CallNode (location: (4,2)-(4,5)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :p @@ -51,23 +57,25 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ LocalVariableReadNode (location: (4,4)-(4,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :b │ │ │ │ └── depth: 0 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ LocalVariableWriteNode (location: (5,2)-(5,6)) + │ │ ├── flags: newline │ │ ├── name: :c │ │ ├── depth: 0 │ │ ├── name_loc: (5,2)-(5,3) = "c" │ │ ├── value: │ │ │ @ IntegerNode (location: (5,5)-(5,6)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── operator_loc: (5,4)-(5,5) = "=" - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: (6,0)-(6,3) = "end" └── @ CallNode (location: (7,0)-(7,1)) - ├── flags: variable_call, ignore_visibility + ├── flags: newline, variable_call, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a diff --git a/test/prism/snapshots/seattlerb/difficult2_.txt b/test/prism/snapshots/seattlerb/difficult2_.txt index b53d4cad3f6..2a7e8e49d0f 100644 --- a/test/prism/snapshots/seattlerb/difficult2_.txt +++ b/test/prism/snapshots/seattlerb/difficult2_.txt @@ -1,20 +1,24 @@ @ ProgramNode (location: (1,0)-(2,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(2,6)) + ├── flags: ∅ └── body: (length: 2) ├── @ IfNode (location: (1,0)-(1,13)) + │ ├── flags: newline │ ├── if_keyword_loc: ∅ │ ├── predicate: │ │ @ IntegerNode (location: (1,0)-(1,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── then_keyword_loc: (1,2)-(1,3) = "?" │ ├── statements: │ │ @ StatementsNode (location: (1,4)-(1,9)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (1,4)-(1,9)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :b @@ -32,19 +36,21 @@ │ │ │ └── unescaped: "" │ │ ├── closing_loc: (1,8)-(1,9) = ")" │ │ └── block: ∅ - │ ├── consequent: + │ ├── subsequent: │ │ @ ElseNode (location: (1,10)-(1,13)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (1,10)-(1,11) = ":" │ │ ├── statements: │ │ │ @ StatementsNode (location: (1,12)-(1,13)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (1,12)-(1,13)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: newline, static_literal, decimal │ │ │ └── value: 2 │ │ └── end_keyword_loc: ∅ │ └── end_keyword_loc: ∅ └── @ CallNode (location: (2,0)-(2,6)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :a @@ -58,16 +64,17 @@ │ ├── flags: symbol_keys │ └── elements: (length: 1) │ └── @ AssocNode (location: (2,2)-(2,6)) + │ ├── flags: static_literal │ ├── key: │ │ @ SymbolNode (location: (2,2)-(2,4)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (2,2)-(2,3) = "d" │ │ ├── closing_loc: (2,3)-(2,4) = ":" │ │ └── unescaped: "d" │ ├── value: │ │ @ IntegerNode (location: (2,5)-(2,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ └── operator_loc: ∅ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/difficult3_.txt b/test/prism/snapshots/seattlerb/difficult3_.txt index f074c49a9f9..313cfa4cf26 100644 --- a/test/prism/snapshots/seattlerb/difficult3_.txt +++ b/test/prism/snapshots/seattlerb/difficult3_.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,18)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,18)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,18)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,22 +16,27 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,18)) + ├── flags: ∅ ├── locals: [:a, :b, :c] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,16)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,15)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,12)-(1,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (1,12)-(1,13) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (1,13)-(1,14)) diff --git a/test/prism/snapshots/seattlerb/difficult3_2.txt b/test/prism/snapshots/seattlerb/difficult3_2.txt index af1a6491716..e1eed78c796 100644 --- a/test/prism/snapshots/seattlerb/difficult3_2.txt +++ b/test/prism/snapshots/seattlerb/difficult3_2.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,13)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,13)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,13)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,13)) + ├── flags: ∅ ├── locals: [:a, :b] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,11)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: diff --git a/test/prism/snapshots/seattlerb/difficult3_3.txt b/test/prism/snapshots/seattlerb/difficult3_3.txt index e49bbcd55ab..5dcd71d6515 100644 --- a/test/prism/snapshots/seattlerb/difficult3_3.txt +++ b/test/prism/snapshots/seattlerb/difficult3_3.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,17)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,11 +16,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,17)) + ├── flags: ∅ ├── locals: [:a, :b, :c] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,15)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: diff --git a/test/prism/snapshots/seattlerb/difficult3_4.txt b/test/prism/snapshots/seattlerb/difficult3_4.txt index 73afffb4cb7..b733c42265e 100644 --- a/test/prism/snapshots/seattlerb/difficult3_4.txt +++ b/test/prism/snapshots/seattlerb/difficult3_4.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [:a] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ LocalVariableWriteNode (location: (1,0)-(1,17)) + ├── flags: newline ├── name: :a ├── depth: 0 ├── name_loc: (1,0)-(1,1) = "a" ├── value: │ @ IfNode (location: (1,2)-(1,17)) + │ ├── flags: newline │ ├── if_keyword_loc: ∅ │ ├── predicate: │ │ @ CallNode (location: (1,2)-(1,3)) @@ -24,15 +28,20 @@ │ ├── then_keyword_loc: (1,4)-(1,5) = "?" │ ├── statements: │ │ @ StatementsNode (location: (1,6)-(1,10)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ TrueNode (location: (1,6)-(1,10)) - │ ├── consequent: + │ │ └── flags: newline, static_literal + │ ├── subsequent: │ │ @ ElseNode (location: (1,10)-(1,17)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (1,10)-(1,11) = ":" │ │ ├── statements: │ │ │ @ StatementsNode (location: (1,12)-(1,17)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ FalseNode (location: (1,12)-(1,17)) + │ │ │ └── flags: newline, static_literal │ │ └── end_keyword_loc: ∅ │ └── end_keyword_loc: ∅ └── operator_loc: (1,1)-(1,2) = "=" diff --git a/test/prism/snapshots/seattlerb/difficult3_5.txt b/test/prism/snapshots/seattlerb/difficult3_5.txt index 793c3f1e118..b8bbbdc03ec 100644 --- a/test/prism/snapshots/seattlerb/difficult3_5.txt +++ b/test/prism/snapshots/seattlerb/difficult3_5.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,19)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,19)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,19)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -15,21 +17,24 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ LambdaNode (location: (1,2)-(1,19)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── operator_loc: (1,2)-(1,4) = "->" │ ├── opening_loc: (1,7)-(1,8) = "{" │ ├── closing_loc: (1,18)-(1,19) = "}" │ ├── parameters: │ │ @ BlockParametersNode (location: (1,4)-(1,6)) + │ │ ├── flags: ∅ │ │ ├── parameters: ∅ │ │ ├── locals: (length: 0) │ │ ├── opening_loc: (1,4)-(1,5) = "(" │ │ └── closing_loc: (1,5)-(1,6) = ")" │ └── body: │ @ StatementsNode (location: (1,9)-(1,17)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,9)-(1,17)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :g @@ -39,6 +44,7 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (1,11)-(1,17)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/difficult3__10.txt b/test/prism/snapshots/seattlerb/difficult3__10.txt index 0131e44d445..a5ce0762f16 100644 --- a/test/prism/snapshots/seattlerb/difficult3__10.txt +++ b/test/prism/snapshots/seattlerb/difficult3__10.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,18)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,18)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,18)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,19 +16,24 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,18)) + ├── flags: ∅ ├── locals: [:a, :b, :c] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,16)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,15)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 0) │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,9)-(1,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (1,9)-(1,10) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (1,10)-(1,11)) diff --git a/test/prism/snapshots/seattlerb/difficult3__11.txt b/test/prism/snapshots/seattlerb/difficult3__11.txt index a658b091c23..c1017885d8e 100644 --- a/test/prism/snapshots/seattlerb/difficult3__11.txt +++ b/test/prism/snapshots/seattlerb/difficult3__11.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,14)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,14)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,14)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,19 +16,24 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,14)) + ├── flags: ∅ ├── locals: [:a] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,12)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 0) │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,9)-(1,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (1,9)-(1,10) = "*" │ │ │ │ └── expression: ∅ │ │ │ ├── rights: (length: 0) diff --git a/test/prism/snapshots/seattlerb/difficult3__12.txt b/test/prism/snapshots/seattlerb/difficult3__12.txt index 5aa252fe6ac..bbcfad48b4c 100644 --- a/test/prism/snapshots/seattlerb/difficult3__12.txt +++ b/test/prism/snapshots/seattlerb/difficult3__12.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,17)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,19 +16,24 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,17)) + ├── flags: ∅ ├── locals: [:a, :b] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,15)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 0) │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,9)-(1,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (1,9)-(1,10) = "*" │ │ │ │ └── expression: ∅ │ │ │ ├── rights: (length: 1) diff --git a/test/prism/snapshots/seattlerb/difficult3__6.txt b/test/prism/snapshots/seattlerb/difficult3__6.txt index a42a625be73..95d1ac39b58 100644 --- a/test/prism/snapshots/seattlerb/difficult3__6.txt +++ b/test/prism/snapshots/seattlerb/difficult3__6.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,21)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,21)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,21)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,22 +16,27 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,21)) + ├── flags: ∅ ├── locals: [:a, :b, :c, :d] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,19)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,18)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,12)-(1,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (1,12)-(1,13) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (1,13)-(1,14)) diff --git a/test/prism/snapshots/seattlerb/difficult3__7.txt b/test/prism/snapshots/seattlerb/difficult3__7.txt index b08025804ca..4640cfdb534 100644 --- a/test/prism/snapshots/seattlerb/difficult3__7.txt +++ b/test/prism/snapshots/seattlerb/difficult3__7.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,17)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,22 +16,27 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,17)) + ├── flags: ∅ ├── locals: [:a, :b] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,15)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,12)-(1,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (1,12)-(1,13) = "*" │ │ │ │ └── expression: ∅ │ │ │ ├── rights: (length: 0) diff --git a/test/prism/snapshots/seattlerb/difficult3__8.txt b/test/prism/snapshots/seattlerb/difficult3__8.txt index b2b118faef0..e19cbfc279e 100644 --- a/test/prism/snapshots/seattlerb/difficult3__8.txt +++ b/test/prism/snapshots/seattlerb/difficult3__8.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,20)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,20)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,20)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,22 +16,27 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,20)) + ├── flags: ∅ ├── locals: [:a, :b, :c] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,18)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,17)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,12)-(1,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (1,12)-(1,13) = "*" │ │ │ │ └── expression: ∅ │ │ │ ├── rights: (length: 1) diff --git a/test/prism/snapshots/seattlerb/difficult3__9.txt b/test/prism/snapshots/seattlerb/difficult3__9.txt index 85c10a4432b..2259351b41f 100644 --- a/test/prism/snapshots/seattlerb/difficult3__9.txt +++ b/test/prism/snapshots/seattlerb/difficult3__9.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,15)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,15)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,15)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :f @@ -14,19 +16,24 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,2)-(1,15)) + ├── flags: ∅ ├── locals: [:a, :b] ├── parameters: │ @ BlockParametersNode (location: (1,4)-(1,13)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,5)-(1,12)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 0) │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,9)-(1,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (1,9)-(1,10) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (1,10)-(1,11)) diff --git a/test/prism/snapshots/seattlerb/difficult4__leading_dots.txt b/test/prism/snapshots/seattlerb/difficult4__leading_dots.txt index 8307c806e62..4201ed00aad 100644 --- a/test/prism/snapshots/seattlerb/difficult4__leading_dots.txt +++ b/test/prism/snapshots/seattlerb/difficult4__leading_dots.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(2,2)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(2,2)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(2,2)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,0)-(1,1)) │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/seattlerb/difficult4__leading_dots2.txt b/test/prism/snapshots/seattlerb/difficult4__leading_dots2.txt index ee4370c0f03..8dd122ddd44 100644 --- a/test/prism/snapshots/seattlerb/difficult4__leading_dots2.txt +++ b/test/prism/snapshots/seattlerb/difficult4__leading_dots2.txt @@ -1,16 +1,18 @@ @ ProgramNode (location: (1,0)-(2,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(2,3)) + ├── flags: ∅ └── body: (length: 2) ├── @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 1 └── @ RangeNode (location: (2,0)-(2,3)) - ├── flags: ∅ + ├── flags: newline, static_literal ├── left: ∅ ├── right: │ @ IntegerNode (location: (2,2)-(2,3)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 3 └── operator_loc: (2,0)-(2,2) = ".." diff --git a/test/prism/snapshots/seattlerb/difficult6_.txt b/test/prism/snapshots/seattlerb/difficult6_.txt index bf80034fe95..fc273bda46d 100644 --- a/test/prism/snapshots/seattlerb/difficult6_.txt +++ b/test/prism/snapshots/seattlerb/difficult6_.txt @@ -1,17 +1,22 @@ @ ProgramNode (location: (1,0)-(1,25)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,25)) + ├── flags: ∅ └── body: (length: 1) └── @ LambdaNode (location: (1,0)-(1,25)) + ├── flags: newline ├── locals: [:a, :b] ├── operator_loc: (1,0)-(1,2) = "->" ├── opening_loc: (1,13)-(1,14) = "{" ├── closing_loc: (1,24)-(1,25) = "}" ├── parameters: │ @ BlockParametersNode (location: (1,2)-(1,12)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,3)-(1,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,3)-(1,4)) │ │ │ ├── flags: ∅ @@ -24,6 +29,7 @@ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ └── value: │ │ │ @ NilNode (location: (1,8)-(1,11)) + │ │ │ └── flags: static_literal │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) @@ -34,9 +40,10 @@ │ └── closing_loc: (1,11)-(1,12) = ")" └── body: @ StatementsNode (location: (1,15)-(1,23)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,15)-(1,23)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :p @@ -50,9 +57,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ LocalVariableReadNode (location: (1,18)-(1,19)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ └── @ LocalVariableReadNode (location: (1,21)-(1,22)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ └── depth: 0 │ ├── opening_loc: (1,17)-(1,18) = "[" diff --git a/test/prism/snapshots/seattlerb/difficult6__7.txt b/test/prism/snapshots/seattlerb/difficult6__7.txt index 7fe70c70332..509da6914f4 100644 --- a/test/prism/snapshots/seattlerb/difficult6__7.txt +++ b/test/prism/snapshots/seattlerb/difficult6__7.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,11)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,11)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,11)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,0)-(1,1)) │ ├── flags: variable_call, ignore_visibility @@ -25,24 +27,28 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ ParenthesesNode (location: (1,4)-(1,7)) + │ ├── flags: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,5)-(1,6)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 1 │ ├── opening_loc: (1,4)-(1,5) = "(" │ └── closing_loc: (1,6)-(1,7) = ")" ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,8)-(1,11)) + ├── flags: ∅ ├── locals: [] ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (1,9)-(1,10)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,9)-(1,10)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :c diff --git a/test/prism/snapshots/seattlerb/difficult6__8.txt b/test/prism/snapshots/seattlerb/difficult6__8.txt index 7f915e283c7..c6fece62cb4 100644 --- a/test/prism/snapshots/seattlerb/difficult6__8.txt +++ b/test/prism/snapshots/seattlerb/difficult6__8.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,12)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,12)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,12)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,0)-(1,1)) │ ├── flags: variable_call, ignore_visibility @@ -25,24 +27,28 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ ParenthesesNode (location: (1,5)-(1,8)) + │ ├── flags: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,6)-(1,7)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 1 │ ├── opening_loc: (1,5)-(1,6) = "(" │ └── closing_loc: (1,7)-(1,8) = ")" ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,9)-(1,12)) + ├── flags: ∅ ├── locals: [] ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (1,10)-(1,11)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,10)-(1,11)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :c diff --git a/test/prism/snapshots/seattlerb/difficult7_.txt b/test/prism/snapshots/seattlerb/difficult7_.txt index 40c778cf6cc..2cf03ce57e6 100644 --- a/test/prism/snapshots/seattlerb/difficult7_.txt +++ b/test/prism/snapshots/seattlerb/difficult7_.txt @@ -1,15 +1,19 @@ @ ProgramNode (location: (1,6)-(4,7)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,6)-(4,7)) + ├── flags: ∅ └── body: (length: 1) └── @ HashNode (location: (1,6)-(4,7)) + ├── flags: newline ├── opening_loc: (1,6)-(1,7) = "{" ├── elements: (length: 2) │ ├── @ AssocNode (location: (2,8)-(2,33)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ SymbolNode (location: (2,8)-(2,10)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (2,8)-(2,9) = "a" │ │ │ ├── closing_loc: (2,9)-(2,10) = ":" @@ -26,12 +30,15 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: │ │ │ @ BlockNode (location: (2,18)-(2,33)) + │ │ │ ├── flags: ∅ │ │ │ ├── locals: [] │ │ │ ├── parameters: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (2,20)-(2,31)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IfNode (location: (2,20)-(2,31)) + │ │ │ │ ├── flags: newline │ │ │ │ ├── if_keyword_loc: ∅ │ │ │ │ ├── predicate: │ │ │ │ │ @ CallNode (location: (2,20)-(2,21)) @@ -47,9 +54,10 @@ │ │ │ │ ├── then_keyword_loc: (2,22)-(2,23) = "?" │ │ │ │ ├── statements: │ │ │ │ │ @ StatementsNode (location: (2,24)-(2,27)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ CallNode (location: (2,24)-(2,27)) - │ │ │ │ │ ├── flags: ignore_visibility + │ │ │ │ │ ├── flags: newline, ignore_visibility │ │ │ │ │ ├── receiver: ∅ │ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ │ ├── name: :c @@ -58,14 +66,16 @@ │ │ │ │ │ ├── arguments: ∅ │ │ │ │ │ ├── closing_loc: (2,26)-(2,27) = ")" │ │ │ │ │ └── block: ∅ - │ │ │ │ ├── consequent: + │ │ │ │ ├── subsequent: │ │ │ │ │ @ ElseNode (location: (2,28)-(2,31)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── else_keyword_loc: (2,28)-(2,29) = ":" │ │ │ │ │ ├── statements: │ │ │ │ │ │ @ StatementsNode (location: (2,30)-(2,31)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ │ └── @ CallNode (location: (2,30)-(2,31)) - │ │ │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ │ │ ├── receiver: ∅ │ │ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ │ │ ├── name: :d @@ -80,14 +90,16 @@ │ │ │ └── closing_loc: (2,32)-(2,33) = "}" │ │ └── operator_loc: ∅ │ └── @ AssocNode (location: (3,8)-(3,14)) + │ ├── flags: static_literal │ ├── key: │ │ @ SymbolNode (location: (3,8)-(3,10)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (3,8)-(3,9) = "e" │ │ ├── closing_loc: (3,9)-(3,10) = ":" │ │ └── unescaped: "e" │ ├── value: │ │ @ NilNode (location: (3,11)-(3,14)) + │ │ └── flags: static_literal │ └── operator_loc: ∅ └── closing_loc: (4,6)-(4,7) = "}" diff --git a/test/prism/snapshots/seattlerb/do_bug.txt b/test/prism/snapshots/seattlerb/do_bug.txt index 5877b18d686..8d1a0b786ce 100644 --- a/test/prism/snapshots/seattlerb/do_bug.txt +++ b/test/prism/snapshots/seattlerb/do_bug.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ └── body: (length: 2) ├── @ CallNode (location: (1,0)-(1,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a @@ -15,12 +17,12 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,2)-(1,3)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ └── @ CallNode (location: (2,0)-(4,3)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (2,0)-(2,1)) │ ├── flags: variable_call, ignore_visibility @@ -40,11 +42,14 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (2,4)-(4,3)) + ├── flags: ∅ ├── locals: [:c] ├── parameters: │ @ BlockParametersNode (location: (2,7)-(2,10)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (2,8)-(2,9)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (2,8)-(2,9)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/do_lambda.txt b/test/prism/snapshots/seattlerb/do_lambda.txt index 4713fb3e4b7..76383b0ada0 100644 --- a/test/prism/snapshots/seattlerb/do_lambda.txt +++ b/test/prism/snapshots/seattlerb/do_lambda.txt @@ -1,15 +1,19 @@ @ ProgramNode (location: (1,0)-(1,11)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,11)) + ├── flags: ∅ └── body: (length: 1) └── @ LambdaNode (location: (1,0)-(1,11)) + ├── flags: newline ├── locals: [] ├── operator_loc: (1,0)-(1,2) = "->" ├── opening_loc: (1,5)-(1,7) = "do" ├── closing_loc: (1,8)-(1,11) = "end" ├── parameters: │ @ BlockParametersNode (location: (1,2)-(1,4)) + │ ├── flags: ∅ │ ├── parameters: ∅ │ ├── locals: (length: 0) │ ├── opening_loc: (1,2)-(1,3) = "(" diff --git a/test/prism/snapshots/seattlerb/dot2_nil__26.txt b/test/prism/snapshots/seattlerb/dot2_nil__26.txt index 104515ac3ad..fc5122055f5 100644 --- a/test/prism/snapshots/seattlerb/dot2_nil__26.txt +++ b/test/prism/snapshots/seattlerb/dot2_nil__26.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,3)) + ├── flags: ∅ └── body: (length: 1) └── @ RangeNode (location: (1,0)-(1,3)) - ├── flags: ∅ + ├── flags: newline ├── left: │ @ CallNode (location: (1,0)-(1,1)) │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/seattlerb/dot3_nil__26.txt b/test/prism/snapshots/seattlerb/dot3_nil__26.txt index ec7f57cd96f..c2277975db0 100644 --- a/test/prism/snapshots/seattlerb/dot3_nil__26.txt +++ b/test/prism/snapshots/seattlerb/dot3_nil__26.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,4)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,4)) + ├── flags: ∅ └── body: (length: 1) └── @ RangeNode (location: (1,0)-(1,4)) - ├── flags: exclude_end + ├── flags: newline, exclude_end ├── left: │ @ CallNode (location: (1,0)-(1,1)) │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/seattlerb/dstr_evstr.txt b/test/prism/snapshots/seattlerb/dstr_evstr.txt index add8ad6f5c1..143d8ff5840 100644 --- a/test/prism/snapshots/seattlerb/dstr_evstr.txt +++ b/test/prism/snapshots/seattlerb/dstr_evstr.txt @@ -1,28 +1,34 @@ @ ProgramNode (location: (1,0)-(1,12)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,12)) + ├── flags: ∅ └── body: (length: 1) └── @ InterpolatedStringNode (location: (1,0)-(1,12)) - ├── flags: ∅ + ├── flags: newline ├── opening_loc: (1,0)-(1,1) = "\"" ├── parts: (length: 2) │ ├── @ EmbeddedStatementsNode (location: (1,1)-(1,7)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (1,1)-(1,3) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (1,3)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ StringNode (location: (1,3)-(1,6)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: (1,3)-(1,4) = "'" │ │ │ ├── content_loc: (1,4)-(1,5) = "a" │ │ │ ├── closing_loc: (1,5)-(1,6) = "'" │ │ │ └── unescaped: "a" │ │ └── closing_loc: (1,6)-(1,7) = "}" │ └── @ EmbeddedStatementsNode (location: (1,7)-(1,11)) + │ ├── flags: ∅ │ ├── opening_loc: (1,7)-(1,9) = "\#{" │ ├── statements: │ │ @ StatementsNode (location: (1,9)-(1,10)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (1,9)-(1,10)) │ │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/seattlerb/dstr_evstr_empty_end.txt b/test/prism/snapshots/seattlerb/dstr_evstr_empty_end.txt index 53f97e4b363..8e3ade63c97 100644 --- a/test/prism/snapshots/seattlerb/dstr_evstr_empty_end.txt +++ b/test/prism/snapshots/seattlerb/dstr_evstr_empty_end.txt @@ -1,15 +1,20 @@ @ ProgramNode (location: (1,0)-(1,11)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,11)) + ├── flags: ∅ └── body: (length: 1) └── @ InterpolatedSymbolNode (location: (1,0)-(1,11)) + ├── flags: newline ├── opening_loc: (1,0)-(1,2) = ":\"" ├── parts: (length: 1) │ └── @ EmbeddedStatementsNode (location: (1,2)-(1,10)) + │ ├── flags: ∅ │ ├── opening_loc: (1,2)-(1,4) = "\#{" │ ├── statements: │ │ @ StatementsNode (location: (1,4)-(1,9)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (1,4)-(1,9)) │ │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/seattlerb/dstr_lex_state.txt b/test/prism/snapshots/seattlerb/dstr_lex_state.txt index c4c0ef0437d..2bdeab0834e 100644 --- a/test/prism/snapshots/seattlerb/dstr_lex_state.txt +++ b/test/prism/snapshots/seattlerb/dstr_lex_state.txt @@ -1,16 +1,20 @@ @ ProgramNode (location: (1,0)-(1,8)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,8)) + ├── flags: ∅ └── body: (length: 1) └── @ InterpolatedStringNode (location: (1,0)-(1,8)) - ├── flags: ∅ + ├── flags: newline ├── opening_loc: (1,0)-(1,1) = "\"" ├── parts: (length: 1) │ └── @ EmbeddedStatementsNode (location: (1,1)-(1,7)) + │ ├── flags: ∅ │ ├── opening_loc: (1,1)-(1,3) = "\#{" │ ├── statements: │ │ @ StatementsNode (location: (1,3)-(1,6)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (1,3)-(1,6)) │ │ ├── flags: ignore_visibility @@ -24,7 +28,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ SymbolNode (location: (1,4)-(1,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,4)-(1,5) = ":" │ │ │ ├── value_loc: (1,5)-(1,6) = "a" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/dstr_str.txt b/test/prism/snapshots/seattlerb/dstr_str.txt index 6fe07818809..7b3e0e36ad5 100644 --- a/test/prism/snapshots/seattlerb/dstr_str.txt +++ b/test/prism/snapshots/seattlerb/dstr_str.txt @@ -1,26 +1,30 @@ @ ProgramNode (location: (1,0)-(1,10)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,10)) + ├── flags: ∅ └── body: (length: 1) └── @ InterpolatedStringNode (location: (1,0)-(1,10)) - ├── flags: mutable + ├── flags: newline, static_literal, mutable ├── opening_loc: (1,0)-(1,1) = "\"" ├── parts: (length: 2) │ ├── @ EmbeddedStatementsNode (location: (1,1)-(1,7)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (1,1)-(1,3) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (1,3)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ StringNode (location: (1,3)-(1,6)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: (1,3)-(1,4) = "'" │ │ │ ├── content_loc: (1,4)-(1,5) = "a" │ │ │ ├── closing_loc: (1,5)-(1,6) = "'" │ │ │ └── unescaped: "a" │ │ └── closing_loc: (1,6)-(1,7) = "}" │ └── @ StringNode (location: (1,7)-(1,9)) - │ ├── flags: frozen + │ ├── flags: static_literal, frozen │ ├── opening_loc: ∅ │ ├── content_loc: (1,7)-(1,9) = " b" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/dsym_esc_to_sym.txt b/test/prism/snapshots/seattlerb/dsym_esc_to_sym.txt index 7b1b68131e0..4224e305e9f 100644 --- a/test/prism/snapshots/seattlerb/dsym_esc_to_sym.txt +++ b/test/prism/snapshots/seattlerb/dsym_esc_to_sym.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ SymbolNode (location: (1,0)-(1,17)) - ├── flags: forced_utf8_encoding + ├── flags: newline, static_literal, forced_utf8_encoding ├── opening_loc: (1,0)-(1,2) = ":\"" ├── value_loc: (1,2)-(1,16) = "Variet\\303\\240" ├── closing_loc: (1,16)-(1,17) = "\"" diff --git a/test/prism/snapshots/seattlerb/dsym_to_sym.txt b/test/prism/snapshots/seattlerb/dsym_to_sym.txt index eb7e435c630..7c5d2bef874 100644 --- a/test/prism/snapshots/seattlerb/dsym_to_sym.txt +++ b/test/prism/snapshots/seattlerb/dsym_to_sym.txt @@ -1,35 +1,39 @@ @ ProgramNode (location: (1,0)-(3,13)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,13)) + ├── flags: ∅ └── body: (length: 2) ├── @ AliasMethodNode (location: (1,0)-(1,17)) + │ ├── flags: newline │ ├── new_name: │ │ @ SymbolNode (location: (1,6)-(1,11)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,6)-(1,8) = ":\"" │ │ ├── value_loc: (1,8)-(1,10) = "<<" │ │ ├── closing_loc: (1,10)-(1,11) = "\"" │ │ └── unescaped: "<<" │ ├── old_name: │ │ @ SymbolNode (location: (1,12)-(1,17)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,12)-(1,14) = ":\"" │ │ ├── value_loc: (1,14)-(1,16) = ">>" │ │ ├── closing_loc: (1,16)-(1,17) = "\"" │ │ └── unescaped: ">>" │ └── keyword_loc: (1,0)-(1,5) = "alias" └── @ AliasMethodNode (location: (3,0)-(3,13)) + ├── flags: newline ├── new_name: │ @ SymbolNode (location: (3,6)-(3,9)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (3,6)-(3,7) = ":" │ ├── value_loc: (3,7)-(3,9) = "<<" │ ├── closing_loc: ∅ │ └── unescaped: "<<" ├── old_name: │ @ SymbolNode (location: (3,10)-(3,13)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (3,10)-(3,11) = ":" │ ├── value_loc: (3,11)-(3,13) = ">>" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/eq_begin_line_numbers.txt b/test/prism/snapshots/seattlerb/eq_begin_line_numbers.txt index a5fc3951d69..010ee71da04 100644 --- a/test/prism/snapshots/seattlerb/eq_begin_line_numbers.txt +++ b/test/prism/snapshots/seattlerb/eq_begin_line_numbers.txt @@ -1,11 +1,13 @@ @ ProgramNode (location: (1,0)-(6,1)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(6,1)) + ├── flags: ∅ └── body: (length: 2) ├── @ IntegerNode (location: (1,0)-(1,1)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 1 └── @ IntegerNode (location: (6,0)-(6,1)) - ├── flags: decimal + ├── flags: newline, static_literal, decimal └── value: 2 diff --git a/test/prism/snapshots/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt b/test/prism/snapshots/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt index 2103bde8cbf..5f6a3fe62ee 100644 --- a/test/prism/snapshots/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt +++ b/test/prism/snapshots/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(3,8)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,8)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(3,8)) - ├── flags: attribute_write + ├── flags: newline, attribute_write ├── receiver: │ @ CallNode (location: (1,0)-(1,1)) │ ├── flags: variable_call, ignore_visibility @@ -35,12 +37,14 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ └── @ BeginNode (location: (1,5)-(3,8)) + │ ├── flags: ∅ │ ├── begin_keyword_loc: (1,5)-(1,10) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (2,7)-(2,9)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (2,7)-(2,9)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 42 │ ├── rescue_clause: ∅ │ ├── else_clause: ∅ diff --git a/test/prism/snapshots/seattlerb/evstr_evstr.txt b/test/prism/snapshots/seattlerb/evstr_evstr.txt index 9c801299f81..c8dba1c3e55 100644 --- a/test/prism/snapshots/seattlerb/evstr_evstr.txt +++ b/test/prism/snapshots/seattlerb/evstr_evstr.txt @@ -1,16 +1,20 @@ @ ProgramNode (location: (1,0)-(1,10)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,10)) + ├── flags: ∅ └── body: (length: 1) └── @ InterpolatedStringNode (location: (1,0)-(1,10)) - ├── flags: ∅ + ├── flags: newline ├── opening_loc: (1,0)-(1,1) = "\"" ├── parts: (length: 2) │ ├── @ EmbeddedStatementsNode (location: (1,1)-(1,5)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (1,1)-(1,3) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (1,3)-(1,4)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (1,3)-(1,4)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -24,9 +28,11 @@ │ │ │ └── block: ∅ │ │ └── closing_loc: (1,4)-(1,5) = "}" │ └── @ EmbeddedStatementsNode (location: (1,5)-(1,9)) + │ ├── flags: ∅ │ ├── opening_loc: (1,5)-(1,7) = "\#{" │ ├── statements: │ │ @ StatementsNode (location: (1,7)-(1,8)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (1,7)-(1,8)) │ │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/seattlerb/evstr_str.txt b/test/prism/snapshots/seattlerb/evstr_str.txt index 54319e613c5..69a992b19a9 100644 --- a/test/prism/snapshots/seattlerb/evstr_str.txt +++ b/test/prism/snapshots/seattlerb/evstr_str.txt @@ -1,16 +1,20 @@ @ ProgramNode (location: (1,0)-(1,8)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,8)) + ├── flags: ∅ └── body: (length: 1) └── @ InterpolatedStringNode (location: (1,0)-(1,8)) - ├── flags: ∅ + ├── flags: newline ├── opening_loc: (1,0)-(1,1) = "\"" ├── parts: (length: 2) │ ├── @ EmbeddedStatementsNode (location: (1,1)-(1,5)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (1,1)-(1,3) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (1,3)-(1,4)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (1,3)-(1,4)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -24,7 +28,7 @@ │ │ │ └── block: ∅ │ │ └── closing_loc: (1,4)-(1,5) = "}" │ └── @ StringNode (location: (1,5)-(1,7)) - │ ├── flags: frozen + │ ├── flags: static_literal, frozen │ ├── opening_loc: ∅ │ ├── content_loc: (1,5)-(1,7) = " b" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/expr_not_bang.txt b/test/prism/snapshots/seattlerb/expr_not_bang.txt index 0a289ab7bed..868ef85648f 100644 --- a/test/prism/snapshots/seattlerb/expr_not_bang.txt +++ b/test/prism/snapshots/seattlerb/expr_not_bang.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(1,5)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,5)) + ├── flags: ∅ └── body: (length: 1) └── @ CallNode (location: (1,0)-(1,5)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (1,2)-(1,5)) │ ├── flags: ignore_visibility diff --git a/test/prism/snapshots/seattlerb/f_kw.txt b/test/prism/snapshots/seattlerb/f_kw.txt index 4226137925a..e2b82371b87 100644 --- a/test/prism/snapshots/seattlerb/f_kw.txt +++ b/test/prism/snapshots/seattlerb/f_kw.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,15)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,15)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,15)) + ├── flags: newline ├── name: :x ├── name_loc: (1,4)-(1,5) = "x" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,10)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -20,7 +24,7 @@ │ │ ├── name_loc: (1,6)-(1,8) = "k:" │ │ └── value: │ │ @ IntegerNode (location: (1,8)-(1,10)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 42 │ ├── keyword_rest: ∅ │ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/f_kw__required.txt b/test/prism/snapshots/seattlerb/f_kw__required.txt index f72f43e034e..c44dbbf2fc8 100644 --- a/test/prism/snapshots/seattlerb/f_kw__required.txt +++ b/test/prism/snapshots/seattlerb/f_kw__required.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,13)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,13)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,13)) + ├── flags: newline ├── name: :x ├── name_loc: (1,4)-(1,5) = "x" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,6)-(1,8)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/flip2_env_lvar.txt b/test/prism/snapshots/seattlerb/flip2_env_lvar.txt index 5a71ab6cda3..def6ffaf3a7 100644 --- a/test/prism/snapshots/seattlerb/flip2_env_lvar.txt +++ b/test/prism/snapshots/seattlerb/flip2_env_lvar.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(1,16)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,16)) + ├── flags: ∅ └── body: (length: 1) └── @ IfNode (location: (1,0)-(1,16)) + ├── flags: newline ├── if_keyword_loc: (1,0)-(1,2) = "if" ├── predicate: │ @ FlipFlopNode (location: (1,3)-(1,7)) @@ -33,5 +36,5 @@ │ └── operator_loc: (1,4)-(1,6) = ".." ├── then_keyword_loc: (1,8)-(1,12) = "then" ├── statements: ∅ - ├── consequent: ∅ + ├── subsequent: ∅ └── end_keyword_loc: (1,13)-(1,16) = "end" diff --git a/test/prism/snapshots/seattlerb/float_with_if_modifier.txt b/test/prism/snapshots/seattlerb/float_with_if_modifier.txt index 9c1da70f242..400c90b17cb 100644 --- a/test/prism/snapshots/seattlerb/float_with_if_modifier.txt +++ b/test/prism/snapshots/seattlerb/float_with_if_modifier.txt @@ -1,17 +1,23 @@ @ ProgramNode (location: (1,0)-(1,10)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,10)) + ├── flags: ∅ └── body: (length: 1) └── @ IfNode (location: (1,0)-(1,10)) + ├── flags: newline ├── if_keyword_loc: (1,3)-(1,5) = "if" ├── predicate: │ @ TrueNode (location: (1,6)-(1,10)) + │ └── flags: static_literal ├── then_keyword_loc: ∅ ├── statements: │ @ StatementsNode (location: (1,0)-(1,3)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ FloatNode (location: (1,0)-(1,3)) + │ ├── flags: newline, static_literal │ └── value: 1.0 - ├── consequent: ∅ + ├── subsequent: ∅ └── end_keyword_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/heredoc__backslash_dos_format.txt b/test/prism/snapshots/seattlerb/heredoc__backslash_dos_format.txt index 353e4c6964c..7d745587b3f 100644 --- a/test/prism/snapshots/seattlerb/heredoc__backslash_dos_format.txt +++ b/test/prism/snapshots/seattlerb/heredoc__backslash_dos_format.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(1,12)) +├── flags: ∅ ├── locals: [:str] └── statements: @ StatementsNode (location: (1,0)-(1,12)) + ├── flags: ∅ └── body: (length: 1) └── @ LocalVariableWriteNode (location: (1,0)-(1,12)) + ├── flags: newline ├── name: :str ├── depth: 0 ├── name_loc: (1,0)-(1,3) = "str" diff --git a/test/prism/snapshots/seattlerb/heredoc_backslash_nl.txt b/test/prism/snapshots/seattlerb/heredoc_backslash_nl.txt index fc4c1784fef..4c34bf6ef60 100644 --- a/test/prism/snapshots/seattlerb/heredoc_backslash_nl.txt +++ b/test/prism/snapshots/seattlerb/heredoc_backslash_nl.txt @@ -1,16 +1,18 @@ @ ProgramNode (location: (1,0)-(5,7)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(5,7)) + ├── flags: ∅ └── body: (length: 2) ├── @ StringNode (location: (1,0)-(3,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (1,0)-(1,1) = "\"" │ ├── content_loc: (1,1)-(3,0) = " why would someone do this? \\\n blah\n" │ ├── closing_loc: (3,0)-(3,1) = "\"" │ └── unescaped: " why would someone do this? blah\n" └── @ StringNode (location: (5,0)-(5,7)) - ├── flags: ∅ + ├── flags: newline ├── opening_loc: (5,0)-(5,7) = "<<-DESC" ├── content_loc: (6,0)-(8,0) = " why would someone do this? \\\n blah\n" ├── closing_loc: (8,0)-(9,0) = "DESC\n" diff --git a/test/prism/snapshots/seattlerb/heredoc_bad_hex_escape.txt b/test/prism/snapshots/seattlerb/heredoc_bad_hex_escape.txt index 2b1d776404b..1c521108c04 100644 --- a/test/prism/snapshots/seattlerb/heredoc_bad_hex_escape.txt +++ b/test/prism/snapshots/seattlerb/heredoc_bad_hex_escape.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(1,9)) +├── flags: ∅ ├── locals: [:s] └── statements: @ StatementsNode (location: (1,0)-(1,9)) + ├── flags: ∅ └── body: (length: 1) └── @ LocalVariableWriteNode (location: (1,0)-(1,9)) + ├── flags: newline ├── name: :s ├── depth: 0 ├── name_loc: (1,0)-(1,1) = "s" diff --git a/test/prism/snapshots/seattlerb/heredoc_bad_oct_escape.txt b/test/prism/snapshots/seattlerb/heredoc_bad_oct_escape.txt index 7a01f8d6d1c..9726a71822b 100644 --- a/test/prism/snapshots/seattlerb/heredoc_bad_oct_escape.txt +++ b/test/prism/snapshots/seattlerb/heredoc_bad_oct_escape.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(1,10)) +├── flags: ∅ ├── locals: [:s] └── statements: @ StatementsNode (location: (1,0)-(1,10)) + ├── flags: ∅ └── body: (length: 1) └── @ LocalVariableWriteNode (location: (1,0)-(1,10)) + ├── flags: newline ├── name: :s ├── depth: 0 ├── name_loc: (1,0)-(1,1) = "s" diff --git a/test/prism/snapshots/seattlerb/heredoc_comma_arg.txt b/test/prism/snapshots/seattlerb/heredoc_comma_arg.txt index 888ebc809a8..0a432984723 100644 --- a/test/prism/snapshots/seattlerb/heredoc_comma_arg.txt +++ b/test/prism/snapshots/seattlerb/heredoc_comma_arg.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(7,1)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(7,1)) + ├── flags: ∅ └── body: (length: 2) ├── @ ArrayNode (location: (1,0)-(2,3)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 1) │ │ └── @ StringNode (location: (1,1)-(2,1)) │ │ ├── flags: ∅ @@ -15,7 +17,7 @@ │ ├── opening_loc: (1,0)-(1,1) = "[" │ └── closing_loc: (2,2)-(2,3) = "]" └── @ ArrayNode (location: (4,0)-(7,1)) - ├── flags: ∅ + ├── flags: newline ├── elements: (length: 1) │ └── @ StringNode (location: (4,1)-(4,8)) │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/heredoc_lineno.txt b/test/prism/snapshots/seattlerb/heredoc_lineno.txt index a51ce71afe8..7dde22912e5 100644 --- a/test/prism/snapshots/seattlerb/heredoc_lineno.txt +++ b/test/prism/snapshots/seattlerb/heredoc_lineno.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(7,6)) +├── flags: ∅ ├── locals: [:c, :d] └── statements: @ StatementsNode (location: (1,0)-(7,6)) + ├── flags: ∅ └── body: (length: 2) ├── @ LocalVariableWriteNode (location: (1,0)-(1,11)) + │ ├── flags: newline │ ├── name: :c │ ├── depth: 0 │ ├── name_loc: (1,0)-(1,1) = "c" @@ -16,11 +19,12 @@ │ │ └── unescaped: "line2\nline3\nline4\n" │ └── operator_loc: (1,2)-(1,3) = "=" └── @ LocalVariableWriteNode (location: (7,0)-(7,6)) + ├── flags: newline ├── name: :d ├── depth: 0 ├── name_loc: (7,0)-(7,1) = "d" ├── value: │ @ IntegerNode (location: (7,4)-(7,6)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 42 └── operator_loc: (7,2)-(7,3) = "=" diff --git a/test/prism/snapshots/seattlerb/heredoc_nested.txt b/test/prism/snapshots/seattlerb/heredoc_nested.txt index a2322b9632e..4820ef6d4db 100644 --- a/test/prism/snapshots/seattlerb/heredoc_nested.txt +++ b/test/prism/snapshots/seattlerb/heredoc_nested.txt @@ -1,42 +1,46 @@ @ ProgramNode (location: (1,0)-(7,2)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(7,2)) + ├── flags: ∅ └── body: (length: 1) └── @ ArrayNode (location: (1,0)-(7,2)) - ├── flags: ∅ + ├── flags: newline, static_literal ├── elements: (length: 2) │ ├── @ InterpolatedStringNode (location: (1,1)-(1,4)) - │ │ ├── flags: mutable + │ │ ├── flags: static_literal, mutable │ │ ├── opening_loc: (1,1)-(1,4) = "<=" ├── @ SymbolNode (location: (77,0)-(77,3)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (77,0)-(77,1) = ":" │ ├── value_loc: (77,1)-(77,3) = ">>" │ ├── closing_loc: ∅ │ └── unescaped: ">>" ├── @ SymbolNode (location: (79,0)-(79,2)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (79,0)-(79,1) = ":" │ ├── value_loc: (79,1)-(79,2) = ">" │ ├── closing_loc: ∅ │ └── unescaped: ">" ├── @ SymbolNode (location: (81,0)-(81,4)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (81,0)-(81,1) = ":" │ ├── value_loc: (81,1)-(81,4) = "<=>" │ ├── closing_loc: ∅ │ └── unescaped: "<=>" ├── @ SymbolNode (location: (83,0)-(83,3)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (83,0)-(83,1) = ":" │ ├── value_loc: (83,1)-(83,3) = "<=" │ ├── closing_loc: ∅ │ └── unescaped: "<=" ├── @ SymbolNode (location: (85,0)-(85,3)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (85,0)-(85,1) = ":" │ ├── value_loc: (85,1)-(85,3) = "<<" │ ├── closing_loc: ∅ │ └── unescaped: "<<" ├── @ SymbolNode (location: (87,0)-(87,2)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (87,0)-(87,1) = ":" │ ├── value_loc: (87,1)-(87,2) = "<" │ ├── closing_loc: ∅ │ └── unescaped: "<" ├── @ SymbolNode (location: (89,0)-(89,9)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (89,0)-(89,1) = ":" │ ├── value_loc: (89,1)-(89,9) = "__LINE__" │ ├── closing_loc: ∅ │ └── unescaped: "__LINE__" ├── @ SymbolNode (location: (91,0)-(91,9)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (91,0)-(91,1) = ":" │ ├── value_loc: (91,1)-(91,9) = "__FILE__" │ ├── closing_loc: ∅ │ └── unescaped: "__FILE__" └── @ SymbolNode (location: (93,0)-(93,13)) - ├── flags: forced_us_ascii_encoding + ├── flags: newline, static_literal, forced_us_ascii_encoding ├── opening_loc: (93,0)-(93,1) = ":" ├── value_loc: (93,1)-(93,13) = "__ENCODING__" ├── closing_loc: ∅ diff --git a/test/prism/snapshots/ternary_operator.txt b/test/prism/snapshots/ternary_operator.txt index 0277ac88f0c..4d6a7423f92 100644 --- a/test/prism/snapshots/ternary_operator.txt +++ b/test/prism/snapshots/ternary_operator.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(15,12)) +├── flags: ∅ ├── locals: [:_a] └── statements: @ StatementsNode (location: (1,0)-(15,12)) + ├── flags: ∅ └── body: (length: 8) ├── @ IfNode (location: (1,0)-(1,9)) + │ ├── flags: newline │ ├── if_keyword_loc: ∅ │ ├── predicate: │ │ @ CallNode (location: (1,0)-(1,1)) @@ -19,9 +22,10 @@ │ ├── then_keyword_loc: (1,2)-(1,3) = "?" │ ├── statements: │ │ @ StatementsNode (location: (1,4)-(1,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (1,4)-(1,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :b @@ -30,14 +34,16 @@ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── consequent: + │ ├── subsequent: │ │ @ ElseNode (location: (1,6)-(1,9)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (1,6)-(1,7) = ":" │ │ ├── statements: │ │ │ @ StatementsNode (location: (1,8)-(1,9)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (1,8)-(1,9)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :c @@ -49,6 +55,7 @@ │ │ └── end_keyword_loc: ∅ │ └── end_keyword_loc: ∅ ├── @ IfNode (location: (3,0)-(3,27)) + │ ├── flags: newline │ ├── if_keyword_loc: ∅ │ ├── predicate: │ │ @ CallNode (location: (3,0)-(3,1)) @@ -64,8 +71,10 @@ │ ├── then_keyword_loc: (3,2)-(3,3) = "?" │ ├── statements: │ │ @ StatementsNode (location: (3,4)-(3,14)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ DefinedNode (location: (3,4)-(3,14)) + │ │ ├── flags: newline │ │ ├── lparen_loc: ∅ │ │ ├── value: │ │ │ @ CallNode (location: (3,13)-(3,14)) @@ -80,13 +89,16 @@ │ │ │ └── block: ∅ │ │ ├── rparen_loc: ∅ │ │ └── keyword_loc: (3,4)-(3,12) = "defined?" - │ ├── consequent: + │ ├── subsequent: │ │ @ ElseNode (location: (3,15)-(3,27)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (3,15)-(3,16) = ":" │ │ ├── statements: │ │ │ @ StatementsNode (location: (3,17)-(3,27)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ DefinedNode (location: (3,17)-(3,27)) + │ │ │ ├── flags: newline │ │ │ ├── lparen_loc: ∅ │ │ │ ├── value: │ │ │ │ @ CallNode (location: (3,26)-(3,27)) @@ -104,6 +116,7 @@ │ │ └── end_keyword_loc: ∅ │ └── end_keyword_loc: ∅ ├── @ IfNode (location: (5,0)-(5,15)) + │ ├── flags: newline │ ├── if_keyword_loc: ∅ │ ├── predicate: │ │ @ CallNode (location: (5,0)-(5,6)) @@ -119,18 +132,24 @@ │ ├── then_keyword_loc: (5,6)-(5,7) = "?" │ ├── statements: │ │ @ StatementsNode (location: (5,7)-(5,11)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ TrueNode (location: (5,7)-(5,11)) - │ ├── consequent: + │ │ └── flags: newline, static_literal + │ ├── subsequent: │ │ @ ElseNode (location: (5,11)-(5,15)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (5,11)-(5,12) = ":" │ │ ├── statements: │ │ │ @ StatementsNode (location: (5,12)-(5,15)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ NilNode (location: (5,12)-(5,15)) + │ │ │ └── flags: newline, static_literal │ │ └── end_keyword_loc: ∅ │ └── end_keyword_loc: ∅ ├── @ IfNode (location: (7,0)-(7,16)) + │ ├── flags: newline │ ├── if_keyword_loc: ∅ │ ├── predicate: │ │ @ CallNode (location: (7,0)-(7,6)) @@ -146,18 +165,24 @@ │ ├── then_keyword_loc: (7,6)-(7,7) = "?" │ ├── statements: │ │ @ StatementsNode (location: (7,7)-(7,12)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ FalseNode (location: (7,7)-(7,12)) - │ ├── consequent: + │ │ └── flags: newline, static_literal + │ ├── subsequent: │ │ @ ElseNode (location: (7,12)-(7,16)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (7,12)-(7,13) = ":" │ │ ├── statements: │ │ │ @ StatementsNode (location: (7,13)-(7,16)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ NilNode (location: (7,13)-(7,16)) + │ │ │ └── flags: newline, static_literal │ │ └── end_keyword_loc: ∅ │ └── end_keyword_loc: ∅ ├── @ IfNode (location: (9,0)-(9,14)) + │ ├── flags: newline │ ├── if_keyword_loc: ∅ │ ├── predicate: │ │ @ CallNode (location: (9,0)-(9,6)) @@ -173,18 +198,24 @@ │ ├── then_keyword_loc: (9,6)-(9,7) = "?" │ ├── statements: │ │ @ StatementsNode (location: (9,7)-(9,10)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NilNode (location: (9,7)-(9,10)) - │ ├── consequent: + │ │ └── flags: newline, static_literal + │ ├── subsequent: │ │ @ ElseNode (location: (9,10)-(9,14)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (9,10)-(9,11) = ":" │ │ ├── statements: │ │ │ @ StatementsNode (location: (9,11)-(9,14)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ NilNode (location: (9,11)-(9,14)) + │ │ │ └── flags: newline, static_literal │ │ └── end_keyword_loc: ∅ │ └── end_keyword_loc: ∅ ├── @ IfNode (location: (11,0)-(11,10)) + │ ├── flags: newline │ ├── if_keyword_loc: ∅ │ ├── predicate: │ │ @ CallNode (location: (11,0)-(11,2)) @@ -200,18 +231,24 @@ │ ├── then_keyword_loc: (11,2)-(11,3) = "?" │ ├── statements: │ │ @ StatementsNode (location: (11,3)-(11,6)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NilNode (location: (11,3)-(11,6)) - │ ├── consequent: + │ │ └── flags: newline, static_literal + │ ├── subsequent: │ │ @ ElseNode (location: (11,6)-(11,10)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (11,6)-(11,7) = ":" │ │ ├── statements: │ │ │ @ StatementsNode (location: (11,7)-(11,10)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ NilNode (location: (11,7)-(11,10)) + │ │ │ └── flags: newline, static_literal │ │ └── end_keyword_loc: ∅ │ └── end_keyword_loc: ∅ ├── @ IfNode (location: (13,0)-(13,14)) + │ ├── flags: newline │ ├── if_keyword_loc: ∅ │ ├── predicate: │ │ @ CallNode (location: (13,0)-(13,1)) @@ -227,9 +264,10 @@ │ ├── then_keyword_loc: (13,2)-(13,3) = "?" │ ├── statements: │ │ @ StatementsNode (location: (13,3)-(13,7)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (13,3)-(13,7)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :var1 @@ -238,14 +276,16 @@ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── consequent: + │ ├── subsequent: │ │ @ ElseNode (location: (13,8)-(13,14)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (13,8)-(13,9) = ":" │ │ ├── statements: │ │ │ @ StatementsNode (location: (13,10)-(13,14)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (13,10)-(13,14)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :var2 @@ -257,6 +297,7 @@ │ │ └── end_keyword_loc: ∅ │ └── end_keyword_loc: ∅ └── @ IfNode (location: (15,0)-(15,12)) + ├── flags: newline ├── if_keyword_loc: ∅ ├── predicate: │ @ CallNode (location: (15,0)-(15,4)) @@ -272,24 +313,28 @@ ├── then_keyword_loc: (15,4)-(15,5) = "?" ├── statements: │ @ StatementsNode (location: (15,5)-(15,10)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ LocalVariableWriteNode (location: (15,5)-(15,10)) + │ ├── flags: newline │ ├── name: :_a │ ├── depth: 0 │ ├── name_loc: (15,5)-(15,7) = "_a" │ ├── value: │ │ @ IntegerNode (location: (15,9)-(15,10)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ └── operator_loc: (15,8)-(15,9) = "=" - ├── consequent: + ├── subsequent: │ @ ElseNode (location: (15,10)-(15,12)) + │ ├── flags: ∅ │ ├── else_keyword_loc: (15,10)-(15,11) = ":" │ ├── statements: │ │ @ StatementsNode (location: (15,11)-(15,12)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (15,11)-(15,12)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 1 │ └── end_keyword_loc: ∅ └── end_keyword_loc: ∅ diff --git a/test/prism/snapshots/tilde_heredocs.txt b/test/prism/snapshots/tilde_heredocs.txt index f50f915a648..dc6321ce1a5 100644 --- a/test/prism/snapshots/tilde_heredocs.txt +++ b/test/prism/snapshots/tilde_heredocs.txt @@ -1,403 +1,419 @@ @ ProgramNode (location: (1,0)-(94,6)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(94,6)) + ├── flags: ∅ └── body: (length: 19) ├── @ InterpolatedStringNode (location: (1,0)-(1,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (1,0)-(1,6) = "<<~EOF" │ ├── parts: (length: 4) │ │ ├── @ StringNode (location: (2,0)-(3,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (2,0)-(3,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: " a\n" │ │ ├── @ EmbeddedStatementsNode (location: (3,0)-(3,4)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (3,0)-(3,2) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (3,2)-(3,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (3,2)-(3,3)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (3,3)-(3,4) = "}" │ │ ├── @ StringNode (location: (3,4)-(4,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (3,4)-(4,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" │ │ └── @ StringNode (location: (4,0)-(5,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (4,0)-(5,0) = " a\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: " a\n" │ └── closing_loc: (5,0)-(6,0) = "EOF\n" ├── @ StringNode (location: (7,0)-(7,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (7,0)-(7,6) = "<<~EOF" │ ├── content_loc: (8,0)-(9,0) = " a\n" │ ├── closing_loc: (9,0)-(10,0) = "EOF\n" │ └── unescaped: "a\n" ├── @ InterpolatedStringNode (location: (11,0)-(11,6)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── opening_loc: (11,0)-(11,6) = "<<~EOF" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (12,0)-(13,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (12,0)-(13,0) = "\ta\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\ta\n" │ │ ├── @ StringNode (location: (13,0)-(14,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (13,0)-(14,0) = " b\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b\n" │ │ └── @ StringNode (location: (14,0)-(15,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (14,0)-(15,0) = "\t\tc\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\t\tc\n" │ └── closing_loc: (15,0)-(16,0) = "EOF\n" ├── @ InterpolatedStringNode (location: (17,0)-(17,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (17,0)-(17,6) = "<<~EOF" │ ├── parts: (length: 2) │ │ ├── @ EmbeddedStatementsNode (location: (18,2)-(18,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (18,2)-(18,4) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (18,4)-(18,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (18,4)-(18,5)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (18,5)-(18,6) = "}" │ │ └── @ StringNode (location: (18,6)-(19,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (18,6)-(19,0) = " a\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: " a\n" │ └── closing_loc: (19,0)-(20,0) = "EOF\n" ├── @ InterpolatedStringNode (location: (21,0)-(21,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (21,0)-(21,6) = "<<~EOF" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (22,0)-(22,4)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (22,0)-(22,4) = " a " │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a " │ │ ├── @ EmbeddedStatementsNode (location: (22,4)-(22,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (22,4)-(22,6) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (22,6)-(22,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (22,6)-(22,7)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (22,7)-(22,8) = "}" │ │ └── @ StringNode (location: (22,8)-(23,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (22,8)-(23,0) = "\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\n" │ └── closing_loc: (23,0)-(24,0) = "EOF\n" ├── @ InterpolatedStringNode (location: (25,0)-(25,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (25,0)-(25,6) = "<<~EOF" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (26,0)-(27,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (26,0)-(27,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: " a\n" │ │ ├── @ EmbeddedStatementsNode (location: (27,1)-(27,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (27,1)-(27,3) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (27,3)-(27,4)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (27,3)-(27,4)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (27,4)-(27,5) = "}" │ │ └── @ StringNode (location: (27,5)-(28,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (27,5)-(28,0) = "\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\n" │ └── closing_loc: (28,0)-(29,0) = "EOF\n" ├── @ InterpolatedStringNode (location: (30,0)-(30,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (30,0)-(30,6) = "<<~EOF" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (31,0)-(32,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (31,0)-(32,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a\n" │ │ ├── @ EmbeddedStatementsNode (location: (32,2)-(32,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (32,2)-(32,4) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (32,4)-(32,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (32,4)-(32,5)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (32,5)-(32,6) = "}" │ │ └── @ StringNode (location: (32,6)-(33,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (32,6)-(33,0) = "\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\n" │ └── closing_loc: (33,0)-(34,0) = "EOF\n" ├── @ InterpolatedStringNode (location: (35,0)-(35,6)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── opening_loc: (35,0)-(35,6) = "<<~EOF" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (36,0)-(37,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (36,0)-(37,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a\n" │ │ └── @ StringNode (location: (37,0)-(38,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (37,0)-(38,0) = " b\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b\n" │ └── closing_loc: (38,0)-(39,0) = "EOF\n" ├── @ InterpolatedStringNode (location: (40,0)-(40,6)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── opening_loc: (40,0)-(40,6) = "<<~EOF" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (41,0)-(42,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (41,0)-(42,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a\n" │ │ └── @ StringNode (location: (42,0)-(43,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (42,0)-(43,0) = " b\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: " b\n" │ └── closing_loc: (43,0)-(44,0) = "EOF\n" ├── @ InterpolatedStringNode (location: (45,0)-(45,6)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── opening_loc: (45,0)-(45,6) = "<<~EOF" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (46,0)-(47,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (46,0)-(47,0) = "\t\t\ta\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\ta\n" │ │ └── @ StringNode (location: (47,0)-(48,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (47,0)-(48,0) = "\t\tb\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b\n" │ └── closing_loc: (48,0)-(49,0) = "EOF\n" ├── @ StringNode (location: (50,0)-(50,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (50,0)-(50,8) = "<<~'EOF'" │ ├── content_loc: (51,0)-(52,0) = " a \#{1}\n" │ ├── closing_loc: (52,0)-(53,0) = "EOF\n" │ └── unescaped: "a \#{1}\n" ├── @ InterpolatedStringNode (location: (54,0)-(54,6)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── opening_loc: (54,0)-(54,6) = "<<~EOF" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (55,0)-(56,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (55,0)-(56,0) = "\ta\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a\n" │ │ └── @ StringNode (location: (56,0)-(57,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (56,0)-(57,0) = "\t b\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: " b\n" │ └── closing_loc: (57,0)-(58,0) = "EOF\n" ├── @ InterpolatedStringNode (location: (59,0)-(59,6)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── opening_loc: (59,0)-(59,6) = "<<~EOF" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (60,0)-(61,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (60,0)-(61,0) = "\t a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: " a\n" │ │ └── @ StringNode (location: (61,0)-(62,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (61,0)-(62,0) = "\tb\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b\n" │ └── closing_loc: (62,0)-(63,0) = "EOF\n" ├── @ InterpolatedStringNode (location: (64,0)-(64,6)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── opening_loc: (64,0)-(64,6) = "<<~EOF" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (65,0)-(66,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (65,0)-(66,0) = " \ta\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a\n" │ │ └── @ StringNode (location: (66,0)-(67,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (66,0)-(67,0) = " b\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b\n" │ └── closing_loc: (67,0)-(68,0) = "EOF\n" ├── @ InterpolatedStringNode (location: (69,0)-(69,6)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── opening_loc: (69,0)-(69,6) = "<<~EOF" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (70,0)-(71,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (70,0)-(71,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a\n" │ │ ├── @ StringNode (location: (71,0)-(72,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (71,0)-(72,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" │ │ └── @ StringNode (location: (72,0)-(73,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (72,0)-(73,0) = " b\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b\n" │ └── closing_loc: (73,0)-(74,0) = "EOF\n" ├── @ InterpolatedStringNode (location: (75,0)-(75,6)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── opening_loc: (75,0)-(75,6) = "<<~EOF" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (76,0)-(77,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (76,0)-(77,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a\n" │ │ ├── @ StringNode (location: (77,0)-(78,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (77,0)-(78,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" │ │ └── @ StringNode (location: (78,0)-(79,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (78,0)-(79,0) = " b\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b\n" │ └── closing_loc: (79,0)-(80,0) = "EOF\n" ├── @ InterpolatedStringNode (location: (81,0)-(81,6)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── opening_loc: (81,0)-(81,6) = "<<~EOF" │ ├── parts: (length: 5) │ │ ├── @ StringNode (location: (82,0)-(83,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (82,0)-(83,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a\n" │ │ ├── @ StringNode (location: (83,0)-(84,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (83,0)-(84,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" │ │ ├── @ StringNode (location: (84,0)-(85,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (84,0)-(85,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" │ │ ├── @ StringNode (location: (85,0)-(86,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (85,0)-(86,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" │ │ └── @ StringNode (location: (86,0)-(87,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (86,0)-(87,0) = " b\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b\n" │ └── closing_loc: (87,0)-(88,0) = "EOF\n" ├── @ InterpolatedStringNode (location: (89,0)-(89,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (89,0)-(89,6) = "<<~EOF" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (90,0)-(91,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (90,0)-(91,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" │ │ ├── @ EmbeddedStatementsNode (location: (91,2)-(91,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (91,2)-(91,4) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (91,4)-(91,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (91,4)-(91,5)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (91,5)-(91,6) = "}" │ │ └── @ StringNode (location: (91,6)-(92,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (91,6)-(92,0) = "a\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a\n" │ └── closing_loc: (92,0)-(93,0) = " EOF\n" └── @ InterpolatedStringNode (location: (94,0)-(94,6)) - ├── flags: ∅ + ├── flags: newline ├── opening_loc: (94,0)-(94,6) = "<<~EOT" ├── parts: (length: 3) │ ├── @ EmbeddedStatementsNode (location: (95,2)-(95,6)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (95,2)-(95,4) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (95,4)-(95,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (95,4)-(95,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── closing_loc: (95,5)-(95,6) = "}" │ ├── @ StringNode (location: (95,6)-(96,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (95,6)-(96,0) = "\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\n" │ └── @ StringNode (location: (96,0)-(97,0)) - │ ├── flags: frozen + │ ├── flags: static_literal, frozen │ ├── opening_loc: ∅ │ ├── content_loc: (96,0)-(97,0) = "\tb\n" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/undef.txt b/test/prism/snapshots/undef.txt index e59ace92f5f..7491fc4c953 100644 --- a/test/prism/snapshots/undef.txt +++ b/test/prism/snapshots/undef.txt @@ -1,115 +1,129 @@ @ ProgramNode (location: (1,0)-(17,14)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(17,14)) + ├── flags: ∅ └── body: (length: 9) ├── @ UndefNode (location: (1,0)-(1,7)) + │ ├── flags: newline │ ├── names: (length: 1) │ │ └── @ SymbolNode (location: (1,6)-(1,7)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,6)-(1,7) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ └── keyword_loc: (1,0)-(1,5) = "undef" ├── @ UndefNode (location: (3,0)-(3,10)) + │ ├── flags: newline │ ├── names: (length: 2) │ │ ├── @ SymbolNode (location: (3,6)-(3,7)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (3,6)-(3,7) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (3,9)-(3,10)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (3,9)-(3,10) = "b" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b" │ └── keyword_loc: (3,0)-(3,5) = "undef" ├── @ UndefNode (location: (5,0)-(5,8)) + │ ├── flags: newline │ ├── names: (length: 1) │ │ └── @ SymbolNode (location: (5,6)-(5,8)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (5,6)-(5,8) = "if" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "if" │ └── keyword_loc: (5,0)-(5,5) = "undef" ├── @ UndefNode (location: (7,0)-(7,9)) + │ ├── flags: newline │ ├── names: (length: 1) │ │ └── @ SymbolNode (location: (7,6)-(7,9)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (7,6)-(7,9) = "<=>" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "<=>" │ └── keyword_loc: (7,0)-(7,5) = "undef" ├── @ UndefNode (location: (9,0)-(9,8)) + │ ├── flags: newline │ ├── names: (length: 1) │ │ └── @ SymbolNode (location: (9,6)-(9,8)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (9,6)-(9,7) = ":" │ │ ├── value_loc: (9,7)-(9,8) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ └── keyword_loc: (9,0)-(9,5) = "undef" ├── @ UndefNode (location: (11,0)-(11,16)) + │ ├── flags: newline │ ├── names: (length: 3) │ │ ├── @ SymbolNode (location: (11,6)-(11,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (11,6)-(11,7) = ":" │ │ │ ├── value_loc: (11,7)-(11,8) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ ├── @ SymbolNode (location: (11,10)-(11,12)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (11,10)-(11,11) = ":" │ │ │ ├── value_loc: (11,11)-(11,12) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" │ │ └── @ SymbolNode (location: (11,14)-(11,16)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (11,14)-(11,15) = ":" │ │ ├── value_loc: (11,15)-(11,16) = "c" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "c" │ └── keyword_loc: (11,0)-(11,5) = "undef" ├── @ UndefNode (location: (13,0)-(13,12)) + │ ├── flags: newline │ ├── names: (length: 1) │ │ └── @ SymbolNode (location: (13,6)-(13,12)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (13,6)-(13,8) = ":'" │ │ ├── value_loc: (13,8)-(13,11) = "abc" │ │ ├── closing_loc: (13,11)-(13,12) = "'" │ │ └── unescaped: "abc" │ └── keyword_loc: (13,0)-(13,5) = "undef" ├── @ UndefNode (location: (15,0)-(15,16)) + │ ├── flags: newline │ ├── names: (length: 1) │ │ └── @ InterpolatedSymbolNode (location: (15,6)-(15,16)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (15,6)-(15,8) = ":\"" │ │ ├── parts: (length: 2) │ │ │ ├── @ StringNode (location: (15,8)-(15,11)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (15,8)-(15,11) = "abc" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "abc" │ │ │ └── @ EmbeddedStatementsNode (location: (15,11)-(15,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (15,11)-(15,13) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (15,13)-(15,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (15,13)-(15,14)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (15,14)-(15,15) = "}" │ │ └── closing_loc: (15,15)-(15,16) = "\"" │ └── keyword_loc: (15,0)-(15,5) = "undef" └── @ UndefNode (location: (17,0)-(17,14)) + ├── flags: newline ├── names: (length: 1) │ └── @ SymbolNode (location: (17,6)-(17,14)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: ∅ │ ├── value_loc: (17,6)-(17,14) = "Constant" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unescaping.txt b/test/prism/snapshots/unescaping.txt index 456ef226d07..822fbe7d8f2 100644 --- a/test/prism/snapshots/unescaping.txt +++ b/test/prism/snapshots/unescaping.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(7,7)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(7,7)) + ├── flags: ∅ └── body: (length: 4) ├── @ ArrayNode (location: (1,0)-(1,10)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 1) │ │ └── @ StringNode (location: (1,1)-(1,9)) │ │ ├── flags: ∅ @@ -15,19 +17,19 @@ │ ├── opening_loc: (1,0)-(1,1) = "[" │ └── closing_loc: (1,9)-(1,10) = "]" ├── @ RegularExpressionNode (location: (3,0)-(3,8)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (3,0)-(3,1) = "/" │ ├── content_loc: (3,1)-(3,7) = "\\c\#{1}" │ ├── closing_loc: (3,7)-(3,8) = "/" │ └── unescaped: "\\x03{1}" ├── @ StringNode (location: (5,0)-(5,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (5,0)-(5,1) = "\"" │ ├── content_loc: (5,1)-(5,7) = "\\c\#{1}" │ ├── closing_loc: (5,7)-(5,8) = "\"" │ └── unescaped: "\u0003{1}" └── @ StringNode (location: (7,0)-(7,7)) - ├── flags: ∅ + ├── flags: newline ├── opening_loc: (7,0)-(7,7) = "<<~HERE" ├── content_loc: (8,0)-(9,0) = " \\c\#{1}\n" ├── closing_loc: (9,0)-(10,0) = "HERE\n" diff --git a/test/prism/snapshots/unless.txt b/test/prism/snapshots/unless.txt index 6c4aaf66a5d..9e62b0c0a96 100644 --- a/test/prism/snapshots/unless.txt +++ b/test/prism/snapshots/unless.txt @@ -1,58 +1,71 @@ @ ProgramNode (location: (1,0)-(14,22)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(14,22)) + ├── flags: ∅ └── body: (length: 7) ├── @ UnlessNode (location: (1,0)-(1,19)) + │ ├── flags: newline │ ├── keyword_loc: (1,0)-(1,6) = "unless" │ ├── predicate: │ │ @ TrueNode (location: (1,7)-(1,11)) + │ │ └── flags: static_literal │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (1,13)-(1,14)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,13)-(1,14)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 1 - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ └── end_keyword_loc: (1,16)-(1,19) = "end" ├── @ UnlessNode (location: (3,0)-(4,12)) + │ ├── flags: newline │ ├── keyword_loc: (3,0)-(3,6) = "unless" │ ├── predicate: │ │ @ TrueNode (location: (3,7)-(3,11)) + │ │ └── flags: static_literal │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (4,0)-(4,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (4,0)-(4,1)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 1 - │ ├── consequent: + │ ├── else_clause: │ │ @ ElseNode (location: (4,2)-(4,12)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (4,2)-(4,6) = "else" │ │ ├── statements: │ │ │ @ StatementsNode (location: (4,7)-(4,8)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (4,7)-(4,8)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: newline, static_literal, decimal │ │ │ └── value: 2 │ │ └── end_keyword_loc: (4,9)-(4,12) = "end" │ └── end_keyword_loc: (4,9)-(4,12) = "end" ├── @ UnlessNode (location: (6,0)-(6,13)) + │ ├── flags: newline │ ├── keyword_loc: (6,2)-(6,8) = "unless" │ ├── predicate: │ │ @ TrueNode (location: (6,9)-(6,13)) + │ │ └── flags: static_literal │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (6,0)-(6,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (6,0)-(6,1)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 1 - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ └── end_keyword_loc: ∅ ├── @ CallNode (location: (8,0)-(8,25)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -62,28 +75,34 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (8,4)-(8,25)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (8,6)-(8,23)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ UnlessNode (location: (8,6)-(8,23)) + │ │ ├── flags: newline │ │ ├── keyword_loc: (8,12)-(8,18) = "unless" │ │ ├── predicate: │ │ │ @ TrueNode (location: (8,19)-(8,23)) + │ │ │ └── flags: static_literal │ │ ├── then_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (8,6)-(8,11)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ BreakNode (location: (8,6)-(8,11)) + │ │ │ ├── flags: newline │ │ │ ├── arguments: ∅ │ │ │ └── keyword_loc: (8,6)-(8,11) = "break" - │ │ ├── consequent: ∅ + │ │ ├── else_clause: ∅ │ │ └── end_keyword_loc: ∅ │ ├── opening_loc: (8,4)-(8,5) = "{" │ └── closing_loc: (8,24)-(8,25) = "}" ├── @ CallNode (location: (10,0)-(10,24)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :tap @@ -93,41 +112,51 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (10,4)-(10,24)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (10,6)-(10,22)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ UnlessNode (location: (10,6)-(10,22)) + │ │ ├── flags: newline │ │ ├── keyword_loc: (10,11)-(10,17) = "unless" │ │ ├── predicate: │ │ │ @ TrueNode (location: (10,18)-(10,22)) + │ │ │ └── flags: static_literal │ │ ├── then_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (10,6)-(10,10)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ NextNode (location: (10,6)-(10,10)) + │ │ │ ├── flags: newline │ │ │ ├── arguments: ∅ │ │ │ └── keyword_loc: (10,6)-(10,10) = "next" - │ │ ├── consequent: ∅ + │ │ ├── else_clause: ∅ │ │ └── end_keyword_loc: ∅ │ ├── opening_loc: (10,4)-(10,5) = "{" │ └── closing_loc: (10,23)-(10,24) = "}" ├── @ UnlessNode (location: (12,0)-(12,18)) + │ ├── flags: newline │ ├── keyword_loc: (12,7)-(12,13) = "unless" │ ├── predicate: │ │ @ TrueNode (location: (12,14)-(12,18)) + │ │ └── flags: static_literal │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (12,0)-(12,6)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ ReturnNode (location: (12,0)-(12,6)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── keyword_loc: (12,0)-(12,6) = "return" │ │ └── arguments: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ └── end_keyword_loc: ∅ └── @ UnlessNode (location: (14,0)-(14,22)) + ├── flags: newline ├── keyword_loc: (14,11)-(14,17) = "unless" ├── predicate: │ @ CallNode (location: (14,18)-(14,22)) @@ -143,9 +172,10 @@ ├── then_keyword_loc: ∅ ├── statements: │ @ StatementsNode (location: (14,0)-(14,10)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (14,0)-(14,10)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -156,18 +186,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (14,4)-(14,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (14,4)-(14,5) = ":" │ │ │ ├── value_loc: (14,5)-(14,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (14,8)-(14,10)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (14,8)-(14,9) = ":" │ │ ├── value_loc: (14,9)-(14,10) = "b" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ └── end_keyword_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/alias.txt b/test/prism/snapshots/unparser/corpus/literal/alias.txt index 18ddc86d4f4..6ce892b54d0 100644 --- a/test/prism/snapshots/unparser/corpus/literal/alias.txt +++ b/test/prism/snapshots/unparser/corpus/literal/alias.txt @@ -1,27 +1,33 @@ @ ProgramNode (location: (1,0)-(2,15)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(2,15)) + ├── flags: ∅ └── body: (length: 2) ├── @ AliasGlobalVariableNode (location: (1,0)-(1,15)) + │ ├── flags: newline │ ├── new_name: │ │ @ GlobalVariableReadNode (location: (1,6)-(1,10)) + │ │ ├── flags: ∅ │ │ └── name: :$foo │ ├── old_name: │ │ @ GlobalVariableReadNode (location: (1,11)-(1,15)) + │ │ ├── flags: ∅ │ │ └── name: :$bar │ └── keyword_loc: (1,0)-(1,5) = "alias" └── @ AliasMethodNode (location: (2,0)-(2,15)) + ├── flags: newline ├── new_name: │ @ SymbolNode (location: (2,6)-(2,10)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (2,6)-(2,7) = ":" │ ├── value_loc: (2,7)-(2,10) = "foo" │ ├── closing_loc: ∅ │ └── unescaped: "foo" ├── old_name: │ @ SymbolNode (location: (2,11)-(2,15)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (2,11)-(2,12) = ":" │ ├── value_loc: (2,12)-(2,15) = "bar" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/assignment.txt b/test/prism/snapshots/unparser/corpus/literal/assignment.txt index 7d3cc389c68..4e4ed86e7b6 100644 --- a/test/prism/snapshots/unparser/corpus/literal/assignment.txt +++ b/test/prism/snapshots/unparser/corpus/literal/assignment.txt @@ -1,21 +1,27 @@ @ ProgramNode (location: (1,0)-(51,17)) +├── flags: ∅ ├── locals: [:a, :b, :foo, :c, :x] └── statements: @ StatementsNode (location: (1,0)-(51,17)) + ├── flags: ∅ └── body: (length: 43) ├── @ GlobalVariableWriteNode (location: (1,0)-(1,6)) + │ ├── flags: newline │ ├── name: :$a │ ├── name_loc: (1,0)-(1,2) = "$a" │ ├── value: │ │ @ IntegerNode (location: (1,5)-(1,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (1,3)-(1,4) = "=" ├── @ MultiWriteNode (location: (2,0)-(2,17)) + │ ├── flags: newline │ ├── lefts: (length: 2) │ │ ├── @ GlobalVariableTargetNode (location: (2,1)-(2,3)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :$a │ │ └── @ GlobalVariableTargetNode (location: (2,5)-(2,7)) + │ │ ├── flags: ∅ │ │ └── name: :$b │ ├── rest: ∅ │ ├── rights: (length: 0) @@ -24,29 +30,34 @@ │ ├── operator_loc: (2,9)-(2,10) = "=" │ └── value: │ @ ArrayNode (location: (2,11)-(2,17)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (2,12)-(2,13)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (2,15)-(2,16)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: (2,11)-(2,12) = "[" │ └── closing_loc: (2,16)-(2,17) = "]" ├── @ MultiWriteNode (location: (3,0)-(3,13)) + │ ├── flags: newline │ ├── lefts: (length: 2) │ │ ├── @ MultiTargetNode (location: (3,1)-(3,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ LocalVariableTargetNode (location: (3,2)-(3,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ └── depth: 0 │ │ │ ├── rest: │ │ │ │ @ ImplicitRestNode (location: (3,3)-(3,4)) + │ │ │ │ └── flags: ∅ │ │ │ ├── rights: (length: 0) │ │ │ ├── lparen_loc: (3,1)-(3,2) = "(" │ │ │ └── rparen_loc: (3,4)-(3,5) = ")" │ │ └── @ LocalVariableTargetNode (location: (3,7)-(3,8)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ └── depth: 0 │ ├── rest: ∅ @@ -56,15 +67,18 @@ │ ├── operator_loc: (3,10)-(3,11) = "=" │ └── value: │ @ IntegerNode (location: (3,12)-(3,13)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ MultiWriteNode (location: (4,0)-(4,9)) + │ ├── flags: newline │ ├── lefts: (length: 0) │ ├── rest: │ │ @ SplatNode (location: (4,1)-(4,3)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (4,1)-(4,2) = "*" │ │ └── expression: │ │ @ LocalVariableTargetNode (location: (4,2)-(4,3)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── rights: (length: 0) @@ -73,17 +87,20 @@ │ ├── operator_loc: (4,5)-(4,6) = "=" │ └── value: │ @ ArrayNode (location: (4,7)-(4,9)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 0) │ ├── opening_loc: (4,7)-(4,8) = "[" │ └── closing_loc: (4,8)-(4,9) = "]" ├── @ MultiWriteNode (location: (5,0)-(5,15)) + │ ├── flags: newline │ ├── lefts: (length: 0) │ ├── rest: │ │ @ SplatNode (location: (5,1)-(5,5)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (5,1)-(5,2) = "*" │ │ └── expression: │ │ @ LocalVariableTargetNode (location: (5,2)-(5,5)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── depth: 0 │ ├── rights: (length: 0) @@ -92,21 +109,24 @@ │ ├── operator_loc: (5,7)-(5,8) = "=" │ └── value: │ @ ArrayNode (location: (5,9)-(5,15)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (5,10)-(5,11)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (5,13)-(5,14)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: (5,9)-(5,10) = "[" │ └── closing_loc: (5,14)-(5,15) = "]" ├── @ MultiWriteNode (location: (6,0)-(6,19)) + │ ├── flags: newline │ ├── lefts: (length: 2) │ │ ├── @ ClassVariableTargetNode (location: (6,1)-(6,4)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :@@a │ │ └── @ ClassVariableTargetNode (location: (6,6)-(6,9)) + │ │ ├── flags: ∅ │ │ └── name: :@@b │ ├── rest: ∅ │ ├── rights: (length: 0) @@ -115,21 +135,24 @@ │ ├── operator_loc: (6,11)-(6,12) = "=" │ └── value: │ @ ArrayNode (location: (6,13)-(6,19)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (6,14)-(6,15)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (6,17)-(6,18)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: (6,13)-(6,14) = "[" │ └── closing_loc: (6,18)-(6,19) = "]" ├── @ MultiWriteNode (location: (7,0)-(7,17)) + │ ├── flags: newline │ ├── lefts: (length: 2) │ │ ├── @ InstanceVariableTargetNode (location: (7,1)-(7,3)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :@a │ │ └── @ InstanceVariableTargetNode (location: (7,5)-(7,7)) + │ │ ├── flags: ∅ │ │ └── name: :@b │ ├── rest: ∅ │ ├── rights: (length: 0) @@ -138,27 +161,32 @@ │ ├── operator_loc: (7,9)-(7,10) = "=" │ └── value: │ @ ArrayNode (location: (7,11)-(7,17)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (7,12)-(7,13)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (7,15)-(7,16)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: (7,11)-(7,12) = "[" │ └── closing_loc: (7,16)-(7,17) = "]" ├── @ MultiWriteNode (location: (8,0)-(8,25)) + │ ├── flags: newline │ ├── lefts: (length: 2) │ │ ├── @ LocalVariableTargetNode (location: (8,1)-(8,2)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ └── @ MultiTargetNode (location: (8,4)-(8,10)) + │ │ ├── flags: ∅ │ │ ├── lefts: (length: 2) │ │ │ ├── @ LocalVariableTargetNode (location: (8,5)-(8,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :b │ │ │ │ └── depth: 0 │ │ │ └── @ LocalVariableTargetNode (location: (8,8)-(8,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ └── depth: 0 │ │ ├── rest: ∅ @@ -175,28 +203,31 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (8,15)-(8,16)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ ArrayNode (location: (8,18)-(8,24)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── elements: (length: 2) │ │ │ ├── @ IntegerNode (location: (8,19)-(8,20)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ └── @ IntegerNode (location: (8,22)-(8,23)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ ├── opening_loc: (8,18)-(8,19) = "[" │ │ └── closing_loc: (8,23)-(8,24) = "]" │ ├── opening_loc: (8,14)-(8,15) = "[" │ └── closing_loc: (8,24)-(8,25) = "]" ├── @ MultiWriteNode (location: (9,0)-(9,15)) + │ ├── flags: newline │ ├── lefts: (length: 1) │ │ └── @ LocalVariableTargetNode (location: (9,1)-(9,2)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── rest: │ │ @ SplatNode (location: (9,4)-(9,5)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (9,4)-(9,5) = "*" │ │ └── expression: ∅ │ ├── rights: (length: 0) @@ -205,26 +236,30 @@ │ ├── operator_loc: (9,7)-(9,8) = "=" │ └── value: │ @ ArrayNode (location: (9,9)-(9,15)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (9,10)-(9,11)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (9,13)-(9,14)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: (9,9)-(9,10) = "[" │ └── closing_loc: (9,14)-(9,15) = "]" ├── @ MultiWriteNode (location: (10,0)-(10,18)) + │ ├── flags: newline │ ├── lefts: (length: 1) │ │ └── @ LocalVariableTargetNode (location: (10,1)-(10,2)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── rest: │ │ @ SplatNode (location: (10,4)-(10,8)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (10,4)-(10,5) = "*" │ │ └── expression: │ │ @ LocalVariableTargetNode (location: (10,5)-(10,8)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── depth: 0 │ ├── rights: (length: 0) @@ -233,22 +268,25 @@ │ ├── operator_loc: (10,10)-(10,11) = "=" │ └── value: │ @ ArrayNode (location: (10,12)-(10,18)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (10,13)-(10,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (10,16)-(10,17)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: (10,12)-(10,13) = "[" │ └── closing_loc: (10,17)-(10,18) = "]" ├── @ MultiWriteNode (location: (11,0)-(11,15)) + │ ├── flags: newline │ ├── lefts: (length: 2) │ │ ├── @ LocalVariableTargetNode (location: (11,1)-(11,2)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ └── @ LocalVariableTargetNode (location: (11,4)-(11,5)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ └── depth: 0 │ ├── rest: ∅ @@ -258,22 +296,25 @@ │ ├── operator_loc: (11,7)-(11,8) = "=" │ └── value: │ @ ArrayNode (location: (11,9)-(11,15)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (11,10)-(11,11)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (11,13)-(11,14)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: (11,9)-(11,10) = "[" │ └── closing_loc: (11,14)-(11,15) = "]" ├── @ MultiWriteNode (location: (12,0)-(12,12)) + │ ├── flags: newline │ ├── lefts: (length: 2) │ │ ├── @ LocalVariableTargetNode (location: (12,1)-(12,2)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ └── @ LocalVariableTargetNode (location: (12,4)-(12,5)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ └── depth: 0 │ ├── rest: ∅ @@ -283,29 +324,36 @@ │ ├── operator_loc: (12,7)-(12,8) = "=" │ └── value: │ @ LocalVariableReadNode (location: (12,9)-(12,12)) + │ ├── flags: ∅ │ ├── name: :foo │ └── depth: 0 ├── @ MultiWriteNode (location: (13,0)-(13,10)) + │ ├── flags: newline │ ├── lefts: (length: 1) │ │ └── @ LocalVariableTargetNode (location: (13,1)-(13,2)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── rest: │ │ @ ImplicitRestNode (location: (13,2)-(13,3)) + │ │ └── flags: ∅ │ ├── rights: (length: 0) │ ├── lparen_loc: (13,0)-(13,1) = "(" │ ├── rparen_loc: (13,3)-(13,4) = ")" │ ├── operator_loc: (13,5)-(13,6) = "=" │ └── value: │ @ LocalVariableReadNode (location: (13,7)-(13,10)) + │ ├── flags: ∅ │ ├── name: :foo │ └── depth: 0 ├── @ MultiWriteNode (location: (14,0)-(14,23)) + │ ├── flags: newline │ ├── lefts: (length: 2) │ │ ├── @ CallTargetNode (location: (14,1)-(14,6)) │ │ │ ├── flags: ∅ │ │ │ ├── receiver: │ │ │ │ @ LocalVariableReadNode (location: (14,1)-(14,2)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ └── depth: 0 │ │ │ ├── call_operator_loc: (14,2)-(14,3) = "." @@ -315,6 +363,7 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ LocalVariableReadNode (location: (14,8)-(14,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── call_operator_loc: (14,9)-(14,10) = "." @@ -327,33 +376,37 @@ │ ├── operator_loc: (14,15)-(14,16) = "=" │ └── value: │ @ ArrayNode (location: (14,17)-(14,23)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (14,18)-(14,19)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (14,21)-(14,22)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: (14,17)-(14,18) = "[" │ └── closing_loc: (14,22)-(14,23) = "]" ├── @ MultiWriteNode (location: (15,0)-(15,24)) + │ ├── flags: newline │ ├── lefts: (length: 2) │ │ ├── @ IndexTargetNode (location: (15,1)-(15,8)) │ │ │ ├── flags: attribute_write │ │ │ ├── receiver: │ │ │ │ @ LocalVariableReadNode (location: (15,1)-(15,2)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ └── depth: 0 │ │ │ ├── opening_loc: (15,2)-(15,3) = "[" │ │ │ ├── arguments: │ │ │ │ @ ArgumentsNode (location: (15,3)-(15,7)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: contains_splat │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ SplatNode (location: (15,3)-(15,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (15,3)-(15,4) = "*" │ │ │ │ └── expression: │ │ │ │ @ LocalVariableReadNode (location: (15,4)-(15,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :foo │ │ │ │ └── depth: 0 │ │ │ ├── closing_loc: (15,7)-(15,8) = "]" @@ -362,6 +415,7 @@ │ │ ├── flags: attribute_write │ │ ├── receiver: │ │ │ @ LocalVariableReadNode (location: (15,10)-(15,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── opening_loc: (15,11)-(15,12) = "[" @@ -370,7 +424,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (15,12)-(15,13)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: (15,13)-(15,14) = "]" │ │ └── block: ∅ @@ -381,22 +435,24 @@ │ ├── operator_loc: (15,16)-(15,17) = "=" │ └── value: │ @ ArrayNode (location: (15,18)-(15,24)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (15,19)-(15,20)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (15,22)-(15,23)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: (15,18)-(15,19) = "[" │ └── closing_loc: (15,23)-(15,24) = "]" ├── @ MultiWriteNode (location: (16,0)-(16,21)) + │ ├── flags: newline │ ├── lefts: (length: 2) │ │ ├── @ IndexTargetNode (location: (16,1)-(16,5)) │ │ │ ├── flags: attribute_write │ │ │ ├── receiver: │ │ │ │ @ LocalVariableReadNode (location: (16,1)-(16,2)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ └── depth: 0 │ │ │ ├── opening_loc: (16,2)-(16,3) = "[" @@ -405,7 +461,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (16,3)-(16,4)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 0 │ │ │ ├── closing_loc: (16,4)-(16,5) = "]" │ │ │ └── block: ∅ @@ -413,6 +469,7 @@ │ │ ├── flags: attribute_write │ │ ├── receiver: │ │ │ @ LocalVariableReadNode (location: (16,7)-(16,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── opening_loc: (16,8)-(16,9) = "[" @@ -421,7 +478,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (16,9)-(16,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: (16,10)-(16,11) = "]" │ │ └── block: ∅ @@ -432,26 +489,29 @@ │ ├── operator_loc: (16,13)-(16,14) = "=" │ └── value: │ @ ArrayNode (location: (16,15)-(16,21)) - │ ├── flags: ∅ + │ ├── flags: static_literal │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (16,16)-(16,17)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (16,19)-(16,20)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: (16,15)-(16,16) = "[" │ └── closing_loc: (16,20)-(16,21) = "]" ├── @ MultiWriteNode (location: (17,0)-(17,12)) + │ ├── flags: newline │ ├── lefts: (length: 0) │ ├── rest: │ │ @ SplatNode (location: (17,1)-(17,7)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (17,1)-(17,2) = "*" │ │ └── expression: │ │ @ CallTargetNode (location: (17,2)-(17,7)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ LocalVariableReadNode (location: (17,2)-(17,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ └── depth: 0 │ │ ├── call_operator_loc: (17,3)-(17,4) = "." @@ -463,11 +523,13 @@ │ ├── operator_loc: (17,9)-(17,10) = "=" │ └── value: │ @ IntegerNode (location: (17,11)-(17,12)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ ConstantPathWriteNode (location: (18,0)-(18,13)) + │ ├── flags: newline │ ├── target: │ │ @ ConstantPathNode (location: (18,0)-(18,5)) + │ │ ├── flags: ∅ │ │ ├── parent: ∅ │ │ ├── name: :Foo │ │ ├── delimiter_loc: (18,0)-(18,2) = "::" @@ -475,41 +537,49 @@ │ ├── operator_loc: (18,6)-(18,7) = "=" │ └── value: │ @ ConstantPathNode (location: (18,8)-(18,13)) + │ ├── flags: ∅ │ ├── parent: ∅ │ ├── name: :Bar │ ├── delimiter_loc: (18,8)-(18,10) = "::" │ └── name_loc: (18,10)-(18,13) = "Bar" ├── @ ClassVariableWriteNode (location: (19,0)-(19,7)) + │ ├── flags: newline │ ├── name: :@@a │ ├── name_loc: (19,0)-(19,3) = "@@a" │ ├── value: │ │ @ IntegerNode (location: (19,6)-(19,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (19,4)-(19,5) = "=" ├── @ InstanceVariableWriteNode (location: (20,0)-(20,6)) + │ ├── flags: newline │ ├── name: :@a │ ├── name_loc: (20,0)-(20,2) = "@a" │ ├── value: │ │ @ IntegerNode (location: (20,5)-(20,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (20,3)-(20,4) = "=" ├── @ ConstantWriteNode (location: (21,0)-(21,9)) + │ ├── flags: newline │ ├── name: :CONST │ ├── name_loc: (21,0)-(21,5) = "CONST" │ ├── value: │ │ @ IntegerNode (location: (21,8)-(21,9)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (21,6)-(21,7) = "=" ├── @ ConstantPathWriteNode (location: (22,0)-(22,23)) + │ ├── flags: newline │ ├── target: │ │ @ ConstantPathNode (location: (22,0)-(22,19)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantPathNode (location: (22,0)-(22,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── parent: │ │ │ │ @ ConstantReadNode (location: (22,0)-(22,4)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :Name │ │ │ ├── name: :Spaced │ │ │ ├── delimiter_loc: (22,4)-(22,6) = "::" @@ -520,23 +590,29 @@ │ ├── operator_loc: (22,20)-(22,21) = "=" │ └── value: │ @ IntegerNode (location: (22,22)-(22,23)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── @ LocalVariableWriteNode (location: (23,0)-(23,16)) + │ ├── flags: newline │ ├── name: :a │ ├── depth: 0 │ ├── name_loc: (23,0)-(23,1) = "a" │ ├── value: │ │ @ ParenthesesNode (location: (23,4)-(23,16)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (23,5)-(23,15)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ MultiWriteNode (location: (23,5)-(23,15)) + │ │ │ ├── flags: newline │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ LocalVariableTargetNode (location: (23,6)-(23,7)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :b │ │ │ │ │ └── depth: 0 │ │ │ │ └── @ LocalVariableTargetNode (location: (23,9)-(23,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :c │ │ │ │ └── depth: 0 │ │ │ ├── rest: ∅ @@ -546,21 +622,23 @@ │ │ │ ├── operator_loc: (23,12)-(23,13) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (23,14)-(23,15)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── opening_loc: (23,4)-(23,5) = "(" │ │ └── closing_loc: (23,15)-(23,16) = ")" │ └── operator_loc: (23,2)-(23,3) = "=" ├── @ LocalVariableWriteNode (location: (24,0)-(24,5)) + │ ├── flags: newline │ ├── name: :a │ ├── depth: 0 │ ├── name_loc: (24,0)-(24,1) = "a" │ ├── value: │ │ @ IntegerNode (location: (24,4)-(24,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (24,2)-(24,3) = "=" ├── @ LocalVariableWriteNode (location: (25,0)-(25,11)) + │ ├── flags: newline │ ├── name: :foo │ ├── depth: 0 │ ├── name_loc: (25,0)-(25,3) = "foo" @@ -577,9 +655,10 @@ │ │ └── block: ∅ │ └── operator_loc: (25,4)-(25,5) = "=" ├── @ CallNode (location: (26,0)-(26,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (26,0)-(26,3)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── depth: 0 │ ├── call_operator_loc: (26,3)-(26,4) = "." @@ -590,9 +669,10 @@ │ ├── closing_loc: (26,8)-(26,9) = ")" │ └── block: ∅ ├── @ CallNode (location: (27,0)-(27,13)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (27,0)-(27,3)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── depth: 0 │ ├── call_operator_loc: (27,3)-(27,4) = "." @@ -604,17 +684,18 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (27,8)-(27,9)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (27,11)-(27,12)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: (27,12)-(27,13) = ")" │ └── block: ∅ ├── @ CallNode (location: (28,0)-(28,11)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (28,0)-(28,3)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── depth: 0 │ ├── call_operator_loc: (28,3)-(28,4) = "." @@ -626,12 +707,14 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ TrueNode (location: (28,7)-(28,11)) + │ │ └── flags: static_literal │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (29,0)-(29,19)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ LocalVariableReadNode (location: (29,0)-(29,3)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -640,9 +723,10 @@ │ ├── opening_loc: (29,3)-(29,4) = "[" │ ├── arguments: │ │ @ ArgumentsNode (location: (29,4)-(29,19)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat │ │ └── arguments: (length: 2) │ │ ├── @ SplatNode (location: (29,4)-(29,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (29,4)-(29,5) = "*" │ │ │ └── expression: │ │ │ @ CallNode (location: (29,5)-(29,10)) @@ -668,9 +752,10 @@ │ ├── closing_loc: (29,10)-(29,11) = "]" │ └── block: ∅ ├── @ CallNode (location: (30,0)-(30,17)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ LocalVariableReadNode (location: (30,0)-(30,3)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -682,14 +767,14 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ RangeNode (location: (30,4)-(30,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: static_literal │ │ │ ├── left: │ │ │ │ @ IntegerNode (location: (30,4)-(30,5)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── right: │ │ │ │ @ IntegerNode (location: (30,7)-(30,8)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ └── operator_loc: (30,5)-(30,7) = ".." │ │ └── @ CallNode (location: (30,12)-(30,17)) @@ -705,9 +790,10 @@ │ ├── closing_loc: (30,8)-(30,9) = "]" │ └── block: ∅ ├── @ CallNode (location: (31,0)-(31,9)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ LocalVariableReadNode (location: (31,0)-(31,3)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -719,14 +805,15 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (31,8)-(31,9)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── closing_loc: (31,4)-(31,5) = "]" │ └── block: ∅ ├── @ CallNode (location: (32,0)-(32,17)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ LocalVariableReadNode (location: (32,0)-(32,3)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -738,9 +825,11 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 3) │ │ ├── @ LocalVariableReadNode (location: (32,4)-(32,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── @ LocalVariableReadNode (location: (32,7)-(32,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ └── depth: 0 │ │ └── @ CallNode (location: (32,12)-(32,17)) @@ -756,9 +845,10 @@ │ ├── closing_loc: (32,8)-(32,9) = "]" │ └── block: ∅ ├── @ CallNode (location: (33,0)-(33,18)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ LocalVariableReadNode (location: (33,0)-(33,3)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -792,6 +882,7 @@ │ ├── closing_loc: (33,9)-(33,10) = "]" │ └── block: ∅ ├── @ LocalVariableWriteNode (location: (34,0)-(34,7)) + │ ├── flags: newline │ ├── name: :x │ ├── depth: 0 │ ├── name_loc: (34,0)-(34,1) = "x" @@ -804,9 +895,10 @@ │ │ └── unescaped: "" │ └── operator_loc: (34,2)-(34,3) = "=" ├── @ CallNode (location: (35,0)-(35,7)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ LocalVariableReadNode (location: (35,0)-(35,1)) + │ │ ├── flags: ∅ │ │ ├── name: :x │ │ └── depth: 0 │ ├── call_operator_loc: (35,1)-(35,2) = "." @@ -826,9 +918,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (36,0)-(36,12)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ LocalVariableReadNode (location: (36,0)-(36,1)) + │ │ ├── flags: ∅ │ │ ├── name: :x │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -858,9 +951,10 @@ │ ├── closing_loc: (36,5)-(36,6) = "]" │ └── block: ∅ ├── @ IndexOrWriteNode (location: (37,0)-(37,14)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (37,0)-(37,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -890,6 +984,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ InstanceVariableOrWriteNode (location: (38,0)-(38,10)) + │ ├── flags: newline │ ├── name: :@a │ ├── name_loc: (38,0)-(38,2) = "@a" │ ├── operator_loc: (38,3)-(38,6) = "||=" @@ -901,6 +996,7 @@ │ ├── closing_loc: (38,9)-(38,10) = ")" │ └── unescaped: "" ├── @ LocalVariableWriteNode (location: (39,0)-(39,14)) + │ ├── flags: newline │ ├── name: :x │ ├── depth: 0 │ ├── name_loc: (39,0)-(39,1) = "x" @@ -910,17 +1006,18 @@ │ │ ├── opening_loc: (39,4)-(39,14) = "<<-HEREDOC" │ │ ├── parts: (length: 3) │ │ │ ├── @ StringNode (location: (40,0)-(40,2)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (40,0)-(40,2) = " " │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: " " │ │ │ ├── @ EmbeddedStatementsNode (location: (40,2)-(40,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: (40,2)-(40,4) = "\#{" │ │ │ │ ├── statements: ∅ │ │ │ │ └── closing_loc: (40,4)-(40,5) = "}" │ │ │ └── @ StringNode (location: (40,5)-(41,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (40,5)-(41,0) = "\n" │ │ │ ├── closing_loc: ∅ @@ -928,9 +1025,10 @@ │ │ └── closing_loc: (41,0)-(42,0) = "HEREDOC\n" │ └── operator_loc: (39,2)-(39,3) = "=" ├── @ CallNode (location: (42,0)-(42,14)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ LocalVariableReadNode (location: (42,0)-(42,1)) + │ │ ├── flags: ∅ │ │ ├── name: :x │ │ └── depth: 0 │ ├── call_operator_loc: (42,1)-(42,2) = "." @@ -946,17 +1044,18 @@ │ │ ├── opening_loc: (42,4)-(42,14) = "<<-HEREDOC" │ │ ├── parts: (length: 3) │ │ │ ├── @ StringNode (location: (43,0)-(43,2)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (43,0)-(43,2) = " " │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: " " │ │ │ ├── @ EmbeddedStatementsNode (location: (43,2)-(43,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: (43,2)-(43,4) = "\#{" │ │ │ │ ├── statements: ∅ │ │ │ │ └── closing_loc: (43,4)-(43,5) = "}" │ │ │ └── @ StringNode (location: (43,5)-(44,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (43,5)-(44,0) = "\n" │ │ │ ├── closing_loc: ∅ @@ -965,9 +1064,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (45,0)-(45,16)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ LocalVariableReadNode (location: (45,0)-(45,1)) + │ │ ├── flags: ∅ │ │ ├── name: :x │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -983,17 +1083,18 @@ │ │ ├── opening_loc: (45,6)-(45,16) = "<<-HEREDOC" │ │ ├── parts: (length: 3) │ │ │ ├── @ StringNode (location: (46,0)-(46,2)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (46,0)-(46,2) = " " │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: " " │ │ │ ├── @ EmbeddedStatementsNode (location: (46,2)-(46,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: (46,2)-(46,4) = "\#{" │ │ │ │ ├── statements: ∅ │ │ │ │ └── closing_loc: (46,4)-(46,5) = "}" │ │ │ └── @ StringNode (location: (46,5)-(47,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (46,5)-(47,0) = "\n" │ │ │ ├── closing_loc: ∅ @@ -1002,9 +1103,10 @@ │ ├── closing_loc: (45,2)-(45,3) = "]" │ └── block: ∅ ├── @ IndexOrWriteNode (location: (48,0)-(48,21)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (48,0)-(48,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -1018,17 +1120,18 @@ │ │ ├── opening_loc: (48,2)-(48,12) = "<<-HEREDOC" │ │ ├── parts: (length: 3) │ │ │ ├── @ StringNode (location: (49,0)-(49,2)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (49,0)-(49,2) = " " │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: " " │ │ │ ├── @ EmbeddedStatementsNode (location: (49,2)-(49,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: (49,2)-(49,4) = "\#{" │ │ │ │ ├── statements: ∅ │ │ │ │ └── closing_loc: (49,4)-(49,5) = "}" │ │ │ └── @ StringNode (location: (49,5)-(50,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (49,5)-(50,0) = "\n" │ │ │ ├── closing_loc: ∅ @@ -1049,6 +1152,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ └── @ InstanceVariableOrWriteNode (location: (51,0)-(51,17)) + ├── flags: newline ├── name: :@a ├── name_loc: (51,0)-(51,2) = "@a" ├── operator_loc: (51,3)-(51,6) = "||=" @@ -1058,17 +1162,18 @@ ├── opening_loc: (51,7)-(51,17) = "<<-HEREDOC" ├── parts: (length: 3) │ ├── @ StringNode (location: (52,0)-(52,2)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (52,0)-(52,2) = " " │ │ ├── closing_loc: ∅ │ │ └── unescaped: " " │ ├── @ EmbeddedStatementsNode (location: (52,2)-(52,5)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (52,2)-(52,4) = "\#{" │ │ ├── statements: ∅ │ │ └── closing_loc: (52,4)-(52,5) = "}" │ └── @ StringNode (location: (52,5)-(53,0)) - │ ├── flags: frozen + │ ├── flags: static_literal, frozen │ ├── opening_loc: ∅ │ ├── content_loc: (52,5)-(53,0) = "\n" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/block.txt b/test/prism/snapshots/unparser/corpus/literal/block.txt index b4c86d0b04b..4320ede87b6 100644 --- a/test/prism/snapshots/unparser/corpus/literal/block.txt +++ b/test/prism/snapshots/unparser/corpus/literal/block.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(96,1)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(96,1)) + ├── flags: ∅ └── body: (length: 30) ├── @ CallNode (location: (1,0)-(2,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -14,13 +16,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (1,4)-(2,1)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ │ ├── opening_loc: (1,4)-(1,5) = "{" │ └── closing_loc: (2,0)-(2,1) = "}" ├── @ CallNode (location: (3,0)-(4,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -30,11 +33,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (3,4)-(4,1)) + │ ├── flags: ∅ │ ├── locals: [:a] │ ├── parameters: │ │ @ BlockParametersNode (location: (3,6)-(3,9)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (3,7)-(3,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (3,7)-(3,8)) │ │ │ │ ├── flags: ∅ @@ -52,7 +58,7 @@ │ ├── opening_loc: (3,4)-(3,5) = "{" │ └── closing_loc: (4,0)-(4,1) = "}" ├── @ CallNode (location: (5,0)-(6,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -62,11 +68,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (5,4)-(6,1)) + │ ├── flags: ∅ │ ├── locals: [:a] │ ├── parameters: │ │ @ BlockParametersNode (location: (5,6)-(5,10)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (5,7)-(5,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (5,7)-(5,8)) │ │ │ │ ├── flags: ∅ @@ -74,6 +83,7 @@ │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ ImplicitRestNode (location: (5,8)-(5,9)) + │ │ │ │ └── flags: ∅ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 0) │ │ │ ├── keyword_rest: ∅ @@ -85,7 +95,7 @@ │ ├── opening_loc: (5,4)-(5,5) = "{" │ └── closing_loc: (6,0)-(6,1) = "}" ├── @ CallNode (location: (7,0)-(8,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -95,11 +105,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (7,4)-(8,1)) + │ ├── flags: ∅ │ ├── locals: [:a, :x] │ ├── parameters: │ │ @ BlockParametersNode (location: (7,6)-(7,13)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (7,7)-(7,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (7,7)-(7,8)) │ │ │ │ ├── flags: ∅ @@ -107,6 +120,7 @@ │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ ImplicitRestNode (location: (7,8)-(7,9)) + │ │ │ │ └── flags: ∅ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 0) │ │ │ ├── keyword_rest: ∅ @@ -121,7 +135,7 @@ │ ├── opening_loc: (7,4)-(7,5) = "{" │ └── closing_loc: (8,0)-(8,1) = "}" ├── @ CallNode (location: (9,0)-(10,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -131,11 +145,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (9,4)-(10,1)) + │ ├── flags: ∅ │ ├── locals: [:a, :b] │ ├── parameters: │ │ @ BlockParametersNode (location: (9,6)-(9,12)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (9,7)-(9,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (9,7)-(9,8)) │ │ │ │ │ ├── flags: ∅ @@ -156,7 +173,7 @@ │ ├── opening_loc: (9,4)-(9,5) = "{" │ └── closing_loc: (10,0)-(10,1) = "}" ├── @ CallNode (location: (11,0)-(13,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -167,21 +184,24 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (11,4)-(11,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── closing_loc: (11,5)-(11,6) = ")" │ └── block: │ @ BlockNode (location: (11,7)-(13,1)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (12,2)-(12,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NilNode (location: (12,2)-(12,5)) + │ │ └── flags: newline, static_literal │ ├── opening_loc: (11,7)-(11,8) = "{" │ └── closing_loc: (13,0)-(13,1) = "}" ├── @ CallNode (location: (14,0)-(16,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -191,11 +211,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (14,4)-(16,1)) + │ ├── flags: ∅ │ ├── locals: [:a, :b] │ ├── parameters: │ │ @ BlockParametersNode (location: (14,6)-(14,13)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (14,7)-(14,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (14,7)-(14,8)) │ │ │ │ ├── flags: ∅ @@ -216,12 +239,14 @@ │ │ └── closing_loc: (14,12)-(14,13) = "|" │ ├── body: │ │ @ StatementsNode (location: (15,2)-(15,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NilNode (location: (15,2)-(15,5)) + │ │ └── flags: newline, static_literal │ ├── opening_loc: (14,4)-(14,5) = "{" │ └── closing_loc: (16,0)-(16,1) = "}" ├── @ CallNode (location: (17,0)-(19,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -231,11 +256,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (17,4)-(19,1)) + │ ├── flags: ∅ │ ├── locals: [:a] │ ├── parameters: │ │ @ BlockParametersNode (location: (17,6)-(17,12)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (17,7)-(17,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (17,7)-(17,8)) │ │ │ │ ├── flags: ∅ @@ -256,12 +284,14 @@ │ │ └── closing_loc: (17,11)-(17,12) = "|" │ ├── body: │ │ @ StatementsNode (location: (18,2)-(18,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NilNode (location: (18,2)-(18,5)) + │ │ └── flags: newline, static_literal │ ├── opening_loc: (17,4)-(17,5) = "{" │ └── closing_loc: (19,0)-(19,1) = "}" ├── @ CallNode (location: (20,0)-(22,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -271,13 +301,15 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (20,4)-(22,1)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (21,2)-(21,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (21,2)-(21,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -289,7 +321,7 @@ │ ├── opening_loc: (20,4)-(20,5) = "{" │ └── closing_loc: (22,0)-(22,1) = "}" ├── @ CallNode (location: (23,0)-(25,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (23,0)-(23,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -309,13 +341,17 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (23,8)-(25,1)) + │ ├── flags: ∅ │ ├── locals: [:a, :b, :c] │ ├── parameters: │ │ @ BlockParametersNode (location: (23,10)-(23,21)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (23,11)-(23,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ MultiTargetNode (location: (23,11)-(23,17)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ │ ├── @ RequiredParameterNode (location: (23,12)-(23,13)) │ │ │ │ │ │ │ ├── flags: ∅ @@ -341,9 +377,10 @@ │ │ └── closing_loc: (23,20)-(23,21) = "|" │ ├── body: │ │ @ StatementsNode (location: (24,2)-(24,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (24,2)-(24,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :d @@ -355,7 +392,7 @@ │ ├── opening_loc: (23,8)-(23,9) = "{" │ └── closing_loc: (25,0)-(25,1) = "}" ├── @ CallNode (location: (26,0)-(27,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (26,0)-(26,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -375,11 +412,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (26,8)-(27,1)) + │ ├── flags: ∅ │ ├── locals: [:a, :b] │ ├── parameters: │ │ @ BlockParametersNode (location: (26,10)-(26,17)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (26,11)-(26,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: @@ -402,7 +442,7 @@ │ ├── opening_loc: (26,8)-(26,9) = "{" │ └── closing_loc: (27,0)-(27,1) = "}" ├── @ CallNode (location: (28,0)-(29,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (28,0)-(28,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -422,11 +462,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (28,8)-(29,1)) + │ ├── flags: ∅ │ ├── locals: [:a, :b] │ ├── parameters: │ │ @ BlockParametersNode (location: (28,10)-(28,16)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (28,11)-(28,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (28,11)-(28,12)) │ │ │ │ ├── flags: ∅ @@ -447,7 +490,7 @@ │ ├── opening_loc: (28,8)-(28,9) = "{" │ └── closing_loc: (29,0)-(29,1) = "}" ├── @ CallNode (location: (30,0)-(31,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (30,0)-(30,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -467,9 +510,11 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (30,8)-(31,1)) + │ ├── flags: ∅ │ ├── locals: [:a, :b] │ ├── parameters: │ │ @ BlockParametersNode (location: (30,10)-(30,18)) + │ │ ├── flags: ∅ │ │ ├── parameters: ∅ │ │ ├── locals: (length: 2) │ │ │ ├── @ BlockLocalVariableNode (location: (30,13)-(30,14)) @@ -484,7 +529,7 @@ │ ├── opening_loc: (30,8)-(30,9) = "{" │ └── closing_loc: (31,0)-(31,1) = "}" ├── @ CallNode (location: (32,0)-(34,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (32,0)-(32,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -504,11 +549,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (32,8)-(34,1)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: │ │ @ BlockParametersNode (location: (32,10)-(32,13)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (32,11)-(32,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: @@ -526,9 +574,10 @@ │ │ └── closing_loc: (32,12)-(32,13) = "|" │ ├── body: │ │ @ StatementsNode (location: (33,2)-(33,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (33,2)-(33,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :d @@ -540,7 +589,7 @@ │ ├── opening_loc: (32,8)-(32,9) = "{" │ └── closing_loc: (34,0)-(34,1) = "}" ├── @ CallNode (location: (35,0)-(37,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (35,0)-(35,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -560,16 +609,21 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (35,8)-(37,1)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: │ │ @ BlockParametersNode (location: (35,10)-(35,15)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (35,11)-(35,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ MultiTargetNode (location: (35,11)-(35,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── lefts: (length: 0) │ │ │ │ ├── rest: │ │ │ │ │ @ SplatNode (location: (35,12)-(35,13)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── operator_loc: (35,12)-(35,13) = "*" │ │ │ │ │ └── expression: ∅ │ │ │ │ ├── rights: (length: 0) @@ -586,9 +640,10 @@ │ │ └── closing_loc: (35,14)-(35,15) = "|" │ ├── body: │ │ @ StatementsNode (location: (36,2)-(36,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (36,2)-(36,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :d @@ -600,7 +655,7 @@ │ ├── opening_loc: (35,8)-(35,9) = "{" │ └── closing_loc: (37,0)-(37,1) = "}" ├── @ CallNode (location: (38,0)-(40,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (38,0)-(38,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -620,18 +675,24 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (38,8)-(40,1)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: │ │ @ BlockParametersNode (location: (38,10)-(38,17)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (38,11)-(38,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ MultiTargetNode (location: (38,11)-(38,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── lefts: (length: 1) │ │ │ │ │ └── @ MultiTargetNode (location: (38,12)-(38,15)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── lefts: (length: 0) │ │ │ │ │ ├── rest: │ │ │ │ │ │ @ SplatNode (location: (38,13)-(38,14)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── operator_loc: (38,13)-(38,14) = "*" │ │ │ │ │ │ └── expression: ∅ │ │ │ │ │ ├── rights: (length: 0) @@ -652,9 +713,10 @@ │ │ └── closing_loc: (38,16)-(38,17) = "|" │ ├── body: │ │ @ StatementsNode (location: (39,2)-(39,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (39,2)-(39,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :d @@ -666,7 +728,7 @@ │ ├── opening_loc: (38,8)-(38,9) = "{" │ └── closing_loc: (40,0)-(40,1) = "}" ├── @ CallNode (location: (41,0)-(43,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (41,0)-(41,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -686,21 +748,27 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (41,8)-(43,1)) + │ ├── flags: ∅ │ ├── locals: [:a] │ ├── parameters: │ │ @ BlockParametersNode (location: (41,10)-(41,20)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (41,11)-(41,19)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ MultiTargetNode (location: (41,11)-(41,19)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ ├── @ RequiredParameterNode (location: (41,12)-(41,13)) │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :a │ │ │ │ │ └── @ MultiTargetNode (location: (41,15)-(41,18)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── lefts: (length: 0) │ │ │ │ │ ├── rest: │ │ │ │ │ │ @ SplatNode (location: (41,16)-(41,17)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── operator_loc: (41,16)-(41,17) = "*" │ │ │ │ │ │ └── expression: ∅ │ │ │ │ │ ├── rights: (length: 0) @@ -721,9 +789,10 @@ │ │ └── closing_loc: (41,19)-(41,20) = "|" │ ├── body: │ │ @ StatementsNode (location: (42,2)-(42,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (42,2)-(42,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :d @@ -735,7 +804,7 @@ │ ├── opening_loc: (41,8)-(41,9) = "{" │ └── closing_loc: (43,0)-(43,1) = "}" ├── @ CallNode (location: (44,0)-(46,1)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (44,0)-(44,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -755,13 +824,17 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (44,8)-(46,1)) + │ ├── flags: ∅ │ ├── locals: [:a, :b] │ ├── parameters: │ │ @ BlockParametersNode (location: (44,10)-(44,18)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (44,11)-(44,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ MultiTargetNode (location: (44,11)-(44,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ ├── @ RequiredParameterNode (location: (44,12)-(44,13)) │ │ │ │ │ │ ├── flags: ∅ @@ -784,9 +857,10 @@ │ │ └── closing_loc: (44,17)-(44,18) = "|" │ ├── body: │ │ @ StatementsNode (location: (45,2)-(45,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (45,2)-(45,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :d @@ -798,7 +872,7 @@ │ ├── opening_loc: (44,8)-(44,9) = "{" │ └── closing_loc: (46,0)-(46,1) = "}" ├── @ CallNode (location: (47,0)-(48,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (47,0)-(48,1)) │ │ ├── flags: ∅ @@ -821,6 +895,7 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (47,8)-(48,1)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: ∅ @@ -834,7 +909,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (49,0)-(51,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :m @@ -844,32 +919,37 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (49,2)-(51,3)) + │ ├── flags: ∅ │ ├── locals: [:e] │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (49,2)-(51,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (50,0)-(50,21)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (50,0)-(50,6) = "rescue" │ │ │ ├── exceptions: (length: 1) │ │ │ │ └── @ ConstantReadNode (location: (50,7)-(50,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :Exception │ │ │ ├── operator_loc: (50,17)-(50,19) = "=>" │ │ │ ├── reference: │ │ │ │ @ LocalVariableTargetNode (location: (50,20)-(50,21)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :e │ │ │ │ └── depth: 0 │ │ │ ├── statements: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (51,0)-(51,3) = "end" │ ├── opening_loc: (49,2)-(49,4) = "do" │ └── closing_loc: (51,0)-(51,3) = "end" ├── @ CallNode (location: (52,0)-(56,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :m @@ -879,16 +959,19 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (52,2)-(56,3)) + │ ├── flags: ∅ │ ├── locals: [:bar] │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (52,2)-(56,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (53,2)-(53,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (53,2)-(53,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :foo @@ -899,29 +982,34 @@ │ │ │ └── block: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (54,0)-(55,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (54,0)-(54,6) = "rescue" │ │ │ ├── exceptions: (length: 1) │ │ │ │ └── @ ConstantReadNode (location: (54,7)-(54,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :Exception │ │ │ ├── operator_loc: (54,17)-(54,19) = "=>" │ │ │ ├── reference: │ │ │ │ @ LocalVariableTargetNode (location: (54,20)-(54,23)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :bar │ │ │ │ └── depth: 0 │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (55,2)-(55,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ LocalVariableReadNode (location: (55,2)-(55,5)) + │ │ │ │ ├── flags: newline │ │ │ │ ├── name: :bar │ │ │ │ └── depth: 0 - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (56,0)-(56,3) = "end" │ ├── opening_loc: (52,2)-(52,4) = "do" │ └── closing_loc: (56,0)-(56,3) = "end" ├── @ CallNode (location: (57,0)-(61,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :m @@ -931,16 +1019,19 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (57,2)-(61,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (57,2)-(61,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (58,2)-(58,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (58,2)-(58,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -951,11 +1042,14 @@ │ │ │ └── block: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (59,0)-(60,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (59,0)-(59,6) = "rescue" │ │ │ ├── exceptions: (length: 2) │ │ │ │ ├── @ ConstantReadNode (location: (59,7)-(59,16)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :SomeError │ │ │ │ └── @ SplatNode (location: (59,18)-(59,22)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (59,18)-(59,19) = "*" │ │ │ │ └── expression: │ │ │ │ @ CallNode (location: (59,19)-(59,22)) @@ -972,9 +1066,10 @@ │ │ │ ├── reference: ∅ │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (60,2)-(60,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (60,2)-(60,5)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :baz @@ -983,14 +1078,14 @@ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (61,0)-(61,3) = "end" │ ├── opening_loc: (57,2)-(57,4) = "do" │ └── closing_loc: (61,0)-(61,3) = "end" ├── @ CallNode (location: (62,0)-(66,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :m @@ -1000,16 +1095,19 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (62,2)-(66,3)) + │ ├── flags: ∅ │ ├── locals: [:exception] │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (62,2)-(66,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (63,2)-(63,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (63,2)-(63,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -1020,11 +1118,14 @@ │ │ │ └── block: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (64,0)-(65,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (64,0)-(64,6) = "rescue" │ │ │ ├── exceptions: (length: 2) │ │ │ │ ├── @ ConstantReadNode (location: (64,7)-(64,16)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :SomeError │ │ │ │ └── @ SplatNode (location: (64,18)-(64,22)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (64,18)-(64,19) = "*" │ │ │ │ └── expression: │ │ │ │ @ CallNode (location: (64,19)-(64,22)) @@ -1040,13 +1141,15 @@ │ │ │ ├── operator_loc: (64,23)-(64,25) = "=>" │ │ │ ├── reference: │ │ │ │ @ LocalVariableTargetNode (location: (64,26)-(64,35)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :exception │ │ │ │ └── depth: 0 │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (65,2)-(65,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (65,2)-(65,5)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :baz @@ -1055,14 +1158,14 @@ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (66,0)-(66,3) = "end" │ ├── opening_loc: (62,2)-(62,4) = "do" │ └── closing_loc: (66,0)-(66,3) = "end" ├── @ CallNode (location: (67,0)-(71,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :m @@ -1072,16 +1175,19 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (67,2)-(71,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (67,2)-(71,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (68,2)-(68,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (68,2)-(68,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -1092,9 +1198,11 @@ │ │ │ └── block: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (69,0)-(70,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (69,0)-(69,6) = "rescue" │ │ │ ├── exceptions: (length: 1) │ │ │ │ └── @ SplatNode (location: (69,7)-(69,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (69,7)-(69,8) = "*" │ │ │ │ └── expression: │ │ │ │ @ CallNode (location: (69,8)-(69,11)) @@ -1111,9 +1219,10 @@ │ │ │ ├── reference: ∅ │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (70,2)-(70,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (70,2)-(70,5)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :baz @@ -1122,14 +1231,14 @@ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (71,0)-(71,3) = "end" │ ├── opening_loc: (67,2)-(67,4) = "do" │ └── closing_loc: (71,0)-(71,3) = "end" ├── @ CallNode (location: (72,0)-(75,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :m @@ -1139,16 +1248,19 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (72,2)-(75,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (72,2)-(75,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (73,2)-(73,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (73,2)-(73,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -1159,21 +1271,23 @@ │ │ │ └── block: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (74,0)-(74,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (74,0)-(74,6) = "rescue" │ │ │ ├── exceptions: (length: 1) │ │ │ │ └── @ ConstantReadNode (location: (74,7)-(74,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :LoadError │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (75,0)-(75,3) = "end" │ ├── opening_loc: (72,2)-(72,4) = "do" │ └── closing_loc: (75,0)-(75,3) = "end" ├── @ CallNode (location: (76,0)-(81,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :m @@ -1183,16 +1297,19 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (76,2)-(81,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (76,2)-(81,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (77,2)-(77,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (77,2)-(77,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -1203,20 +1320,23 @@ │ │ │ └── block: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (78,0)-(78,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (78,0)-(78,6) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: │ │ │ @ ElseNode (location: (79,0)-(81,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── else_keyword_loc: (79,0)-(79,4) = "else" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (80,2)-(80,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (80,2)-(80,5)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :baz @@ -1231,7 +1351,7 @@ │ ├── opening_loc: (76,2)-(76,4) = "do" │ └── closing_loc: (81,0)-(81,3) = "end" ├── @ CallNode (location: (82,0)-(86,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :m @@ -1241,16 +1361,19 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (82,2)-(86,3)) + │ ├── flags: ∅ │ ├── locals: [:exception] │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (82,2)-(86,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (83,2)-(83,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (83,2)-(83,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -1261,9 +1384,11 @@ │ │ │ └── block: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (84,0)-(85,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (84,0)-(84,6) = "rescue" │ │ │ ├── exceptions: (length: 1) │ │ │ │ └── @ SplatNode (location: (84,7)-(84,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (84,7)-(84,8) = "*" │ │ │ │ └── expression: │ │ │ │ @ CallNode (location: (84,8)-(84,11)) @@ -1279,13 +1404,15 @@ │ │ │ ├── operator_loc: (84,12)-(84,14) = "=>" │ │ │ ├── reference: │ │ │ │ @ LocalVariableTargetNode (location: (84,15)-(84,24)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :exception │ │ │ │ └── depth: 0 │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (85,2)-(85,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (85,2)-(85,5)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :baz @@ -1294,14 +1421,14 @@ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (86,0)-(86,3) = "end" │ ├── opening_loc: (82,2)-(82,4) = "do" │ └── closing_loc: (86,0)-(86,3) = "end" ├── @ CallNode (location: (87,0)-(89,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :m @@ -1311,16 +1438,19 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (87,2)-(89,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (87,2)-(89,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── rescue_clause: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: │ │ │ @ EnsureNode (location: (88,0)-(89,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── ensure_keyword_loc: (88,0)-(88,6) = "ensure" │ │ │ ├── statements: ∅ │ │ │ └── end_keyword_loc: (89,0)-(89,3) = "end" @@ -1328,7 +1458,7 @@ │ ├── opening_loc: (87,2)-(87,4) = "do" │ └── closing_loc: (89,0)-(89,3) = "end" ├── @ CallNode (location: (90,0)-(93,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :m @@ -1338,23 +1468,27 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (90,2)-(93,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (90,2)-(93,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (91,0)-(91,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (91,0)-(91,6) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: │ │ │ @ EnsureNode (location: (92,0)-(93,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── ensure_keyword_loc: (92,0)-(92,6) = "ensure" │ │ │ ├── statements: ∅ │ │ │ └── end_keyword_loc: (93,0)-(93,3) = "end" @@ -1362,7 +1496,7 @@ │ ├── opening_loc: (90,2)-(90,4) = "do" │ └── closing_loc: (93,0)-(93,3) = "end" └── @ CallNode (location: (94,0)-(96,1)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :bar @@ -1372,17 +1506,21 @@ ├── closing_loc: ∅ └── block: @ BlockNode (location: (94,4)-(96,1)) + ├── flags: ∅ ├── locals: [:_1, :_2] ├── parameters: │ @ NumberedParametersNode (location: (94,4)-(96,1)) + │ ├── flags: ∅ │ └── maximum: 2 ├── body: │ @ StatementsNode (location: (95,2)-(95,9)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (95,2)-(95,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (95,2)-(95,4)) + │ │ ├── flags: ∅ │ │ ├── name: :_1 │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -1394,6 +1532,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ LocalVariableReadNode (location: (95,7)-(95,9)) + │ │ ├── flags: ∅ │ │ ├── name: :_2 │ │ └── depth: 0 │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/case.txt b/test/prism/snapshots/unparser/corpus/literal/case.txt index 509caa55c8b..5e831cc6c3a 100644 --- a/test/prism/snapshots/unparser/corpus/literal/case.txt +++ b/test/prism/snapshots/unparser/corpus/literal/case.txt @@ -1,12 +1,16 @@ @ ProgramNode (location: (1,0)-(37,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(37,3)) + ├── flags: ∅ └── body: (length: 8) ├── @ CaseNode (location: (1,0)-(6,3)) + │ ├── flags: newline │ ├── predicate: ∅ │ ├── conditions: (length: 2) │ │ ├── @ WhenNode (location: (2,0)-(3,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (2,0)-(2,4) = "when" │ │ │ ├── conditions: (length: 1) │ │ │ │ └── @ CallNode (location: (2,5)-(2,8)) @@ -22,9 +26,10 @@ │ │ │ ├── then_keyword_loc: ∅ │ │ │ └── statements: │ │ │ @ StatementsNode (location: (3,2)-(3,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (3,2)-(3,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz @@ -34,6 +39,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ WhenNode (location: (4,0)-(5,5)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (4,0)-(4,4) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ CallNode (location: (4,5)-(4,8)) @@ -49,9 +55,10 @@ │ │ ├── then_keyword_loc: ∅ │ │ └── statements: │ │ @ StatementsNode (location: (5,2)-(5,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (5,2)-(5,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -60,10 +67,11 @@ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (1,0)-(1,4) = "case" │ └── end_keyword_loc: (6,0)-(6,3) = "end" ├── @ CaseNode (location: (7,0)-(11,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (7,5)-(7,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -77,6 +85,7 @@ │ │ └── block: ∅ │ ├── conditions: (length: 2) │ │ ├── @ WhenNode (location: (8,0)-(8,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (8,0)-(8,4) = "when" │ │ │ ├── conditions: (length: 1) │ │ │ │ └── @ CallNode (location: (8,5)-(8,8)) @@ -92,6 +101,7 @@ │ │ │ ├── then_keyword_loc: ∅ │ │ │ └── statements: ∅ │ │ └── @ WhenNode (location: (9,0)-(10,5)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (9,0)-(9,4) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ CallNode (location: (9,5)-(9,8)) @@ -107,9 +117,10 @@ │ │ ├── then_keyword_loc: ∅ │ │ └── statements: │ │ @ StatementsNode (location: (10,2)-(10,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (10,2)-(10,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -118,10 +129,11 @@ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (7,0)-(7,4) = "case" │ └── end_keyword_loc: (11,0)-(11,3) = "end" ├── @ CaseNode (location: (12,0)-(17,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (12,5)-(12,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -135,6 +147,7 @@ │ │ └── block: ∅ │ ├── conditions: (length: 2) │ │ ├── @ WhenNode (location: (13,0)-(14,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (13,0)-(13,4) = "when" │ │ │ ├── conditions: (length: 1) │ │ │ │ └── @ CallNode (location: (13,5)-(13,8)) @@ -150,9 +163,10 @@ │ │ │ ├── then_keyword_loc: ∅ │ │ │ └── statements: │ │ │ @ StatementsNode (location: (14,2)-(14,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (14,2)-(14,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz @@ -162,6 +176,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ WhenNode (location: (15,0)-(16,5)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (15,0)-(15,4) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ CallNode (location: (15,5)-(15,8)) @@ -177,9 +192,10 @@ │ │ ├── then_keyword_loc: ∅ │ │ └── statements: │ │ @ StatementsNode (location: (16,2)-(16,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (16,2)-(16,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -188,10 +204,11 @@ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (12,0)-(12,4) = "case" │ └── end_keyword_loc: (17,0)-(17,3) = "end" ├── @ CaseNode (location: (18,0)-(21,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (18,5)-(18,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -205,6 +222,7 @@ │ │ └── block: ∅ │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (19,0)-(20,8)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (19,0)-(19,4) = "when" │ │ ├── conditions: (length: 2) │ │ │ ├── @ CallNode (location: (19,5)-(19,8)) @@ -230,17 +248,19 @@ │ │ ├── then_keyword_loc: ∅ │ │ └── statements: │ │ @ StatementsNode (location: (20,2)-(20,8)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (20,2)-(20,8)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (20,2)-(20,3) = ":" │ │ ├── value_loc: (20,3)-(20,8) = "other" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "other" - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (18,0)-(18,4) = "case" │ └── end_keyword_loc: (21,0)-(21,3) = "end" ├── @ CaseNode (location: (22,0)-(25,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (22,5)-(22,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -254,9 +274,11 @@ │ │ └── block: ∅ │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (23,0)-(24,8)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (23,0)-(23,4) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ SplatNode (location: (23,5)-(23,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (23,5)-(23,6) = "*" │ │ │ └── expression: │ │ │ @ CallNode (location: (23,6)-(23,9)) @@ -272,17 +294,19 @@ │ │ ├── then_keyword_loc: ∅ │ │ └── statements: │ │ @ StatementsNode (location: (24,2)-(24,8)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (24,2)-(24,8)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (24,2)-(24,3) = ":" │ │ ├── value_loc: (24,3)-(24,8) = "value" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "value" - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (22,0)-(22,4) = "case" │ └── end_keyword_loc: (25,0)-(25,3) = "end" ├── @ CaseNode (location: (26,0)-(31,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (26,5)-(26,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -296,6 +320,7 @@ │ │ └── block: ∅ │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (27,0)-(28,5)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (27,0)-(27,4) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ CallNode (location: (27,5)-(27,8)) @@ -311,9 +336,10 @@ │ │ ├── then_keyword_loc: ∅ │ │ └── statements: │ │ @ StatementsNode (location: (28,2)-(28,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (28,2)-(28,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :baz @@ -322,14 +348,16 @@ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── consequent: + │ ├── else_clause: │ │ @ ElseNode (location: (29,0)-(31,3)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (29,0)-(29,4) = "else" │ │ ├── statements: │ │ │ @ StatementsNode (location: (30,2)-(30,6)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (30,2)-(30,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (30,2)-(30,3) = ":" │ │ │ ├── value_loc: (30,3)-(30,6) = "foo" │ │ │ ├── closing_loc: ∅ @@ -338,6 +366,7 @@ │ ├── case_keyword_loc: (26,0)-(26,4) = "case" │ └── end_keyword_loc: (31,0)-(31,3) = "end" ├── @ CaseNode (location: (32,0)-(34,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (32,5)-(32,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -351,9 +380,11 @@ │ │ └── block: ∅ │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (33,0)-(33,15)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (33,0)-(33,4) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ SplatNode (location: (33,5)-(33,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (33,5)-(33,6) = "*" │ │ │ └── expression: │ │ │ @ CallNode (location: (33,6)-(33,15)) @@ -391,10 +422,11 @@ │ │ │ └── block: ∅ │ │ ├── then_keyword_loc: ∅ │ │ └── statements: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (32,0)-(32,4) = "case" │ └── end_keyword_loc: (34,0)-(34,3) = "end" └── @ CaseNode (location: (35,0)-(37,3)) + ├── flags: newline ├── predicate: │ @ CallNode (location: (35,5)-(35,8)) │ ├── flags: variable_call, ignore_visibility @@ -408,9 +440,11 @@ │ └── block: ∅ ├── conditions: (length: 1) │ └── @ WhenNode (location: (36,0)-(36,15)) + │ ├── flags: ∅ │ ├── keyword_loc: (36,0)-(36,4) = "when" │ ├── conditions: (length: 1) │ │ └── @ SplatNode (location: (36,5)-(36,15)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (36,5)-(36,6) = "*" │ │ └── expression: │ │ @ CallNode (location: (36,6)-(36,15)) @@ -435,12 +469,12 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (36,14)-(36,15)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── then_keyword_loc: ∅ │ └── statements: ∅ - ├── consequent: ∅ + ├── else_clause: ∅ ├── case_keyword_loc: (35,0)-(35,4) = "case" └── end_keyword_loc: (37,0)-(37,3) = "end" diff --git a/test/prism/snapshots/unparser/corpus/literal/class.txt b/test/prism/snapshots/unparser/corpus/literal/class.txt index 53068883987..add60ce3056 100644 --- a/test/prism/snapshots/unparser/corpus/literal/class.txt +++ b/test/prism/snapshots/unparser/corpus/literal/class.txt @@ -1,13 +1,17 @@ @ ProgramNode (location: (1,0)-(35,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(35,3)) + ├── flags: ∅ └── body: (length: 10) ├── @ ClassNode (location: (1,0)-(2,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (1,0)-(1,5) = "class" │ ├── constant_path: │ │ @ ConstantReadNode (location: (1,6)-(1,7)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── inheritance_operator_loc: ∅ │ ├── superclass: ∅ @@ -15,6 +19,7 @@ │ ├── end_keyword_loc: (2,0)-(2,3) = "end" │ └── name: :A ├── @ SingletonClassNode (location: (4,0)-(5,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (4,0)-(4,5) = "class" │ ├── operator_loc: (4,6)-(4,8) = "<<" @@ -32,6 +37,7 @@ │ ├── body: ∅ │ └── end_keyword_loc: (5,0)-(5,3) = "end" ├── @ SingletonClassNode (location: (7,0)-(9,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (7,0)-(7,5) = "class" │ ├── operator_loc: (7,6)-(7,8) = "<<" @@ -48,9 +54,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (8,2)-(8,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (8,2)-(8,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :b @@ -61,12 +68,15 @@ │ │ └── block: ∅ │ └── end_keyword_loc: (9,0)-(9,3) = "end" ├── @ ClassNode (location: (11,0)-(12,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (11,0)-(11,5) = "class" │ ├── constant_path: │ │ @ ConstantPathNode (location: (11,6)-(11,10)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantReadNode (location: (11,6)-(11,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── name: :B │ │ ├── delimiter_loc: (11,7)-(11,9) = "::" @@ -77,14 +87,18 @@ │ ├── end_keyword_loc: (12,0)-(12,3) = "end" │ └── name: :B ├── @ ClassNode (location: (14,0)-(15,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (14,0)-(14,5) = "class" │ ├── constant_path: │ │ @ ConstantPathNode (location: (14,6)-(14,13)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantPathNode (location: (14,6)-(14,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── parent: │ │ │ │ @ ConstantReadNode (location: (14,6)-(14,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :A │ │ │ ├── name: :B │ │ │ ├── delimiter_loc: (14,7)-(14,9) = "::" @@ -98,29 +112,36 @@ │ ├── end_keyword_loc: (15,0)-(15,3) = "end" │ └── name: :C ├── @ ClassNode (location: (17,0)-(18,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (17,0)-(17,5) = "class" │ ├── constant_path: │ │ @ ConstantReadNode (location: (17,6)-(17,7)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── inheritance_operator_loc: (17,8)-(17,9) = "<" │ ├── superclass: │ │ @ ConstantReadNode (location: (17,10)-(17,11)) + │ │ ├── flags: ∅ │ │ └── name: :B │ ├── body: ∅ │ ├── end_keyword_loc: (18,0)-(18,3) = "end" │ └── name: :A ├── @ ClassNode (location: (20,0)-(21,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (20,0)-(20,5) = "class" │ ├── constant_path: │ │ @ ConstantReadNode (location: (20,6)-(20,7)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── inheritance_operator_loc: (20,8)-(20,9) = "<" │ ├── superclass: │ │ @ ConstantPathNode (location: (20,10)-(20,14)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantReadNode (location: (20,10)-(20,11)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :B │ │ ├── name: :C │ │ ├── delimiter_loc: (20,11)-(20,13) = "::" @@ -129,12 +150,15 @@ │ ├── end_keyword_loc: (21,0)-(21,3) = "end" │ └── name: :A ├── @ ClassNode (location: (23,0)-(24,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (23,0)-(23,5) = "class" │ ├── constant_path: │ │ @ ConstantPathNode (location: (23,6)-(23,10)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantReadNode (location: (23,6)-(23,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── name: :B │ │ ├── delimiter_loc: (23,7)-(23,9) = "::" @@ -142,8 +166,10 @@ │ ├── inheritance_operator_loc: (23,11)-(23,12) = "<" │ ├── superclass: │ │ @ ConstantPathNode (location: (23,13)-(23,17)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantReadNode (location: (23,13)-(23,14)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :C │ │ ├── name: :D │ │ ├── delimiter_loc: (23,14)-(23,16) = "::" @@ -152,18 +178,21 @@ │ ├── end_keyword_loc: (24,0)-(24,3) = "end" │ └── name: :B ├── @ ClassNode (location: (26,0)-(32,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── class_keyword_loc: (26,0)-(26,5) = "class" │ ├── constant_path: │ │ @ ConstantReadNode (location: (26,6)-(26,7)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── inheritance_operator_loc: ∅ │ ├── superclass: ∅ │ ├── body: │ │ @ StatementsNode (location: (27,2)-(31,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 2) │ │ ├── @ CallNode (location: (27,2)-(27,16)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :include @@ -177,6 +206,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ ├── receiver: │ │ │ │ │ @ ConstantReadNode (location: (27,10)-(27,11)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :B │ │ │ │ ├── call_operator_loc: (27,11)-(27,12) = "." │ │ │ │ ├── name: :new @@ -188,15 +218,17 @@ │ │ │ ├── closing_loc: (27,15)-(27,16) = ")" │ │ │ └── block: ∅ │ │ └── @ DefNode (location: (29,2)-(31,5)) + │ │ ├── flags: newline │ │ ├── name: :foo │ │ ├── name_loc: (29,6)-(29,9) = "foo" │ │ ├── receiver: ∅ │ │ ├── parameters: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (30,4)-(30,8)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (30,4)-(30,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (30,4)-(30,5) = ":" │ │ │ ├── value_loc: (30,5)-(30,8) = "bar" │ │ │ ├── closing_loc: ∅ @@ -211,10 +243,12 @@ │ ├── end_keyword_loc: (32,0)-(32,3) = "end" │ └── name: :A └── @ ClassNode (location: (34,0)-(35,3)) + ├── flags: newline ├── locals: [] ├── class_keyword_loc: (34,0)-(34,5) = "class" ├── constant_path: │ @ ConstantPathNode (location: (34,6)-(34,9)) + │ ├── flags: ∅ │ ├── parent: ∅ │ ├── name: :A │ ├── delimiter_loc: (34,6)-(34,8) = "::" diff --git a/test/prism/snapshots/unparser/corpus/literal/def.txt b/test/prism/snapshots/unparser/corpus/literal/def.txt index f3ef6c388e4..d27977cbde6 100644 --- a/test/prism/snapshots/unparser/corpus/literal/def.txt +++ b/test/prism/snapshots/unparser/corpus/literal/def.txt @@ -1,21 +1,26 @@ @ ProgramNode (location: (1,0)-(134,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(134,3)) + ├── flags: ∅ └── body: (length: 30) ├── @ DefNode (location: (1,0)-(9,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (1,4)-(1,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (1,0)-(9,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (2,2)-(2,3)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (2,2)-(2,3)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :a @@ -26,15 +31,17 @@ │ │ │ └── block: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (3,0)-(4,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (3,0)-(3,6) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (4,2)-(4,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (4,2)-(4,3)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :b @@ -43,15 +50,17 @@ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: │ │ │ @ ElseNode (location: (5,0)-(7,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── else_keyword_loc: (5,0)-(5,4) = "else" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (6,2)-(6,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (6,2)-(6,3)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :c @@ -63,12 +72,14 @@ │ │ │ └── end_keyword_loc: (7,0)-(7,6) = "ensure" │ │ ├── ensure_clause: │ │ │ @ EnsureNode (location: (7,0)-(9,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── ensure_keyword_loc: (7,0)-(7,6) = "ensure" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (8,2)-(8,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (8,2)-(8,3)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :d @@ -87,17 +98,21 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (9,0)-(9,3) = "end" ├── @ DefNode (location: (11,0)-(19,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (11,4)-(11,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (11,0)-(19,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (12,2)-(12,12)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ RescueModifierNode (location: (12,2)-(12,12)) + │ │ │ ├── flags: newline │ │ │ ├── expression: │ │ │ │ @ CallNode (location: (12,2)-(12,3)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -123,15 +138,17 @@ │ │ │ └── block: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (13,0)-(14,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (13,0)-(13,6) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (14,2)-(14,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (14,2)-(14,3)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :b @@ -140,15 +157,17 @@ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: │ │ │ @ ElseNode (location: (15,0)-(17,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── else_keyword_loc: (15,0)-(15,4) = "else" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (16,2)-(16,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (16,2)-(16,3)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :c @@ -160,12 +179,14 @@ │ │ │ └── end_keyword_loc: (17,0)-(17,6) = "ensure" │ │ ├── ensure_clause: │ │ │ @ EnsureNode (location: (17,0)-(19,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── ensure_keyword_loc: (17,0)-(17,6) = "ensure" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (18,2)-(18,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (18,2)-(18,3)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :d @@ -184,11 +205,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (19,0)-(19,3) = "end" ├── @ DefNode (location: (21,0)-(22,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (21,4)-(21,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (21,8)-(21,18)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -213,6 +236,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (22,0)-(22,3) = "end" ├── @ DefNode (location: (24,0)-(25,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (24,4)-(24,7) = "foo" │ ├── receiver: ∅ @@ -226,15 +250,17 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (25,0)-(25,3) = "end" ├── @ DefNode (location: (27,0)-(29,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (27,4)-(27,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (28,2)-(28,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (28,2)-(28,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -251,18 +277,21 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (29,0)-(29,3) = "end" ├── @ DefNode (location: (31,0)-(37,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (31,4)-(31,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (31,0)-(37,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (32,2)-(32,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (32,2)-(32,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :foo @@ -273,15 +302,17 @@ │ │ │ └── block: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (33,0)-(34,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (33,0)-(33,6) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (34,2)-(34,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (34,2)-(34,5)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :bar @@ -290,16 +321,18 @@ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: │ │ │ @ EnsureNode (location: (35,0)-(37,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── ensure_keyword_loc: (35,0)-(35,6) = "ensure" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (36,2)-(36,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (36,2)-(36,5)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :baz @@ -318,18 +351,21 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (37,0)-(37,3) = "end" ├── @ DefNode (location: (39,0)-(43,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (39,4)-(39,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (39,0)-(43,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (40,2)-(40,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (40,2)-(40,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -342,12 +378,14 @@ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: │ │ │ @ EnsureNode (location: (41,0)-(43,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── ensure_keyword_loc: (41,0)-(41,6) = "ensure" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (42,2)-(42,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (42,2)-(42,5)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :baz @@ -366,18 +404,21 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (43,0)-(43,3) = "end" ├── @ DefNode (location: (45,0)-(49,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (45,4)-(45,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (45,0)-(49,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (46,2)-(46,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (46,2)-(46,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -388,15 +429,17 @@ │ │ │ └── block: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (47,0)-(48,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (47,0)-(47,6) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (48,2)-(48,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (48,2)-(48,5)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :baz @@ -405,7 +448,7 @@ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (49,0)-(49,3) = "end" @@ -417,11 +460,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (49,0)-(49,3) = "end" ├── @ DefNode (location: (51,0)-(53,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (51,4)-(51,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (51,8)-(51,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (51,8)-(51,11)) │ │ │ ├── flags: ∅ @@ -434,8 +479,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (52,2)-(52,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (52,2)-(52,5)) + │ │ ├── flags: newline │ │ ├── name: :bar │ │ └── depth: 0 │ ├── locals: [:bar] @@ -446,11 +493,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (53,0)-(53,3) = "end" ├── @ DefNode (location: (55,0)-(57,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (55,4)-(55,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (55,8)-(55,16)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (55,8)-(55,11)) │ │ │ │ ├── flags: ∅ @@ -466,8 +515,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (56,2)-(56,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (56,2)-(56,5)) + │ │ ├── flags: newline │ │ ├── name: :bar │ │ └── depth: 0 │ ├── locals: [:bar, :baz] @@ -478,11 +529,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (57,0)-(57,3) = "end" ├── @ DefNode (location: (59,0)-(61,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (59,4)-(59,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (59,8)-(59,16)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (59,8)-(59,16)) @@ -492,6 +545,7 @@ │ │ │ ├── operator_loc: (59,12)-(59,13) = "=" │ │ │ └── value: │ │ │ @ ParenthesesNode (location: (59,14)-(59,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: ∅ │ │ │ ├── opening_loc: (59,14)-(59,15) = "(" │ │ │ └── closing_loc: (59,15)-(59,16) = ")" @@ -502,8 +556,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (60,2)-(60,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (60,2)-(60,5)) + │ │ ├── flags: newline │ │ ├── name: :bar │ │ └── depth: 0 │ ├── locals: [:bar] @@ -514,11 +570,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (61,0)-(61,3) = "end" ├── @ DefNode (location: (63,0)-(64,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (63,4)-(63,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (63,8)-(63,24)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (63,8)-(63,24)) @@ -528,11 +586,13 @@ │ │ │ ├── operator_loc: (63,12)-(63,13) = "=" │ │ │ └── value: │ │ │ @ ParenthesesNode (location: (63,14)-(63,24)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (63,15)-(63,23)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 2) │ │ │ │ ├── @ CallNode (location: (63,15)-(63,18)) - │ │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ │ ├── receiver: ∅ │ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ │ ├── name: :baz @@ -542,6 +602,7 @@ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: ∅ │ │ │ │ └── @ NilNode (location: (63,20)-(63,23)) + │ │ │ │ └── flags: newline, static_literal │ │ │ ├── opening_loc: (63,14)-(63,15) = "(" │ │ │ └── closing_loc: (63,23)-(63,24) = ")" │ │ ├── rest: ∅ @@ -558,11 +619,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (64,0)-(64,3) = "end" ├── @ DefNode (location: (66,0)-(68,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (66,4)-(66,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (66,8)-(66,18)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (66,8)-(66,18)) @@ -572,6 +635,7 @@ │ │ │ ├── operator_loc: (66,12)-(66,13) = "=" │ │ │ └── value: │ │ │ @ TrueNode (location: (66,14)-(66,18)) + │ │ │ └── flags: static_literal │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) @@ -579,8 +643,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (67,2)-(67,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (67,2)-(67,5)) + │ │ ├── flags: newline │ │ ├── name: :bar │ │ └── depth: 0 │ ├── locals: [:bar] @@ -591,11 +657,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (68,0)-(68,3) = "end" ├── @ DefNode (location: (70,0)-(72,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (70,4)-(70,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (70,8)-(70,23)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (70,8)-(70,11)) │ │ │ ├── flags: ∅ @@ -608,6 +676,7 @@ │ │ │ ├── operator_loc: (70,17)-(70,18) = "=" │ │ │ └── value: │ │ │ @ TrueNode (location: (70,19)-(70,23)) + │ │ │ └── flags: static_literal │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) @@ -615,8 +684,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (71,2)-(71,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (71,2)-(71,5)) + │ │ ├── flags: newline │ │ ├── name: :bar │ │ └── depth: 0 │ ├── locals: [:bar, :baz] @@ -627,11 +698,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (72,0)-(72,3) = "end" ├── @ DefNode (location: (74,0)-(75,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (74,4)-(74,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (74,8)-(74,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -643,7 +716,7 @@ │ │ │ ├── name_loc: (74,8)-(74,12) = "bar:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (74,13)-(74,14)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ @@ -656,11 +729,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (75,0)-(75,3) = "end" ├── @ DefNode (location: (77,0)-(78,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (77,4)-(77,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (77,8)-(77,16)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -692,11 +767,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (78,0)-(78,3) = "end" ├── @ DefNode (location: (80,0)-(81,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (80,4)-(80,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (80,8)-(80,18)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -728,11 +805,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (81,0)-(81,3) = "end" ├── @ DefNode (location: (83,0)-(85,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (83,4)-(83,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (83,8)-(83,9)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: @@ -747,9 +826,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (84,2)-(84,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (84,2)-(84,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -766,11 +846,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (85,0)-(85,3) = "end" ├── @ DefNode (location: (87,0)-(89,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (87,4)-(87,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (87,8)-(87,12)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: @@ -785,8 +867,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (88,2)-(88,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (88,2)-(88,5)) + │ │ ├── flags: newline │ │ ├── name: :bar │ │ └── depth: 0 │ ├── locals: [:bar] @@ -797,11 +881,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (89,0)-(89,3) = "end" ├── @ DefNode (location: (91,0)-(93,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (91,4)-(91,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (91,8)-(91,17)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (91,8)-(91,11)) │ │ │ ├── flags: ∅ @@ -819,8 +905,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (92,2)-(92,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (92,2)-(92,5)) + │ │ ├── flags: newline │ │ ├── name: :bar │ │ └── depth: 0 │ ├── locals: [:bar, :baz] @@ -831,11 +919,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (93,0)-(93,3) = "end" ├── @ DefNode (location: (95,0)-(97,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (95,4)-(95,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (95,8)-(95,24)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (95,8)-(95,18)) @@ -845,6 +935,7 @@ │ │ │ ├── operator_loc: (95,12)-(95,13) = "=" │ │ │ └── value: │ │ │ @ TrueNode (location: (95,14)-(95,18)) + │ │ │ └── flags: static_literal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (95,20)-(95,24)) │ │ │ ├── flags: ∅ @@ -857,9 +948,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (96,2)-(96,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (96,2)-(96,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -876,11 +968,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (97,0)-(97,3) = "end" ├── @ DefNode (location: (99,0)-(101,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (99,4)-(99,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (99,8)-(99,32)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (99,8)-(99,18)) @@ -890,6 +984,7 @@ │ │ │ ├── operator_loc: (99,12)-(99,13) = "=" │ │ │ └── value: │ │ │ @ TrueNode (location: (99,14)-(99,18)) + │ │ │ └── flags: static_literal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (99,20)-(99,24)) │ │ │ ├── flags: ∅ @@ -907,9 +1002,10 @@ │ │ └── operator_loc: (99,26)-(99,27) = "&" │ ├── body: │ │ @ StatementsNode (location: (100,2)-(100,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (100,2)-(100,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -926,11 +1022,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (101,0)-(101,3) = "end" ├── @ DefNode (location: (103,0)-(105,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (103,4)-(103,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (103,8)-(103,29)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (103,8)-(103,11)) │ │ │ ├── flags: ∅ @@ -943,6 +1041,7 @@ │ │ │ ├── operator_loc: (103,17)-(103,18) = "=" │ │ │ └── value: │ │ │ @ TrueNode (location: (103,19)-(103,23)) + │ │ │ └── flags: static_literal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (103,25)-(103,29)) │ │ │ ├── flags: ∅ @@ -955,8 +1054,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (104,2)-(104,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (104,2)-(104,5)) + │ │ ├── flags: newline │ │ ├── name: :bar │ │ └── depth: 0 │ ├── locals: [:bar, :baz, :bor] @@ -967,11 +1068,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (105,0)-(105,3) = "end" ├── @ DefNode (location: (107,0)-(109,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (107,4)-(107,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (107,8)-(107,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -986,9 +1089,10 @@ │ │ └── operator_loc: (107,8)-(107,9) = "&" │ ├── body: │ │ @ StatementsNode (location: (108,2)-(108,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (108,2)-(108,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -1005,11 +1109,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (109,0)-(109,3) = "end" ├── @ DefNode (location: (111,0)-(113,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (111,4)-(111,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (111,8)-(111,19)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (111,8)-(111,11)) │ │ │ ├── flags: ∅ @@ -1027,8 +1133,10 @@ │ │ └── operator_loc: (111,13)-(111,14) = "&" │ ├── body: │ │ @ StatementsNode (location: (112,2)-(112,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (112,2)-(112,5)) + │ │ ├── flags: newline │ │ ├── name: :bar │ │ └── depth: 0 │ ├── locals: [:bar, :block] @@ -1039,15 +1147,17 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (113,0)-(113,3) = "end" ├── @ DefNode (location: (115,0)-(118,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (115,4)-(115,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (116,2)-(117,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 2) │ │ ├── @ CallNode (location: (116,2)-(116,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -1057,7 +1167,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ CallNode (location: (117,2)-(117,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :baz @@ -1074,15 +1184,19 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (118,0)-(118,3) = "end" ├── @ DefNode (location: (120,0)-(121,3)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (120,4)-(120,5) = "f" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (120,6)-(120,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ MultiTargetNode (location: (120,6)-(120,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ MultiTargetNode (location: (120,7)-(120,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── lefts: (length: 1) │ │ │ │ │ └── @ RequiredParameterNode (location: (120,8)-(120,9)) │ │ │ │ │ ├── flags: ∅ @@ -1110,11 +1224,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (121,0)-(121,3) = "end" ├── @ DefNode (location: (123,0)-(124,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (123,4)-(123,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (123,8)-(123,26)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -1146,29 +1262,32 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (124,0)-(124,3) = "end" ├── @ DefNode (location: (126,0)-(130,3)) + │ ├── flags: newline │ ├── name: :f │ ├── name_loc: (126,4)-(126,5) = "f" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (127,2)-(127,12)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ InterpolatedStringNode (location: (127,2)-(127,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── opening_loc: (127,2)-(127,12) = "<<-HEREDOC" │ │ ├── parts: (length: 3) │ │ │ ├── @ StringNode (location: (128,0)-(128,4)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (128,0)-(128,4) = " " │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: " " │ │ │ ├── @ EmbeddedStatementsNode (location: (128,4)-(128,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: (128,4)-(128,6) = "\#{" │ │ │ │ ├── statements: ∅ │ │ │ │ └── closing_loc: (128,6)-(128,7) = "}" │ │ │ └── @ StringNode (location: (128,7)-(129,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (128,7)-(129,0) = "\n" │ │ │ ├── closing_loc: ∅ @@ -1182,15 +1301,17 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (130,0)-(130,3) = "end" └── @ DefNode (location: (132,0)-(134,3)) + ├── flags: newline ├── name: :f ├── name_loc: (132,4)-(132,5) = "f" ├── receiver: ∅ ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (133,2)-(133,5)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ StringNode (location: (133,2)-(133,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (133,2)-(133,4) = "%(" │ ├── content_loc: (133,4)-(133,4) = "" │ ├── closing_loc: (133,4)-(133,5) = ")" diff --git a/test/prism/snapshots/unparser/corpus/literal/defined.txt b/test/prism/snapshots/unparser/corpus/literal/defined.txt index 89145ddcda8..d1b5a15685e 100644 --- a/test/prism/snapshots/unparser/corpus/literal/defined.txt +++ b/test/prism/snapshots/unparser/corpus/literal/defined.txt @@ -1,35 +1,47 @@ @ ProgramNode (location: (1,0)-(3,27)) +├── flags: ∅ ├── locals: [:a, :b] └── statements: @ StatementsNode (location: (1,0)-(3,27)) + ├── flags: ∅ └── body: (length: 3) ├── @ DefinedNode (location: (1,0)-(1,14)) + │ ├── flags: newline │ ├── lparen_loc: (1,8)-(1,9) = "(" │ ├── value: │ │ @ InstanceVariableReadNode (location: (1,9)-(1,13)) + │ │ ├── flags: ∅ │ │ └── name: :@foo │ ├── rparen_loc: (1,13)-(1,14) = ")" │ └── keyword_loc: (1,0)-(1,8) = "defined?" ├── @ DefinedNode (location: (2,0)-(2,13)) + │ ├── flags: newline │ ├── lparen_loc: (2,8)-(2,9) = "(" │ ├── value: │ │ @ ConstantReadNode (location: (2,9)-(2,12)) + │ │ ├── flags: ∅ │ │ └── name: :Foo │ ├── rparen_loc: (2,12)-(2,13) = ")" │ └── keyword_loc: (2,0)-(2,8) = "defined?" └── @ DefinedNode (location: (3,0)-(3,27)) + ├── flags: newline ├── lparen_loc: (3,8)-(3,9) = "(" ├── value: │ @ ParenthesesNode (location: (3,9)-(3,26)) + │ ├── flags: ∅ │ ├── body: │ │ @ StatementsNode (location: (3,10)-(3,25)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ MultiWriteNode (location: (3,10)-(3,25)) + │ │ ├── flags: newline │ │ ├── lefts: (length: 2) │ │ │ ├── @ LocalVariableTargetNode (location: (3,11)-(3,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ └── depth: 0 │ │ │ └── @ LocalVariableTargetNode (location: (3,14)-(3,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ └── depth: 0 │ │ ├── rest: ∅ @@ -39,13 +51,13 @@ │ │ ├── operator_loc: (3,17)-(3,18) = "=" │ │ └── value: │ │ @ ArrayNode (location: (3,19)-(3,25)) - │ │ ├── flags: ∅ + │ │ ├── flags: static_literal │ │ ├── elements: (length: 2) │ │ │ ├── @ IntegerNode (location: (3,20)-(3,21)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── @ IntegerNode (location: (3,23)-(3,24)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── opening_loc: (3,19)-(3,20) = "[" │ │ └── closing_loc: (3,24)-(3,25) = "]" diff --git a/test/prism/snapshots/unparser/corpus/literal/defs.txt b/test/prism/snapshots/unparser/corpus/literal/defs.txt index 78588771723..33c24f3b24e 100644 --- a/test/prism/snapshots/unparser/corpus/literal/defs.txt +++ b/test/prism/snapshots/unparser/corpus/literal/defs.txt @@ -1,13 +1,17 @@ @ ProgramNode (location: (1,0)-(40,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(40,3)) + ├── flags: ∅ └── body: (length: 10) ├── @ DefNode (location: (1,0)-(2,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (1,9)-(1,12) = "foo" │ ├── receiver: │ │ @ SelfNode (location: (1,4)-(1,8)) + │ │ └── flags: ∅ │ ├── parameters: ∅ │ ├── body: ∅ │ ├── locals: [] @@ -18,16 +22,19 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (2,0)-(2,3) = "end" ├── @ DefNode (location: (4,0)-(6,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (4,9)-(4,12) = "foo" │ ├── receiver: │ │ @ SelfNode (location: (4,4)-(4,8)) + │ │ └── flags: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (5,2)-(5,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (5,2)-(5,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -44,16 +51,19 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (6,0)-(6,3) = "end" ├── @ DefNode (location: (8,0)-(11,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (8,9)-(8,12) = "foo" │ ├── receiver: │ │ @ SelfNode (location: (8,4)-(8,8)) + │ │ └── flags: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (9,2)-(10,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 2) │ │ ├── @ CallNode (location: (9,2)-(9,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -63,7 +73,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ CallNode (location: (10,2)-(10,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :baz @@ -80,17 +90,20 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (11,0)-(11,3) = "end" ├── @ DefNode (location: (13,0)-(15,3)) + │ ├── flags: newline │ ├── name: :bar │ ├── name_loc: (13,8)-(13,11) = "bar" │ ├── receiver: │ │ @ ConstantReadNode (location: (13,4)-(13,7)) + │ │ ├── flags: ∅ │ │ └── name: :Foo │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (14,2)-(14,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (14,2)-(14,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -107,10 +120,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (15,0)-(15,3) = "end" ├── @ DefNode (location: (17,0)-(20,3)) + │ ├── flags: newline │ ├── name: :bar │ ├── name_loc: (18,3)-(18,6) = "bar" │ ├── receiver: │ │ @ ParenthesesNode (location: (17,4)-(18,2)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ CallNode (location: (17,5)-(18,1)) │ │ │ ├── flags: ignore_visibility @@ -123,11 +138,14 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: │ │ │ @ BlockNode (location: (17,9)-(18,1)) + │ │ │ ├── flags: ∅ │ │ │ ├── locals: [:bar] │ │ │ ├── parameters: │ │ │ │ @ BlockParametersNode (location: (17,11)-(17,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── parameters: │ │ │ │ │ @ ParametersNode (location: (17,12)-(17,15)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ │ └── @ RequiredParameterNode (location: (17,12)-(17,15)) │ │ │ │ │ │ ├── flags: ∅ @@ -149,9 +167,10 @@ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (19,2)-(19,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (19,2)-(19,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -168,10 +187,12 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (20,0)-(20,3) = "end" ├── @ DefNode (location: (22,0)-(24,3)) + │ ├── flags: newline │ ├── name: :bar │ ├── name_loc: (22,13)-(22,16) = "bar" │ ├── receiver: │ │ @ ParenthesesNode (location: (22,4)-(22,12)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ CallNode (location: (22,5)-(22,11)) │ │ │ ├── flags: ignore_visibility @@ -185,7 +206,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (22,9)-(22,10)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── closing_loc: (22,10)-(22,11) = ")" │ │ │ └── block: ∅ @@ -194,9 +215,10 @@ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (23,2)-(23,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (23,2)-(23,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -213,17 +235,21 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (24,0)-(24,3) = "end" ├── @ DefNode (location: (26,0)-(28,3)) + │ ├── flags: newline │ ├── name: :bar │ ├── name_loc: (26,19)-(26,22) = "bar" │ ├── receiver: │ │ @ ParenthesesNode (location: (26,4)-(26,18)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ CallNode (location: (26,5)-(26,17)) │ │ │ ├── flags: ∅ │ │ │ ├── receiver: │ │ │ │ @ ConstantPathNode (location: (26,5)-(26,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── parent: │ │ │ │ │ @ ConstantReadNode (location: (26,5)-(26,8)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :Foo │ │ │ │ ├── name: :Bar │ │ │ │ ├── delimiter_loc: (26,8)-(26,10) = "::" @@ -240,9 +266,10 @@ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (27,2)-(27,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (27,2)-(27,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :baz @@ -259,14 +286,18 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (28,0)-(28,3) = "end" ├── @ DefNode (location: (30,0)-(32,3)) + │ ├── flags: newline │ ├── name: :bar │ ├── name_loc: (30,15)-(30,18) = "bar" │ ├── receiver: │ │ @ ParenthesesNode (location: (30,4)-(30,14)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ ConstantPathNode (location: (30,5)-(30,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── parent: │ │ │ │ @ ConstantReadNode (location: (30,5)-(30,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :Foo │ │ │ ├── name: :Bar │ │ │ ├── delimiter_loc: (30,8)-(30,10) = "::" @@ -276,9 +307,10 @@ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (31,2)-(31,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (31,2)-(31,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :baz @@ -295,17 +327,20 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (32,0)-(32,3) = "end" ├── @ DefNode (location: (34,0)-(36,3)) + │ ├── flags: newline │ ├── name: :bar │ ├── name_loc: (34,8)-(34,11) = "bar" │ ├── receiver: │ │ @ ConstantReadNode (location: (34,4)-(34,7)) + │ │ ├── flags: ∅ │ │ └── name: :Foo │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (35,2)-(35,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (35,2)-(35,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :baz @@ -322,6 +357,7 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (36,0)-(36,3) = "end" └── @ DefNode (location: (38,0)-(40,3)) + ├── flags: newline ├── name: :bar ├── name_loc: (38,8)-(38,11) = "bar" ├── receiver: @@ -338,9 +374,10 @@ ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (39,2)-(39,5)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (39,2)-(39,5)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :baz diff --git a/test/prism/snapshots/unparser/corpus/literal/dstr.txt b/test/prism/snapshots/unparser/corpus/literal/dstr.txt index 8893e8b75d2..64cb3ff1b20 100644 --- a/test/prism/snapshots/unparser/corpus/literal/dstr.txt +++ b/test/prism/snapshots/unparser/corpus/literal/dstr.txt @@ -1,64 +1,74 @@ @ ProgramNode (location: (1,0)-(37,1)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(37,1)) + ├── flags: ∅ └── body: (length: 11) ├── @ IfNode (location: (1,0)-(3,3)) + │ ├── flags: newline │ ├── if_keyword_loc: (1,0)-(1,2) = "if" │ ├── predicate: │ │ @ TrueNode (location: (1,3)-(1,7)) + │ │ └── flags: static_literal │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (2,2)-(2,8)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ InterpolatedStringNode (location: (2,2)-(2,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── opening_loc: (2,2)-(2,3) = "\"" │ │ ├── parts: (length: 2) │ │ │ ├── @ EmbeddedStatementsNode (location: (2,3)-(2,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: (2,3)-(2,5) = "\#{" │ │ │ │ ├── statements: ∅ │ │ │ │ └── closing_loc: (2,5)-(2,6) = "}" │ │ │ └── @ StringNode (location: (2,6)-(2,7)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (2,6)-(2,7) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── closing_loc: (2,7)-(2,8) = "\"" - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: (3,0)-(3,3) = "end" ├── @ IfNode (location: (4,0)-(11,3)) + │ ├── flags: newline │ ├── if_keyword_loc: (4,0)-(4,2) = "if" │ ├── predicate: │ │ @ TrueNode (location: (4,3)-(4,7)) + │ │ └── flags: static_literal │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (5,2)-(10,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 2) │ │ ├── @ InterpolatedStringNode (location: (5,2)-(5,12)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── opening_loc: (5,2)-(5,12) = "<<-HEREDOC" │ │ │ ├── parts: (length: 3) │ │ │ │ ├── @ StringNode (location: (6,0)-(7,0)) - │ │ │ │ │ ├── flags: frozen + │ │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── content_loc: (6,0)-(7,0) = "a\n" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "a\n" │ │ │ │ ├── @ EmbeddedStatementsNode (location: (7,0)-(7,3)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── opening_loc: (7,0)-(7,2) = "\#{" │ │ │ │ │ ├── statements: ∅ │ │ │ │ │ └── closing_loc: (7,2)-(7,3) = "}" │ │ │ │ └── @ StringNode (location: (7,3)-(9,0)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (7,3)-(9,0) = "a\nb\n" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "a\nb\n" │ │ │ └── closing_loc: (9,0)-(10,0) = " HEREDOC\n" │ │ └── @ CallNode (location: (10,2)-(10,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :x @@ -67,61 +77,66 @@ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: (11,0)-(11,3) = "end" ├── @ InterpolatedStringNode (location: (12,0)-(12,10)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (12,0)-(12,10) = "<<-HEREDOC" │ ├── parts: (length: 7) │ │ ├── @ StringNode (location: (13,0)-(14,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (13,0)-(14,0) = "\\\#{}\\\#{}\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\#{}\#{}\n" │ │ ├── @ EmbeddedStatementsNode (location: (14,0)-(14,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (14,0)-(14,2) = "\#{" │ │ │ ├── statements: ∅ │ │ │ └── closing_loc: (14,2)-(14,3) = "}" │ │ ├── @ StringNode (location: (14,3)-(15,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (14,3)-(15,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" │ │ ├── @ EmbeddedStatementsNode (location: (15,0)-(15,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (15,0)-(15,2) = "\#{" │ │ │ ├── statements: ∅ │ │ │ └── closing_loc: (15,2)-(15,3) = "}" │ │ ├── @ StringNode (location: (15,3)-(16,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (15,3)-(16,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" │ │ ├── @ EmbeddedStatementsNode (location: (16,0)-(16,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (16,0)-(16,2) = "\#{" │ │ │ ├── statements: ∅ │ │ │ └── closing_loc: (16,2)-(16,3) = "}" │ │ └── @ StringNode (location: (16,3)-(17,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (16,3)-(17,0) = "\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\n" │ └── closing_loc: (17,0)-(18,0) = "HEREDOC\n" ├── @ RescueModifierNode (location: (18,0)-(18,21)) + │ ├── flags: newline │ ├── expression: │ │ @ InterpolatedStringNode (location: (18,0)-(18,10)) │ │ ├── flags: ∅ │ │ ├── opening_loc: (18,0)-(18,10) = "<<-HEREDOC" │ │ ├── parts: (length: 2) │ │ │ ├── @ EmbeddedStatementsNode (location: (19,0)-(19,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: (19,0)-(19,2) = "\#{" │ │ │ │ ├── statements: ∅ │ │ │ │ └── closing_loc: (19,2)-(19,3) = "}" │ │ │ └── @ StringNode (location: (19,3)-(21,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (19,3)-(21,0) = "\na\n" │ │ │ ├── closing_loc: ∅ @@ -130,80 +145,92 @@ │ ├── keyword_loc: (18,11)-(18,17) = "rescue" │ └── rescue_expression: │ @ NilNode (location: (18,18)-(18,21)) + │ └── flags: static_literal ├── @ InterpolatedStringNode (location: (22,0)-(22,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (22,0)-(22,1) = "\"" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (22,1)-(22,2)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (22,1)-(22,2) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ EmbeddedVariableNode (location: (22,2)-(22,5)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (22,2)-(22,3) = "#" │ │ └── variable: │ │ @ NumberedReferenceReadNode (location: (22,3)-(22,5)) + │ │ ├── flags: ∅ │ │ └── number: 1 │ └── closing_loc: (22,5)-(22,6) = "\"" ├── @ InterpolatedStringNode (location: (23,0)-(23,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (23,0)-(23,1) = "\"" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (23,1)-(23,2)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (23,1)-(23,2) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ EmbeddedVariableNode (location: (23,2)-(23,5)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (23,2)-(23,3) = "#" │ │ └── variable: │ │ @ GlobalVariableReadNode (location: (23,3)-(23,5)) + │ │ ├── flags: ∅ │ │ └── name: :$a │ └── closing_loc: (23,5)-(23,6) = "\"" ├── @ InterpolatedStringNode (location: (24,0)-(24,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (24,0)-(24,1) = "\"" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (24,1)-(24,2)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (24,1)-(24,2) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ EmbeddedVariableNode (location: (24,2)-(24,5)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (24,2)-(24,3) = "#" │ │ └── variable: │ │ @ InstanceVariableReadNode (location: (24,3)-(24,5)) + │ │ ├── flags: ∅ │ │ └── name: :@a │ └── closing_loc: (24,5)-(24,6) = "\"" ├── @ InterpolatedStringNode (location: (25,0)-(25,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (25,0)-(25,1) = "\"" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (25,1)-(25,2)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (25,1)-(25,2) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ EmbeddedVariableNode (location: (25,2)-(25,6)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (25,2)-(25,3) = "#" │ │ └── variable: │ │ @ ClassVariableReadNode (location: (25,3)-(25,6)) + │ │ ├── flags: ∅ │ │ └── name: :@@a │ └── closing_loc: (25,6)-(25,7) = "\"" ├── @ IfNode (location: (26,0)-(30,3)) + │ ├── flags: newline │ ├── if_keyword_loc: (26,0)-(26,2) = "if" │ ├── predicate: │ │ @ TrueNode (location: (26,3)-(26,7)) + │ │ └── flags: static_literal │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (27,2)-(27,19)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ ReturnNode (location: (27,2)-(27,19)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── keyword_loc: (27,2)-(27,8) = "return" │ │ └── arguments: │ │ @ ArgumentsNode (location: (27,9)-(27,19)) @@ -214,31 +241,33 @@ │ │ ├── opening_loc: (27,9)-(27,19) = "<<-HEREDOC" │ │ ├── parts: (length: 3) │ │ │ ├── @ StringNode (location: (28,0)-(28,4)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (28,0)-(28,4) = " " │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: " " │ │ │ ├── @ EmbeddedStatementsNode (location: (28,4)-(28,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: (28,4)-(28,6) = "\#{" │ │ │ │ ├── statements: │ │ │ │ │ @ StatementsNode (location: (28,6)-(28,8)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (28,6)-(28,8)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 42 │ │ │ │ └── closing_loc: (28,8)-(28,9) = "}" │ │ │ └── @ StringNode (location: (28,9)-(29,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (28,9)-(29,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" │ │ └── closing_loc: (29,0)-(30,0) = " HEREDOC\n" - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: (30,0)-(30,3) = "end" ├── @ CallNode (location: (31,0)-(31,15)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -253,15 +282,17 @@ │ │ ├── opening_loc: (31,4)-(31,14) = "<<-HEREDOC" │ │ ├── parts: (length: 3) │ │ │ ├── @ StringNode (location: (32,0)-(32,2)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (32,0)-(32,2) = " " │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: " " │ │ │ ├── @ EmbeddedStatementsNode (location: (32,2)-(32,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: (32,2)-(32,4) = "\#{" │ │ │ │ ├── statements: │ │ │ │ │ @ StatementsNode (location: (32,4)-(32,7)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ CallNode (location: (32,4)-(32,7)) │ │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -275,7 +306,7 @@ │ │ │ │ │ └── block: ∅ │ │ │ │ └── closing_loc: (32,7)-(32,8) = "}" │ │ │ └── @ StringNode (location: (32,8)-(33,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (32,8)-(33,0) = "\n" │ │ │ ├── closing_loc: ∅ @@ -284,7 +315,7 @@ │ ├── closing_loc: (31,14)-(31,15) = ")" │ └── block: ∅ └── @ CallNode (location: (34,0)-(37,1)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :foo @@ -299,15 +330,17 @@ │ ├── opening_loc: (34,4)-(34,14) = "<<-HEREDOC" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (35,0)-(35,2)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (35,0)-(35,2) = " " │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: " " │ │ ├── @ EmbeddedStatementsNode (location: (35,2)-(35,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (35,2)-(35,4) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (35,4)-(35,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (35,4)-(35,7)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -321,7 +354,7 @@ │ │ │ │ └── block: ∅ │ │ │ └── closing_loc: (35,7)-(35,8) = "}" │ │ └── @ StringNode (location: (35,8)-(36,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (35,8)-(36,0) = "\n" │ │ ├── closing_loc: ∅ @@ -330,11 +363,14 @@ ├── closing_loc: (34,14)-(34,15) = ")" └── block: @ BlockNode (location: (34,16)-(37,1)) + ├── flags: ∅ ├── locals: [:x] ├── parameters: │ @ BlockParametersNode (location: (34,18)-(34,21)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (34,19)-(34,20)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (34,19)-(34,20)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/empty.txt b/test/prism/snapshots/unparser/corpus/literal/empty.txt index 3a21ce5559c..5756285aaf2 100644 --- a/test/prism/snapshots/unparser/corpus/literal/empty.txt +++ b/test/prism/snapshots/unparser/corpus/literal/empty.txt @@ -1,5 +1,7 @@ @ ProgramNode (location: (1,0)-(1,0)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,0)) + ├── flags: ∅ └── body: (length: 0) diff --git a/test/prism/snapshots/unparser/corpus/literal/empty_begin.txt b/test/prism/snapshots/unparser/corpus/literal/empty_begin.txt index 838b4bf6f04..25dc0b26a21 100644 --- a/test/prism/snapshots/unparser/corpus/literal/empty_begin.txt +++ b/test/prism/snapshots/unparser/corpus/literal/empty_begin.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(1,2)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,2)) + ├── flags: ∅ └── body: (length: 1) └── @ ParenthesesNode (location: (1,0)-(1,2)) + ├── flags: newline ├── body: ∅ ├── opening_loc: (1,0)-(1,1) = "(" └── closing_loc: (1,1)-(1,2) = ")" diff --git a/test/prism/snapshots/unparser/corpus/literal/flipflop.txt b/test/prism/snapshots/unparser/corpus/literal/flipflop.txt index 2d9f669e6f1..418aa242cbe 100644 --- a/test/prism/snapshots/unparser/corpus/literal/flipflop.txt +++ b/test/prism/snapshots/unparser/corpus/literal/flipflop.txt @@ -1,24 +1,31 @@ @ ProgramNode (location: (1,0)-(10,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(10,3)) + ├── flags: ∅ └── body: (length: 4) ├── @ IfNode (location: (1,0)-(3,3)) + │ ├── flags: newline │ ├── if_keyword_loc: (1,0)-(1,2) = "if" │ ├── predicate: │ │ @ ParenthesesNode (location: (1,3)-(1,23)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (1,4)-(1,22)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ FlipFlopNode (location: (1,4)-(1,22)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── left: │ │ │ │ @ ParenthesesNode (location: (1,4)-(1,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── body: │ │ │ │ │ @ StatementsNode (location: (1,5)-(1,11)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ CallNode (location: (1,5)-(1,11)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: newline │ │ │ │ │ ├── receiver: │ │ │ │ │ │ @ CallNode (location: (1,5)-(1,6)) │ │ │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -39,7 +46,7 @@ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ │ └── value: 4 │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: ∅ @@ -47,11 +54,13 @@ │ │ │ │ └── closing_loc: (1,11)-(1,12) = ")" │ │ │ ├── right: │ │ │ │ @ ParenthesesNode (location: (1,14)-(1,22)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── body: │ │ │ │ │ @ StatementsNode (location: (1,15)-(1,21)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ CallNode (location: (1,15)-(1,21)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: newline │ │ │ │ │ ├── receiver: │ │ │ │ │ │ @ CallNode (location: (1,15)-(1,16)) │ │ │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -72,7 +81,7 @@ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ │ └── @ IntegerNode (location: (1,20)-(1,21)) - │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ │ └── value: 4 │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: ∅ @@ -84,9 +93,10 @@ │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (2,2)-(2,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (2,2)-(2,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo @@ -95,24 +105,29 @@ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: (3,0)-(3,3) = "end" ├── @ IfNode (location: (4,0)-(6,3)) + │ ├── flags: newline │ ├── if_keyword_loc: (4,0)-(4,2) = "if" │ ├── predicate: │ │ @ ParenthesesNode (location: (4,3)-(4,24)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (4,4)-(4,23)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ FlipFlopNode (location: (4,4)-(4,23)) - │ │ │ ├── flags: exclude_end + │ │ │ ├── flags: newline, exclude_end │ │ │ ├── left: │ │ │ │ @ ParenthesesNode (location: (4,4)-(4,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── body: │ │ │ │ │ @ StatementsNode (location: (4,5)-(4,11)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ CallNode (location: (4,5)-(4,11)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: newline │ │ │ │ │ ├── receiver: │ │ │ │ │ │ @ CallNode (location: (4,5)-(4,6)) │ │ │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -133,7 +148,7 @@ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ │ └── @ IntegerNode (location: (4,10)-(4,11)) - │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ │ └── value: 4 │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: ∅ @@ -141,11 +156,13 @@ │ │ │ │ └── closing_loc: (4,11)-(4,12) = ")" │ │ │ ├── right: │ │ │ │ @ ParenthesesNode (location: (4,15)-(4,23)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── body: │ │ │ │ │ @ StatementsNode (location: (4,16)-(4,22)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ CallNode (location: (4,16)-(4,22)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: newline │ │ │ │ │ ├── receiver: │ │ │ │ │ │ @ CallNode (location: (4,16)-(4,17)) │ │ │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -166,7 +183,7 @@ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ │ └── @ IntegerNode (location: (4,21)-(4,22)) - │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ │ └── value: 4 │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: ∅ @@ -178,9 +195,10 @@ │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (5,2)-(5,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (5,2)-(5,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo @@ -189,9 +207,10 @@ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: (6,0)-(6,3) = "end" ├── @ IfNode (location: (7,0)-(8,3)) + │ ├── flags: newline │ ├── if_keyword_loc: (7,0)-(7,2) = "if" │ ├── predicate: │ │ @ FlipFlopNode (location: (7,3)-(7,8)) @@ -211,9 +230,10 @@ │ │ └── operator_loc: (7,3)-(7,5) = ".." │ ├── then_keyword_loc: ∅ │ ├── statements: ∅ - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: (8,0)-(8,3) = "end" └── @ IfNode (location: (9,0)-(10,3)) + ├── flags: newline ├── if_keyword_loc: (9,0)-(9,2) = "if" ├── predicate: │ @ FlipFlopNode (location: (9,3)-(9,8)) @@ -233,5 +253,5 @@ │ └── operator_loc: (9,6)-(9,8) = ".." ├── then_keyword_loc: ∅ ├── statements: ∅ - ├── consequent: ∅ + ├── subsequent: ∅ └── end_keyword_loc: (10,0)-(10,3) = "end" diff --git a/test/prism/snapshots/unparser/corpus/literal/for.txt b/test/prism/snapshots/unparser/corpus/literal/for.txt index 660c6b73f3f..a1722a8a099 100644 --- a/test/prism/snapshots/unparser/corpus/literal/for.txt +++ b/test/prism/snapshots/unparser/corpus/literal/for.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(12,3)) +├── flags: ∅ ├── locals: [:a, :b] └── statements: @ StatementsNode (location: (1,0)-(12,3)) + ├── flags: ∅ └── body: (length: 4) ├── @ CallNode (location: (1,0)-(3,4)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :bar @@ -15,8 +17,10 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ ForNode (location: (1,4)-(3,3)) + │ │ ├── flags: ∅ │ │ ├── index: │ │ │ @ LocalVariableTargetNode (location: (1,8)-(1,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── collection: @@ -32,9 +36,10 @@ │ │ │ └── block: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (2,2)-(2,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (2,2)-(2,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz @@ -50,8 +55,10 @@ │ ├── closing_loc: (3,3)-(3,4) = ")" │ └── block: ∅ ├── @ ForNode (location: (4,0)-(6,3)) + │ ├── flags: newline │ ├── index: │ │ @ LocalVariableTargetNode (location: (4,4)-(4,5)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── collection: @@ -67,9 +74,10 @@ │ │ └── block: ∅ │ ├── statements: │ │ @ StatementsNode (location: (5,2)-(5,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (5,2)-(5,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :baz @@ -83,17 +91,22 @@ │ ├── do_keyword_loc: (4,13)-(4,15) = "do" │ └── end_keyword_loc: (6,0)-(6,3) = "end" ├── @ ForNode (location: (7,0)-(9,3)) + │ ├── flags: newline │ ├── index: │ │ @ MultiTargetNode (location: (7,4)-(7,11)) + │ │ ├── flags: ∅ │ │ ├── lefts: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (7,5)-(7,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── rest: │ │ │ @ SplatNode (location: (7,8)-(7,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (7,8)-(7,9) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableTargetNode (location: (7,9)-(7,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ └── depth: 0 │ │ ├── rights: (length: 0) @@ -112,9 +125,10 @@ │ │ └── block: ∅ │ ├── statements: │ │ @ StatementsNode (location: (8,2)-(8,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (8,2)-(8,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :baz @@ -128,13 +142,17 @@ │ ├── do_keyword_loc: (7,19)-(7,21) = "do" │ └── end_keyword_loc: (9,0)-(9,3) = "end" └── @ ForNode (location: (10,0)-(12,3)) + ├── flags: newline ├── index: │ @ MultiTargetNode (location: (10,4)-(10,10)) + │ ├── flags: ∅ │ ├── lefts: (length: 2) │ │ ├── @ LocalVariableTargetNode (location: (10,5)-(10,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ └── @ LocalVariableTargetNode (location: (10,8)-(10,9)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ └── depth: 0 │ ├── rest: ∅ @@ -154,9 +172,10 @@ │ └── block: ∅ ├── statements: │ @ StatementsNode (location: (11,2)-(11,5)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (11,2)-(11,5)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :baz diff --git a/test/prism/snapshots/unparser/corpus/literal/hookexe.txt b/test/prism/snapshots/unparser/corpus/literal/hookexe.txt index dabedbc5885..bbcb8fee1b0 100644 --- a/test/prism/snapshots/unparser/corpus/literal/hookexe.txt +++ b/test/prism/snapshots/unparser/corpus/literal/hookexe.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(7,1)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(7,1)) + ├── flags: ∅ └── body: (length: 3) ├── @ PreExecutionNode (location: (1,0)-(3,1)) + │ ├── flags: newline │ ├── statements: │ │ @ StatementsNode (location: (2,2)-(2,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (2,2)-(2,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo @@ -21,7 +25,7 @@ │ ├── opening_loc: (1,6)-(1,7) = "{" │ └── closing_loc: (3,0)-(3,1) = "}" ├── @ CallNode (location: (4,0)-(4,3)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :bar @@ -31,11 +35,13 @@ │ ├── closing_loc: ∅ │ └── block: ∅ └── @ PostExecutionNode (location: (5,0)-(7,1)) + ├── flags: newline ├── statements: │ @ StatementsNode (location: (6,2)-(6,5)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (6,2)-(6,5)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :baz diff --git a/test/prism/snapshots/unparser/corpus/literal/if.txt b/test/prism/snapshots/unparser/corpus/literal/if.txt index 00eeba179c6..10240962c59 100644 --- a/test/prism/snapshots/unparser/corpus/literal/if.txt +++ b/test/prism/snapshots/unparser/corpus/literal/if.txt @@ -1,13 +1,16 @@ @ ProgramNode (location: (1,0)-(36,3)) +├── flags: ∅ ├── locals: [:foo, :pair] └── statements: @ StatementsNode (location: (1,0)-(36,3)) + ├── flags: ∅ └── body: (length: 10) ├── @ IfNode (location: (1,0)-(3,3)) + │ ├── flags: newline │ ├── if_keyword_loc: (1,0)-(1,2) = "if" │ ├── predicate: │ │ @ MatchLastLineNode (location: (1,3)-(1,8)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,3)-(1,4) = "/" │ │ ├── content_loc: (1,4)-(1,7) = "foo" │ │ ├── closing_loc: (1,7)-(1,8) = "/" @@ -15,9 +18,10 @@ │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (2,2)-(2,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (2,2)-(2,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -26,76 +30,88 @@ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: (3,0)-(3,3) = "end" ├── @ IfNode (location: (4,0)-(6,3)) + │ ├── flags: newline │ ├── if_keyword_loc: (4,0)-(4,2) = "if" │ ├── predicate: │ │ @ IntegerNode (location: (4,3)-(4,4)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (5,2)-(5,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (5,2)-(5,3)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 9 - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: (6,0)-(6,3) = "end" ├── @ IfNode (location: (7,0)-(11,3)) + │ ├── flags: newline │ ├── if_keyword_loc: (7,0)-(7,2) = "if" │ ├── predicate: │ │ @ IntegerNode (location: (7,3)-(7,4)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 4 │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (8,2)-(8,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (8,2)-(8,3)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 5 - │ ├── consequent: + │ ├── subsequent: │ │ @ ElseNode (location: (9,0)-(11,3)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (9,0)-(9,4) = "else" │ │ ├── statements: │ │ │ @ StatementsNode (location: (10,2)-(10,3)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (10,2)-(10,3)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: newline, static_literal, decimal │ │ │ └── value: 6 │ │ └── end_keyword_loc: (11,0)-(11,3) = "end" │ └── end_keyword_loc: (11,0)-(11,3) = "end" ├── @ UnlessNode (location: (12,0)-(14,3)) + │ ├── flags: newline │ ├── keyword_loc: (12,0)-(12,6) = "unless" │ ├── predicate: │ │ @ IntegerNode (location: (12,7)-(12,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (13,2)-(13,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ NilNode (location: (13,2)-(13,5)) - │ ├── consequent: ∅ + │ │ └── flags: newline, static_literal + │ ├── else_clause: ∅ │ └── end_keyword_loc: (14,0)-(14,3) = "end" ├── @ UnlessNode (location: (15,0)-(17,3)) + │ ├── flags: newline │ ├── keyword_loc: (15,0)-(15,6) = "unless" │ ├── predicate: │ │ @ IntegerNode (location: (15,7)-(15,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (16,2)-(16,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (16,2)-(16,3)) - │ │ ├── flags: decimal + │ │ ├── flags: newline, static_literal, decimal │ │ └── value: 9 - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ └── end_keyword_loc: (17,0)-(17,3) = "end" ├── @ IfNode (location: (18,0)-(19,3)) + │ ├── flags: newline │ ├── if_keyword_loc: (18,0)-(18,2) = "if" │ ├── predicate: │ │ @ CallNode (location: (18,3)-(18,6)) @@ -110,28 +126,35 @@ │ │ └── block: ∅ │ ├── then_keyword_loc: ∅ │ ├── statements: ∅ - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: (19,0)-(19,3) = "end" ├── @ ModuleNode (location: (21,0)-(23,3)) + │ ├── flags: newline │ ├── locals: [:foo] │ ├── module_keyword_loc: (21,0)-(21,6) = "module" │ ├── constant_path: │ │ @ ConstantReadNode (location: (21,7)-(21,8)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── body: │ │ @ StatementsNode (location: (22,2)-(22,18)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IfNode (location: (22,2)-(22,18)) + │ │ ├── flags: newline │ │ ├── if_keyword_loc: (22,12)-(22,14) = "if" │ │ ├── predicate: │ │ │ @ LocalVariableReadNode (location: (22,15)-(22,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :foo │ │ │ └── depth: 0 │ │ ├── then_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (22,2)-(22,11)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ LocalVariableWriteNode (location: (22,2)-(22,11)) + │ │ │ ├── flags: newline │ │ │ ├── name: :foo │ │ │ ├── depth: 0 │ │ │ ├── name_loc: (22,2)-(22,5) = "foo" @@ -147,30 +170,37 @@ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ └── operator_loc: (22,6)-(22,7) = "=" - │ │ ├── consequent: ∅ + │ │ ├── subsequent: ∅ │ │ └── end_keyword_loc: ∅ │ ├── end_keyword_loc: (23,0)-(23,3) = "end" │ └── name: :A ├── @ ModuleNode (location: (25,0)-(27,3)) + │ ├── flags: newline │ ├── locals: [:foo] │ ├── module_keyword_loc: (25,0)-(25,6) = "module" │ ├── constant_path: │ │ @ ConstantReadNode (location: (25,7)-(25,8)) + │ │ ├── flags: ∅ │ │ └── name: :B │ ├── body: │ │ @ StatementsNode (location: (26,2)-(26,22)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ UnlessNode (location: (26,2)-(26,22)) + │ │ ├── flags: newline │ │ ├── keyword_loc: (26,12)-(26,18) = "unless" │ │ ├── predicate: │ │ │ @ LocalVariableReadNode (location: (26,19)-(26,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :foo │ │ │ └── depth: 0 │ │ ├── then_keyword_loc: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (26,2)-(26,11)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ LocalVariableWriteNode (location: (26,2)-(26,11)) + │ │ │ ├── flags: newline │ │ │ ├── name: :foo │ │ │ ├── depth: 0 │ │ │ ├── name_loc: (26,2)-(26,5) = "foo" @@ -186,11 +216,12 @@ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ └── operator_loc: (26,6)-(26,7) = "=" - │ │ ├── consequent: ∅ + │ │ ├── else_clause: ∅ │ │ └── end_keyword_loc: ∅ │ ├── end_keyword_loc: (27,0)-(27,3) = "end" │ └── name: :B ├── @ UnlessNode (location: (28,0)-(30,3)) + │ ├── flags: newline │ ├── keyword_loc: (28,0)-(28,6) = "unless" │ ├── predicate: │ │ @ CallNode (location: (28,7)-(28,10)) @@ -206,8 +237,10 @@ │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (29,2)-(29,11)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableWriteNode (location: (29,2)-(29,11)) + │ │ ├── flags: newline │ │ ├── name: :foo │ │ ├── depth: 0 │ │ ├── name_loc: (29,2)-(29,5) = "foo" @@ -223,9 +256,10 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── operator_loc: (29,6)-(29,7) = "=" - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ └── end_keyword_loc: (30,0)-(30,3) = "end" └── @ IfNode (location: (31,0)-(36,3)) + ├── flags: newline ├── if_keyword_loc: (31,0)-(31,2) = "if" ├── predicate: │ @ CallNode (location: (31,3)-(33,1)) @@ -239,11 +273,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (31,7)-(33,1)) + │ ├── flags: ∅ │ ├── locals: [:pair] │ ├── parameters: │ │ @ BlockParametersNode (location: (31,9)-(31,15)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (31,10)-(31,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (31,10)-(31,14)) │ │ │ │ ├── flags: ∅ @@ -259,8 +296,10 @@ │ │ └── closing_loc: (31,14)-(31,15) = "|" │ ├── body: │ │ @ StatementsNode (location: (32,2)-(32,6)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (32,2)-(32,6)) + │ │ ├── flags: newline │ │ ├── name: :pair │ │ └── depth: 0 │ ├── opening_loc: (31,7)-(31,8) = "{" @@ -268,21 +307,24 @@ ├── then_keyword_loc: ∅ ├── statements: │ @ StatementsNode (location: (34,2)-(35,5)) + │ ├── flags: ∅ │ └── body: (length: 2) │ ├── @ LocalVariableWriteNode (location: (34,2)-(34,13)) + │ │ ├── flags: newline │ │ ├── name: :pair │ │ ├── depth: 0 │ │ ├── name_loc: (34,2)-(34,6) = "pair" │ │ ├── value: │ │ │ @ SymbolNode (location: (34,9)-(34,13)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (34,9)-(34,10) = ":" │ │ │ ├── value_loc: (34,10)-(34,13) = "foo" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "foo" │ │ └── operator_loc: (34,7)-(34,8) = "=" │ └── @ LocalVariableReadNode (location: (35,2)-(35,5)) + │ ├── flags: newline │ ├── name: :foo │ └── depth: 0 - ├── consequent: ∅ + ├── subsequent: ∅ └── end_keyword_loc: (36,0)-(36,3) = "end" diff --git a/test/prism/snapshots/unparser/corpus/literal/kwbegin.txt b/test/prism/snapshots/unparser/corpus/literal/kwbegin.txt index 48e53af00e4..9c7febe206b 100644 --- a/test/prism/snapshots/unparser/corpus/literal/kwbegin.txt +++ b/test/prism/snapshots/unparser/corpus/literal/kwbegin.txt @@ -1,40 +1,48 @@ @ ProgramNode (location: (1,0)-(80,3)) +├── flags: ∅ ├── locals: [:foo, :bar, :exception] └── statements: @ StatementsNode (location: (1,0)-(80,3)) + ├── flags: ∅ └── body: (length: 14) ├── @ BeginNode (location: (1,0)-(3,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (1,0)-(1,5) = "begin" │ ├── statements: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (2,0)-(2,6)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (2,0)-(2,6) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (3,0)-(3,3) = "end" ├── @ BeginNode (location: (5,0)-(7,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (5,0)-(5,5) = "begin" │ ├── statements: ∅ │ ├── rescue_clause: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: │ │ @ EnsureNode (location: (6,0)-(7,3)) + │ │ ├── flags: ∅ │ │ ├── ensure_keyword_loc: (6,0)-(6,6) = "ensure" │ │ ├── statements: ∅ │ │ └── end_keyword_loc: (7,0)-(7,3) = "end" │ └── end_keyword_loc: (7,0)-(7,3) = "end" ├── @ BeginNode (location: (9,0)-(11,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (9,0)-(9,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (10,2)-(10,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (10,2)-(10,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -48,12 +56,14 @@ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (11,0)-(11,3) = "end" ├── @ BeginNode (location: (13,0)-(17,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (13,0)-(13,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (14,2)-(14,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (14,2)-(14,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -64,15 +74,17 @@ │ │ └── block: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (15,0)-(16,3)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (15,0)-(15,6) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (16,2)-(16,3)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (16,2)-(16,3)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -81,17 +93,19 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (17,0)-(17,3) = "end" ├── @ BeginNode (location: (19,0)-(24,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (19,0)-(19,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (20,2)-(21,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 2) │ │ ├── @ CallNode (location: (20,2)-(20,3)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :a @@ -101,7 +115,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ CallNode (location: (21,2)-(21,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :b @@ -112,15 +126,17 @@ │ │ └── block: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (22,0)-(23,3)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (22,0)-(22,6) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (23,2)-(23,3)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (23,2)-(23,3)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -129,52 +145,61 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (24,0)-(24,3) = "end" ├── @ BeginNode (location: (26,0)-(28,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (26,0)-(26,5) = "begin" │ ├── statements: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (27,0)-(27,8)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (27,0)-(27,6) = "rescue" │ │ ├── exceptions: (length: 1) │ │ │ └── @ ConstantReadNode (location: (27,7)-(27,8)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (28,0)-(28,3) = "end" ├── @ BeginNode (location: (30,0)-(32,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (30,0)-(30,5) = "begin" │ ├── statements: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (31,0)-(31,15)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (31,0)-(31,6) = "rescue" │ │ ├── exceptions: (length: 1) │ │ │ └── @ ConstantReadNode (location: (31,7)-(31,8)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── operator_loc: (31,9)-(31,11) = "=>" │ │ ├── reference: │ │ │ @ LocalVariableTargetNode (location: (31,12)-(31,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :foo │ │ │ └── depth: 0 │ │ ├── statements: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (32,0)-(32,3) = "end" ├── @ BeginNode (location: (34,0)-(42,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (34,0)-(34,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (35,2)-(35,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (35,2)-(35,3)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a @@ -185,17 +210,20 @@ │ │ └── block: ∅ │ ├── rescue_clause: │ │ @ RescueNode (location: (36,0)-(39,3)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (36,0)-(36,6) = "rescue" │ │ ├── exceptions: (length: 1) │ │ │ └── @ ConstantReadNode (location: (36,7)-(36,8)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (37,2)-(37,3)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (37,2)-(37,3)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b @@ -204,19 +232,22 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: + │ │ └── subsequent: │ │ @ RescueNode (location: (38,0)-(39,3)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (38,0)-(38,6) = "rescue" │ │ ├── exceptions: (length: 1) │ │ │ └── @ ConstantReadNode (location: (38,7)-(38,8)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :B │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (39,2)-(39,3)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (39,2)-(39,3)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :c @@ -225,16 +256,18 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: │ │ @ EnsureNode (location: (40,0)-(42,3)) + │ │ ├── flags: ∅ │ │ ├── ensure_keyword_loc: (40,0)-(40,6) = "ensure" │ │ ├── statements: │ │ │ @ StatementsNode (location: (41,2)-(41,3)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (41,2)-(41,3)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :d @@ -246,20 +279,25 @@ │ │ └── end_keyword_loc: (42,0)-(42,3) = "end" │ └── end_keyword_loc: (42,0)-(42,3) = "end" ├── @ BeginNode (location: (44,0)-(53,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (44,0)-(44,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (45,2)-(49,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ BeginNode (location: (45,2)-(49,5)) + │ │ ├── flags: newline │ │ ├── begin_keyword_loc: (45,2)-(45,7) = "begin" │ │ ├── statements: │ │ │ @ StatementsNode (location: (46,4)-(47,7)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 2) │ │ │ ├── @ LocalVariableReadNode (location: (46,4)-(46,7)) + │ │ │ │ ├── flags: newline │ │ │ │ ├── name: :foo │ │ │ │ └── depth: 0 │ │ │ └── @ CallNode (location: (47,4)-(47,7)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -270,26 +308,29 @@ │ │ │ └── block: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (48,2)-(48,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (48,2)-(48,8) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (49,2)-(49,5) = "end" │ ├── rescue_clause: │ │ @ RescueNode (location: (50,0)-(52,5)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (50,0)-(50,6) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: │ │ │ @ StatementsNode (location: (51,2)-(52,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 2) │ │ │ ├── @ CallNode (location: (51,2)-(51,5)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :baz @@ -299,7 +340,7 @@ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ └── @ CallNode (location: (52,2)-(52,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -308,16 +349,19 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (53,0)-(53,3) = "end" ├── @ BeginNode (location: (55,0)-(58,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (55,0)-(55,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (56,2)-(56,35)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RescueModifierNode (location: (56,2)-(56,35)) + │ │ ├── flags: newline │ │ ├── expression: │ │ │ @ CallNode (location: (56,2)-(56,18)) │ │ │ ├── flags: ignore_visibility @@ -331,12 +375,14 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ ConstantReadNode (location: (56,8)-(56,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :Exception │ │ │ ├── closing_loc: (56,17)-(56,18) = ")" │ │ │ └── block: ∅ │ │ ├── keyword_loc: (56,19)-(56,25) = "rescue" │ │ └── rescue_expression: │ │ @ LocalVariableWriteNode (location: (56,26)-(56,35)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ ├── depth: 0 │ │ ├── name_loc: (56,26)-(56,29) = "foo" @@ -354,105 +400,132 @@ │ │ └── operator_loc: (56,30)-(56,31) = "=" │ ├── rescue_clause: │ │ @ RescueNode (location: (57,0)-(57,16)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (57,0)-(57,6) = "rescue" │ │ ├── exceptions: (length: 1) │ │ │ └── @ ConstantReadNode (location: (57,7)-(57,16)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Exception │ │ ├── operator_loc: ∅ │ │ ├── reference: ∅ │ │ ├── statements: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (58,0)-(58,3) = "end" ├── @ BeginNode (location: (60,0)-(64,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (60,0)-(60,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (61,2)-(61,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (61,2)-(61,5)) + │ │ ├── flags: newline │ │ ├── name: :foo │ │ └── depth: 0 │ ├── rescue_clause: │ │ @ RescueNode (location: (62,0)-(63,5)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (62,0)-(62,6) = "rescue" │ │ ├── exceptions: (length: 0) │ │ ├── operator_loc: (62,7)-(62,9) = "=>" │ │ ├── reference: │ │ │ @ LocalVariableTargetNode (location: (62,10)-(62,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── statements: │ │ │ @ StatementsNode (location: (63,2)-(63,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ LocalVariableReadNode (location: (63,2)-(63,5)) + │ │ │ ├── flags: newline │ │ │ ├── name: :bar │ │ │ └── depth: 0 - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (64,0)-(64,3) = "end" ├── @ BeginNode (location: (66,0)-(70,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (66,0)-(66,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (67,2)-(67,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (67,2)-(67,5)) + │ │ ├── flags: newline │ │ ├── name: :foo │ │ └── depth: 0 │ ├── rescue_clause: │ │ @ RescueNode (location: (68,0)-(69,5)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (68,0)-(68,6) = "rescue" │ │ ├── exceptions: (length: 2) │ │ │ ├── @ ConstantReadNode (location: (68,7)-(68,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :Exception │ │ │ └── @ ConstantReadNode (location: (68,18)-(68,23)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :Other │ │ ├── operator_loc: (68,24)-(68,26) = "=>" │ │ ├── reference: │ │ │ @ LocalVariableTargetNode (location: (68,27)-(68,30)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── statements: │ │ │ @ StatementsNode (location: (69,2)-(69,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ LocalVariableReadNode (location: (69,2)-(69,5)) + │ │ │ ├── flags: newline │ │ │ ├── name: :bar │ │ │ └── depth: 0 - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (70,0)-(70,3) = "end" ├── @ BeginNode (location: (72,0)-(76,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (72,0)-(72,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (73,2)-(73,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (73,2)-(73,5)) + │ │ ├── flags: newline │ │ ├── name: :bar │ │ └── depth: 0 │ ├── rescue_clause: │ │ @ RescueNode (location: (74,0)-(75,5)) + │ │ ├── flags: ∅ │ │ ├── keyword_loc: (74,0)-(74,6) = "rescue" │ │ ├── exceptions: (length: 2) │ │ │ ├── @ ConstantReadNode (location: (74,7)-(74,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :SomeError │ │ │ └── @ SplatNode (location: (74,18)-(74,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (74,18)-(74,19) = "*" │ │ │ └── expression: │ │ │ @ LocalVariableReadNode (location: (74,19)-(74,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ └── depth: 0 │ │ ├── operator_loc: (74,23)-(74,25) = "=>" │ │ ├── reference: │ │ │ @ LocalVariableTargetNode (location: (74,26)-(74,35)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :exception │ │ │ └── depth: 0 │ │ ├── statements: │ │ │ @ StatementsNode (location: (75,2)-(75,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (75,2)-(75,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz @@ -461,25 +534,30 @@ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── consequent: ∅ + │ │ └── subsequent: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (76,0)-(76,3) = "end" └── @ SingletonClassNode (location: (78,0)-(80,3)) + ├── flags: newline ├── locals: [] ├── class_keyword_loc: (78,0)-(78,5) = "class" ├── operator_loc: (78,6)-(78,8) = "<<" ├── expression: │ @ SelfNode (location: (78,9)-(78,13)) + │ └── flags: ∅ ├── body: │ @ StatementsNode (location: (79,2)-(79,23)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ RescueModifierNode (location: (79,2)-(79,23)) + │ ├── flags: newline │ ├── expression: │ │ @ UndefNode (location: (79,2)-(79,12)) + │ │ ├── flags: ∅ │ │ ├── names: (length: 1) │ │ │ └── @ SymbolNode (location: (79,8)-(79,12)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (79,8)-(79,9) = ":" │ │ │ ├── value_loc: (79,9)-(79,12) = "bar" │ │ │ ├── closing_loc: ∅ @@ -488,4 +566,5 @@ │ ├── keyword_loc: (79,13)-(79,19) = "rescue" │ └── rescue_expression: │ @ NilNode (location: (79,20)-(79,23)) + │ └── flags: static_literal └── end_keyword_loc: (80,0)-(80,3) = "end" diff --git a/test/prism/snapshots/unparser/corpus/literal/lambda.txt b/test/prism/snapshots/unparser/corpus/literal/lambda.txt index 3594787bcab..863678f17b4 100644 --- a/test/prism/snapshots/unparser/corpus/literal/lambda.txt +++ b/test/prism/snapshots/unparser/corpus/literal/lambda.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(13,1)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(13,1)) + ├── flags: ∅ └── body: (length: 6) ├── @ CallNode (location: (1,0)-(2,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :lambda @@ -14,13 +16,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (1,7)-(2,1)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ │ ├── opening_loc: (1,7)-(1,8) = "{" │ └── closing_loc: (2,0)-(2,1) = "}" ├── @ CallNode (location: (3,0)-(5,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :lambda @@ -30,11 +33,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (3,7)-(5,1)) + │ ├── flags: ∅ │ ├── locals: [:a, :b] │ ├── parameters: │ │ @ BlockParametersNode (location: (3,9)-(3,15)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (3,10)-(3,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (3,10)-(3,11)) │ │ │ │ │ ├── flags: ∅ @@ -53,33 +59,40 @@ │ │ └── closing_loc: (3,14)-(3,15) = "|" │ ├── body: │ │ @ StatementsNode (location: (4,2)-(4,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (4,2)-(4,3)) + │ │ ├── flags: newline │ │ ├── name: :a │ │ └── depth: 0 │ ├── opening_loc: (3,7)-(3,8) = "{" │ └── closing_loc: (5,0)-(5,1) = "}" ├── @ LambdaNode (location: (6,0)-(7,1)) + │ ├── flags: newline │ ├── locals: [] │ ├── operator_loc: (6,0)-(6,2) = "->" │ ├── opening_loc: (6,5)-(6,6) = "{" │ ├── closing_loc: (7,0)-(7,1) = "}" │ ├── parameters: │ │ @ BlockParametersNode (location: (6,2)-(6,4)) + │ │ ├── flags: ∅ │ │ ├── parameters: ∅ │ │ ├── locals: (length: 0) │ │ ├── opening_loc: (6,2)-(6,3) = "(" │ │ └── closing_loc: (6,3)-(6,4) = ")" │ └── body: ∅ ├── @ LambdaNode (location: (8,0)-(9,1)) + │ ├── flags: newline │ ├── locals: [:a] │ ├── operator_loc: (8,0)-(8,2) = "->" │ ├── opening_loc: (8,6)-(8,7) = "{" │ ├── closing_loc: (9,0)-(9,1) = "}" │ ├── parameters: │ │ @ BlockParametersNode (location: (8,2)-(8,5)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (8,3)-(8,4)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (8,3)-(8,4)) │ │ │ │ ├── flags: ∅ @@ -95,14 +108,17 @@ │ │ └── closing_loc: (8,4)-(8,5) = ")" │ └── body: ∅ ├── @ LambdaNode (location: (10,0)-(11,1)) + │ ├── flags: newline │ ├── locals: [:a, :b] │ ├── operator_loc: (10,0)-(10,2) = "->" │ ├── opening_loc: (10,9)-(10,10) = "{" │ ├── closing_loc: (11,0)-(11,1) = "}" │ ├── parameters: │ │ @ BlockParametersNode (location: (10,2)-(10,8)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (10,3)-(10,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (10,3)-(10,4)) │ │ │ │ │ ├── flags: ∅ @@ -121,14 +137,17 @@ │ │ └── closing_loc: (10,7)-(10,8) = ")" │ └── body: ∅ └── @ LambdaNode (location: (12,0)-(13,1)) + ├── flags: newline ├── locals: [:a, :b, :c] ├── operator_loc: (12,0)-(12,2) = "->" ├── opening_loc: (12,12)-(12,13) = "{" ├── closing_loc: (13,0)-(13,1) = "}" ├── parameters: │ @ BlockParametersNode (location: (12,2)-(12,11)) + │ ├── flags: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (12,3)-(12,7)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (12,3)-(12,4)) │ │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/literal.txt b/test/prism/snapshots/unparser/corpus/literal/literal.txt index 98b88e11ceb..430a8a06793 100644 --- a/test/prism/snapshots/unparser/corpus/literal/literal.txt +++ b/test/prism/snapshots/unparser/corpus/literal/literal.txt @@ -1,15 +1,19 @@ @ ProgramNode (location: (1,0)-(91,2)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(91,2)) + ├── flags: ∅ └── body: (length: 78) ├── @ HashNode (location: (1,0)-(1,38)) + │ ├── flags: newline │ ├── opening_loc: (1,0)-(1,1) = "{" │ ├── elements: (length: 2) │ │ ├── @ AssocNode (location: (1,2)-(1,21)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ StringNode (location: (1,2)-(1,7)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: (1,2)-(1,3) = "\"" │ │ │ │ ├── content_loc: (1,3)-(1,6) = "foo" │ │ │ │ ├── closing_loc: (1,6)-(1,7) = "\"" @@ -20,17 +24,18 @@ │ │ │ │ ├── opening_loc: (1,11)-(1,21) = "<<-HEREDOC" │ │ │ │ ├── parts: (length: 3) │ │ │ │ │ ├── @ StringNode (location: (2,0)-(2,2)) - │ │ │ │ │ │ ├── flags: frozen + │ │ │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ │ ├── content_loc: (2,0)-(2,2) = " " │ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ │ └── unescaped: " " │ │ │ │ │ ├── @ EmbeddedStatementsNode (location: (2,2)-(2,5)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── opening_loc: (2,2)-(2,4) = "\#{" │ │ │ │ │ │ ├── statements: ∅ │ │ │ │ │ │ └── closing_loc: (2,4)-(2,5) = "}" │ │ │ │ │ └── @ StringNode (location: (2,5)-(3,0)) - │ │ │ │ │ ├── flags: frozen + │ │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── content_loc: (2,5)-(3,0) = "\n" │ │ │ │ │ ├── closing_loc: ∅ @@ -38,16 +43,17 @@ │ │ │ │ └── closing_loc: (3,0)-(4,0) = "HEREDOC\n" │ │ │ └── operator_loc: (1,8)-(1,10) = "=>" │ │ └── @ AssocNode (location: (1,23)-(1,36)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ StringNode (location: (1,23)-(1,28)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: (1,23)-(1,24) = "\"" │ │ │ ├── content_loc: (1,24)-(1,27) = "bar" │ │ │ ├── closing_loc: (1,27)-(1,28) = "\"" │ │ │ └── unescaped: "bar" │ │ ├── value: │ │ │ @ SymbolNode (location: (1,32)-(1,36)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,32)-(1,33) = ":" │ │ │ ├── value_loc: (1,33)-(1,36) = "baz" │ │ │ ├── closing_loc: ∅ @@ -55,12 +61,14 @@ │ │ └── operator_loc: (1,29)-(1,31) = "=>" │ └── closing_loc: (1,37)-(1,38) = "}" ├── @ HashNode (location: (4,0)-(4,31)) + │ ├── flags: newline │ ├── opening_loc: (4,0)-(4,1) = "{" │ ├── elements: (length: 2) │ │ ├── @ AssocNode (location: (4,2)-(4,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ StringNode (location: (4,2)-(4,7)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: (4,2)-(4,3) = "\"" │ │ │ │ ├── content_loc: (4,3)-(4,6) = "foo" │ │ │ │ ├── closing_loc: (4,6)-(4,7) = "\"" @@ -74,16 +82,17 @@ │ │ │ │ └── unescaped: "" │ │ │ └── operator_loc: (4,8)-(4,10) = "=>" │ │ └── @ AssocNode (location: (4,16)-(4,29)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ StringNode (location: (4,16)-(4,21)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: (4,16)-(4,17) = "\"" │ │ │ ├── content_loc: (4,17)-(4,20) = "bar" │ │ │ ├── closing_loc: (4,20)-(4,21) = "\"" │ │ │ └── unescaped: "bar" │ │ ├── value: │ │ │ @ SymbolNode (location: (4,25)-(4,29)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (4,25)-(4,26) = ":" │ │ │ ├── value_loc: (4,26)-(4,29) = "baz" │ │ │ ├── closing_loc: ∅ @@ -91,7 +100,7 @@ │ │ └── operator_loc: (4,22)-(4,24) = "=>" │ └── closing_loc: (4,30)-(4,31) = "}" ├── @ ArrayNode (location: (5,0)-(5,12)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 2) │ │ ├── @ StringNode (location: (5,1)-(5,6)) │ │ │ ├── flags: ∅ @@ -108,7 +117,7 @@ │ ├── opening_loc: (5,0)-(5,1) = "[" │ └── closing_loc: (5,11)-(5,12) = "]" ├── @ CallNode (location: (6,0)-(6,15)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (6,0)-(6,13)) │ │ ├── flags: ignore_visibility @@ -126,17 +135,18 @@ │ │ │ ├── opening_loc: (6,2)-(6,12) = "<<-HEREDOC" │ │ │ ├── parts: (length: 3) │ │ │ │ ├── @ StringNode (location: (7,0)-(7,2)) - │ │ │ │ │ ├── flags: frozen + │ │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── content_loc: (7,0)-(7,2) = " " │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: " " │ │ │ │ ├── @ EmbeddedStatementsNode (location: (7,2)-(7,5)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── opening_loc: (7,2)-(7,4) = "\#{" │ │ │ │ │ ├── statements: ∅ │ │ │ │ │ └── closing_loc: (7,4)-(7,5) = "}" │ │ │ │ └── @ StringNode (location: (7,5)-(8,0)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (7,5)-(8,0) = "\n" │ │ │ │ ├── closing_loc: ∅ @@ -152,7 +162,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (9,0)-(9,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (9,0)-(9,6)) │ │ ├── flags: ignore_visibility @@ -181,12 +191,14 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ HashNode (location: (10,0)-(10,30)) + │ ├── flags: newline │ ├── opening_loc: (10,0)-(10,1) = "{" │ ├── elements: (length: 2) │ │ ├── @ AssocNode (location: (10,2)-(10,21)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ StringNode (location: (10,2)-(10,7)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: (10,2)-(10,3) = "\"" │ │ │ │ ├── content_loc: (10,3)-(10,6) = "foo" │ │ │ │ ├── closing_loc: (10,6)-(10,7) = "\"" @@ -197,17 +209,18 @@ │ │ │ │ ├── opening_loc: (10,11)-(10,21) = "<<-HEREDOC" │ │ │ │ ├── parts: (length: 3) │ │ │ │ │ ├── @ StringNode (location: (11,0)-(11,2)) - │ │ │ │ │ │ ├── flags: frozen + │ │ │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ │ ├── content_loc: (11,0)-(11,2) = " " │ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ │ └── unescaped: " " │ │ │ │ │ ├── @ EmbeddedStatementsNode (location: (11,2)-(11,5)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── opening_loc: (11,2)-(11,4) = "\#{" │ │ │ │ │ │ ├── statements: ∅ │ │ │ │ │ │ └── closing_loc: (11,4)-(11,5) = "}" │ │ │ │ │ └── @ StringNode (location: (11,5)-(12,0)) - │ │ │ │ │ ├── flags: frozen + │ │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── content_loc: (11,5)-(12,0) = "\n" │ │ │ │ │ ├── closing_loc: ∅ @@ -215,6 +228,7 @@ │ │ │ │ └── closing_loc: (12,0)-(13,0) = "HEREDOC\n" │ │ │ └── operator_loc: (10,8)-(10,10) = "=>" │ │ └── @ AssocSplatNode (location: (10,23)-(10,28)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ CallNode (location: (10,25)-(10,28)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -229,12 +243,14 @@ │ │ └── operator_loc: (10,23)-(10,25) = "**" │ └── closing_loc: (10,29)-(10,30) = "}" ├── @ HashNode (location: (13,0)-(13,23)) + │ ├── flags: newline │ ├── opening_loc: (13,0)-(13,1) = "{" │ ├── elements: (length: 2) │ │ ├── @ AssocNode (location: (13,2)-(13,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ StringNode (location: (13,2)-(13,7)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: (13,2)-(13,3) = "\"" │ │ │ │ ├── content_loc: (13,3)-(13,6) = "foo" │ │ │ │ ├── closing_loc: (13,6)-(13,7) = "\"" @@ -248,6 +264,7 @@ │ │ │ │ └── unescaped: "" │ │ │ └── operator_loc: (13,8)-(13,10) = "=>" │ │ └── @ AssocSplatNode (location: (13,16)-(13,21)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ CallNode (location: (13,18)-(13,21)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -262,45 +279,51 @@ │ │ └── operator_loc: (13,16)-(13,18) = "**" │ └── closing_loc: (13,22)-(13,23) = "}" ├── @ InterpolatedStringNode (location: (14,0)-(14,14)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (14,0)-(14,1) = "\"" │ ├── parts: (length: 5) │ │ ├── @ EmbeddedVariableNode (location: (14,1)-(14,4)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (14,1)-(14,2) = "#" │ │ │ └── variable: │ │ │ @ InstanceVariableReadNode (location: (14,2)-(14,4)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :@a │ │ ├── @ StringNode (location: (14,4)-(14,5)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (14,4)-(14,5) = " " │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: " " │ │ ├── @ EmbeddedVariableNode (location: (14,5)-(14,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (14,5)-(14,6) = "#" │ │ │ └── variable: │ │ │ @ ClassVariableReadNode (location: (14,6)-(14,9)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :@@a │ │ ├── @ StringNode (location: (14,9)-(14,10)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (14,9)-(14,10) = " " │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: " " │ │ └── @ EmbeddedVariableNode (location: (14,10)-(14,13)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (14,10)-(14,11) = "#" │ │ └── variable: │ │ @ GlobalVariableReadNode (location: (14,11)-(14,13)) + │ │ ├── flags: ∅ │ │ └── name: :$a │ └── closing_loc: (14,13)-(14,14) = "\"" ├── @ IntegerNode (location: (15,0)-(15,1)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 0 ├── @ CallNode (location: (16,0)-(16,3)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ IntegerNode (location: (16,1)-(16,3)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :+@ @@ -310,85 +333,93 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ IntegerNode (location: (17,0)-(17,1)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 1 ├── @ IntegerNode (location: (18,0)-(18,1)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 1 ├── @ RationalNode (location: (19,0)-(19,2)) - │ └── numeric: - │ @ IntegerNode (location: (19,0)-(19,1)) - │ ├── flags: decimal - │ └── value: 1 + │ ├── flags: newline, static_literal, decimal + │ ├── numerator: 1 + │ └── denominator: 1 ├── @ RationalNode (location: (20,0)-(20,4)) - │ └── numeric: - │ @ FloatNode (location: (20,0)-(20,3)) - │ └── value: 1.5 + │ ├── flags: newline, static_literal, decimal + │ ├── numerator: 3 + │ └── denominator: 2 ├── @ RationalNode (location: (21,0)-(21,4)) - │ └── numeric: - │ @ FloatNode (location: (21,0)-(21,3)) - │ └── value: 1.3 + │ ├── flags: newline, static_literal, decimal + │ ├── numerator: 13 + │ └── denominator: 10 ├── @ ImaginaryNode (location: (22,0)-(22,2)) + │ ├── flags: newline, static_literal │ └── numeric: │ @ IntegerNode (location: (22,0)-(22,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 5 ├── @ ImaginaryNode (location: (23,0)-(23,3)) + │ ├── flags: newline, static_literal │ └── numeric: │ @ IntegerNode (location: (23,0)-(23,2)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: -5 ├── @ ImaginaryNode (location: (24,0)-(24,4)) + │ ├── flags: newline, static_literal │ └── numeric: │ @ FloatNode (location: (24,0)-(24,3)) + │ ├── flags: static_literal │ └── value: 0.6 ├── @ ImaginaryNode (location: (25,0)-(25,5)) + │ ├── flags: newline, static_literal │ └── numeric: │ @ FloatNode (location: (25,0)-(25,4)) + │ ├── flags: static_literal │ └── value: -0.6 ├── @ ImaginaryNode (location: (26,0)-(26,32)) + │ ├── flags: newline, static_literal │ └── numeric: │ @ IntegerNode (location: (26,0)-(26,31)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1000000000000000000000000000000 ├── @ ImaginaryNode (location: (27,0)-(27,3)) + │ ├── flags: newline, static_literal │ └── numeric: │ @ RationalNode (location: (27,0)-(27,2)) - │ └── numeric: - │ @ IntegerNode (location: (27,0)-(27,1)) - │ ├── flags: decimal - │ └── value: 1 + │ ├── flags: static_literal, decimal + │ ├── numerator: 1 + │ └── denominator: 1 ├── @ InterpolatedStringNode (location: (28,0)-(28,11)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── opening_loc: ∅ │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (28,0)-(28,5)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: (28,0)-(28,1) = "\"" │ │ │ ├── content_loc: (28,1)-(28,4) = "foo" │ │ │ ├── closing_loc: (28,4)-(28,5) = "\"" │ │ │ └── unescaped: "foo" │ │ └── @ StringNode (location: (28,6)-(28,11)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: (28,6)-(28,7) = "\"" │ │ ├── content_loc: (28,7)-(28,10) = "bar" │ │ ├── closing_loc: (28,10)-(28,11) = "\"" │ │ └── unescaped: "bar" │ └── closing_loc: ∅ ├── @ InterpolatedStringNode (location: (29,0)-(29,15)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (29,0)-(29,1) = "\"" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (29,1)-(29,8)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (29,1)-(29,8) = "foobar " │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "foobar " │ │ └── @ EmbeddedStatementsNode (location: (29,8)-(29,14)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (29,8)-(29,10) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (29,10)-(29,13)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (29,10)-(29,13)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -403,239 +434,256 @@ │ │ └── closing_loc: (29,13)-(29,14) = "}" │ └── closing_loc: (29,14)-(29,15) = "\"" ├── @ InterpolatedStringNode (location: (30,0)-(30,12)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (30,0)-(30,1) = "\"" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (30,1)-(30,4)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (30,1)-(30,4) = "foo" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "foo" │ │ ├── @ EmbeddedStatementsNode (location: (30,4)-(30,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (30,4)-(30,6) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (30,6)-(30,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (30,6)-(30,7)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (30,7)-(30,8) = "}" │ │ └── @ StringNode (location: (30,8)-(30,11)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (30,8)-(30,11) = "bar" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "bar" │ └── closing_loc: (30,11)-(30,12) = "\"" ├── @ InterpolatedStringNode (location: (31,0)-(31,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (31,0)-(31,1) = "\"" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (31,1)-(31,5)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (31,1)-(31,5) = "\\\\\\\\" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\\\\" │ │ └── @ EmbeddedStatementsNode (location: (31,5)-(31,8)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (31,5)-(31,7) = "\#{" │ │ ├── statements: ∅ │ │ └── closing_loc: (31,7)-(31,8) = "}" │ └── closing_loc: (31,8)-(31,9) = "\"" ├── @ InterpolatedStringNode (location: (32,0)-(32,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (32,0)-(32,1) = "\"" │ ├── parts: (length: 2) │ │ ├── @ EmbeddedStatementsNode (location: (32,1)-(32,4)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (32,1)-(32,3) = "\#{" │ │ │ ├── statements: ∅ │ │ │ └── closing_loc: (32,3)-(32,4) = "}" │ │ └── @ StringNode (location: (32,4)-(32,8)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (32,4)-(32,8) = "\\\#{}" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\#{}" │ └── closing_loc: (32,8)-(32,9) = "\"" ├── @ InterpolatedStringNode (location: (33,0)-(33,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (33,0)-(33,1) = "\"" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (33,1)-(33,5)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (33,1)-(33,5) = "\\\#{}" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\#{}" │ │ └── @ EmbeddedStatementsNode (location: (33,5)-(33,8)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (33,5)-(33,7) = "\#{" │ │ ├── statements: ∅ │ │ └── closing_loc: (33,7)-(33,8) = "}" │ └── closing_loc: (33,8)-(33,9) = "\"" ├── @ StringNode (location: (34,0)-(34,15)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (34,0)-(34,1) = "\"" │ ├── content_loc: (34,1)-(34,14) = "foo\\\\\\\#{@bar}" │ ├── closing_loc: (34,14)-(34,15) = "\"" │ └── unescaped: "foo\\\#{@bar}" ├── @ StringNode (location: (35,0)-(35,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (35,0)-(35,1) = "\"" │ ├── content_loc: (35,1)-(35,3) = "\\\"" │ ├── closing_loc: (35,3)-(35,4) = "\"" │ └── unescaped: "\"" ├── @ StringNode (location: (36,0)-(36,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (36,0)-(36,1) = "\"" │ ├── content_loc: (36,1)-(36,8) = "foo bar" │ ├── closing_loc: (36,8)-(36,9) = "\"" │ └── unescaped: "foo bar" ├── @ StringNode (location: (37,0)-(37,10)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (37,0)-(37,1) = "\"" │ ├── content_loc: (37,1)-(37,9) = "foo\\nbar" │ ├── closing_loc: (37,9)-(37,10) = "\"" │ └── unescaped: "foo\nbar" ├── @ XStringNode (location: (38,0)-(38,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (38,0)-(38,1) = "`" │ ├── content_loc: (38,1)-(38,4) = "foo" │ ├── closing_loc: (38,4)-(38,5) = "`" │ └── unescaped: "foo" ├── @ InterpolatedXStringNode (location: (39,0)-(39,12)) + │ ├── flags: newline │ ├── opening_loc: (39,0)-(39,1) = "`" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (39,1)-(39,4)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (39,1)-(39,4) = "foo" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "foo" │ │ └── @ EmbeddedStatementsNode (location: (39,4)-(39,11)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (39,4)-(39,6) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (39,6)-(39,10)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ InstanceVariableReadNode (location: (39,6)-(39,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :@bar │ │ └── closing_loc: (39,10)-(39,11) = "}" │ └── closing_loc: (39,11)-(39,12) = "`" ├── @ XStringNode (location: (40,0)-(40,3)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (40,0)-(40,1) = "`" │ ├── content_loc: (40,1)-(40,2) = ")" │ ├── closing_loc: (40,2)-(40,3) = "`" │ └── unescaped: ")" ├── @ XStringNode (location: (41,0)-(41,4)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (41,0)-(41,1) = "`" │ ├── content_loc: (41,1)-(41,3) = "\\`" │ ├── closing_loc: (41,3)-(41,4) = "`" │ └── unescaped: "`" ├── @ XStringNode (location: (42,0)-(42,3)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (42,0)-(42,1) = "`" │ ├── content_loc: (42,1)-(42,2) = "\"" │ ├── closing_loc: (42,2)-(42,3) = "`" │ └── unescaped: "\"" ├── @ SymbolNode (location: (43,0)-(43,4)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (43,0)-(43,1) = ":" │ ├── value_loc: (43,1)-(43,4) = "foo" │ ├── closing_loc: ∅ │ └── unescaped: "foo" ├── @ SymbolNode (location: (44,0)-(44,6)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (44,0)-(44,2) = ":\"" │ ├── value_loc: (44,2)-(44,5) = "A B" │ ├── closing_loc: (44,5)-(44,6) = "\"" │ └── unescaped: "A B" ├── @ SymbolNode (location: (45,0)-(45,4)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (45,0)-(45,1) = ":" │ ├── value_loc: (45,1)-(45,4) = "foo" │ ├── closing_loc: ∅ │ └── unescaped: "foo" ├── @ SymbolNode (location: (46,0)-(46,6)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (46,0)-(46,2) = ":\"" │ ├── value_loc: (46,2)-(46,5) = "A B" │ ├── closing_loc: (46,5)-(46,6) = "\"" │ └── unescaped: "A B" ├── @ SymbolNode (location: (47,0)-(47,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (47,0)-(47,2) = ":\"" │ ├── value_loc: (47,2)-(47,6) = "A\\\"B" │ ├── closing_loc: (47,6)-(47,7) = "\"" │ └── unescaped: "A\"B" ├── @ SymbolNode (location: (48,0)-(48,3)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── opening_loc: (48,0)-(48,2) = ":\"" │ ├── value_loc: (1,0)-(1,0) = "" │ ├── closing_loc: (48,2)-(48,3) = "\"" │ └── unescaped: "" ├── @ RegularExpressionNode (location: (49,0)-(49,5)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (49,0)-(49,1) = "/" │ ├── content_loc: (49,1)-(49,4) = "foo" │ ├── closing_loc: (49,4)-(49,5) = "/" │ └── unescaped: "foo" ├── @ RegularExpressionNode (location: (50,0)-(50,28)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (50,0)-(50,1) = "/" │ ├── content_loc: (50,1)-(50,27) = "[^-+',.\\/:@[:alnum:]\\[\\]]+" │ ├── closing_loc: (50,27)-(50,28) = "/" │ └── unescaped: "[^-+',./:@[:alnum:]\\[\\]]+" ├── @ InterpolatedRegularExpressionNode (location: (51,0)-(51,12)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (51,0)-(51,1) = "/" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (51,1)-(51,4)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (51,1)-(51,4) = "foo" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "foo" │ │ └── @ EmbeddedStatementsNode (location: (51,4)-(51,11)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (51,4)-(51,6) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (51,6)-(51,10)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ InstanceVariableReadNode (location: (51,6)-(51,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :@bar │ │ └── closing_loc: (51,10)-(51,11) = "}" │ └── closing_loc: (51,11)-(51,12) = "/" ├── @ InterpolatedRegularExpressionNode (location: (52,0)-(52,15)) - │ ├── flags: ignore_case, extended, multi_line + │ ├── flags: newline, ignore_case, extended, multi_line │ ├── opening_loc: (52,0)-(52,1) = "/" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (52,1)-(52,4)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (52,1)-(52,4) = "foo" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "foo" │ │ └── @ EmbeddedStatementsNode (location: (52,4)-(52,11)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (52,4)-(52,6) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (52,6)-(52,10)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ InstanceVariableReadNode (location: (52,6)-(52,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :@bar │ │ └── closing_loc: (52,10)-(52,11) = "}" │ └── closing_loc: (52,11)-(52,15) = "/imx" ├── @ InterpolatedRegularExpressionNode (location: (53,0)-(53,13)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── opening_loc: (53,0)-(53,1) = "/" │ ├── parts: (length: 1) │ │ └── @ EmbeddedStatementsNode (location: (53,1)-(53,12)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (53,1)-(53,3) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (53,3)-(53,11)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ StringNode (location: (53,3)-(53,11)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: (53,3)-(53,4) = "\"" │ │ │ ├── content_loc: (53,4)-(53,10) = "\\u0000" │ │ │ ├── closing_loc: (53,10)-(53,11) = "\"" @@ -643,42 +691,45 @@ │ │ └── closing_loc: (53,11)-(53,12) = "}" │ └── closing_loc: (53,12)-(53,13) = "/" ├── @ RegularExpressionNode (location: (54,0)-(54,4)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (54,0)-(54,1) = "/" │ ├── content_loc: (54,1)-(54,3) = "\\n" │ ├── closing_loc: (54,3)-(54,4) = "/" │ └── unescaped: "\\n" ├── @ RegularExpressionNode (location: (55,0)-(55,4)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (55,0)-(55,1) = "/" │ ├── content_loc: (55,1)-(55,3) = "\\n" │ ├── closing_loc: (55,3)-(55,4) = "/" │ └── unescaped: "\\n" ├── @ RegularExpressionNode (location: (56,0)-(56,5)) - │ ├── flags: extended, forced_us_ascii_encoding + │ ├── flags: newline, static_literal, extended, forced_us_ascii_encoding │ ├── opening_loc: (56,0)-(56,1) = "/" │ ├── content_loc: (56,1)-(56,3) = "\\n" │ ├── closing_loc: (56,3)-(56,5) = "/x" │ └── unescaped: "\\n" ├── @ RegularExpressionNode (location: (57,0)-(57,7)) - │ ├── flags: extended, forced_us_ascii_encoding + │ ├── flags: newline, static_literal, extended, forced_us_ascii_encoding │ ├── opening_loc: (57,0)-(57,1) = "/" │ ├── content_loc: (57,1)-(57,5) = "\\/\\/" │ ├── closing_loc: (57,5)-(57,7) = "/x" │ └── unescaped: "//" ├── @ InterpolatedSymbolNode (location: (58,0)-(58,15)) + │ ├── flags: newline │ ├── opening_loc: (58,0)-(58,2) = ":\"" │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (58,2)-(58,5)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (58,2)-(58,5) = "foo" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "foo" │ │ ├── @ EmbeddedStatementsNode (location: (58,5)-(58,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (58,5)-(58,7) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (58,7)-(58,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (58,7)-(58,10)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -692,22 +743,25 @@ │ │ │ │ └── block: ∅ │ │ │ └── closing_loc: (58,10)-(58,11) = "}" │ │ └── @ StringNode (location: (58,11)-(58,14)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (58,11)-(58,14) = "baz" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "baz" │ └── closing_loc: (58,14)-(58,15) = "\"" ├── @ InterpolatedSymbolNode (location: (59,0)-(59,11)) + │ ├── flags: newline, static_literal │ ├── opening_loc: (59,0)-(59,2) = ":\"" │ ├── parts: (length: 1) │ │ └── @ EmbeddedStatementsNode (location: (59,2)-(59,10)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (59,2)-(59,4) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (59,4)-(59,9)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ StringNode (location: (59,4)-(59,9)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: (59,4)-(59,5) = "\"" │ │ │ ├── content_loc: (59,5)-(59,8) = "foo" │ │ │ ├── closing_loc: (59,8)-(59,9) = "\"" @@ -715,16 +769,19 @@ │ │ └── closing_loc: (59,9)-(59,10) = "}" │ └── closing_loc: (59,10)-(59,11) = "\"" ├── @ RangeNode (location: (60,0)-(60,14)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── left: │ │ @ ParenthesesNode (location: (60,0)-(60,11)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (60,1)-(60,10)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (60,1)-(60,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ FloatNode (location: (60,1)-(60,4)) + │ │ │ │ ├── flags: static_literal │ │ │ │ └── value: 0.0 │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :/ @@ -735,6 +792,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ FloatNode (location: (60,7)-(60,10)) + │ │ │ │ ├── flags: static_literal │ │ │ │ └── value: 0.0 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ @@ -742,24 +800,27 @@ │ │ └── closing_loc: (60,10)-(60,11) = ")" │ ├── right: │ │ @ IntegerNode (location: (60,13)-(60,14)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (60,11)-(60,13) = ".." ├── @ RangeNode (location: (61,0)-(61,14)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── left: │ │ @ IntegerNode (location: (61,0)-(61,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── right: │ │ @ ParenthesesNode (location: (61,3)-(61,14)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (61,4)-(61,13)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (61,4)-(61,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ FloatNode (location: (61,4)-(61,7)) + │ │ │ │ ├── flags: static_literal │ │ │ │ └── value: 0.0 │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :/ @@ -770,6 +831,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ FloatNode (location: (61,10)-(61,13)) + │ │ │ │ ├── flags: static_literal │ │ │ │ └── value: 0.0 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ @@ -777,16 +839,19 @@ │ │ └── closing_loc: (61,13)-(61,14) = ")" │ └── operator_loc: (61,1)-(61,3) = ".." ├── @ RangeNode (location: (62,0)-(62,16)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── left: │ │ @ ParenthesesNode (location: (62,0)-(62,11)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (62,1)-(62,10)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (62,1)-(62,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ FloatNode (location: (62,1)-(62,4)) + │ │ │ │ ├── flags: static_literal │ │ │ │ └── value: 0.0 │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :/ @@ -797,6 +862,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ FloatNode (location: (62,7)-(62,10)) + │ │ │ │ ├── flags: static_literal │ │ │ │ └── value: 0.0 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ @@ -804,31 +870,34 @@ │ │ └── closing_loc: (62,10)-(62,11) = ")" │ ├── right: │ │ @ IntegerNode (location: (62,13)-(62,16)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 100 │ └── operator_loc: (62,11)-(62,13) = ".." ├── @ FloatNode (location: (63,0)-(63,4)) + │ ├── flags: newline, static_literal │ └── value: -0.1 ├── @ FloatNode (location: (64,0)-(64,3)) + │ ├── flags: newline, static_literal │ └── value: 0.1 ├── @ ArrayNode (location: (65,0)-(65,6)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (65,1)-(65,2)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (65,4)-(65,5)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── opening_loc: (65,0)-(65,1) = "[" │ └── closing_loc: (65,5)-(65,6) = "]" ├── @ ArrayNode (location: (66,0)-(66,11)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── elements: (length: 3) │ │ ├── @ IntegerNode (location: (66,1)-(66,2)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── @ ParenthesesNode (location: (66,4)-(66,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: ∅ │ │ │ ├── opening_loc: (66,4)-(66,5) = "(" │ │ │ └── closing_loc: (66,5)-(66,6) = ")" @@ -845,137 +914,160 @@ │ ├── opening_loc: (66,0)-(66,1) = "[" │ └── closing_loc: (66,10)-(66,11) = "]" ├── @ ArrayNode (location: (67,0)-(67,3)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 1) │ │ └── @ IntegerNode (location: (67,1)-(67,2)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── opening_loc: (67,0)-(67,1) = "[" │ └── closing_loc: (67,2)-(67,3) = "]" ├── @ ArrayNode (location: (68,0)-(68,2)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── elements: (length: 0) │ ├── opening_loc: (68,0)-(68,1) = "[" │ └── closing_loc: (68,1)-(68,2) = "]" ├── @ ArrayNode (location: (69,0)-(69,10)) - │ ├── flags: contains_splat + │ ├── flags: newline, contains_splat │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (69,1)-(69,2)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ SplatNode (location: (69,4)-(69,9)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (69,4)-(69,5) = "*" │ │ └── expression: │ │ @ InstanceVariableReadNode (location: (69,5)-(69,9)) + │ │ ├── flags: ∅ │ │ └── name: :@foo │ ├── opening_loc: (69,0)-(69,1) = "[" │ └── closing_loc: (69,9)-(69,10) = "]" ├── @ ArrayNode (location: (70,0)-(70,10)) - │ ├── flags: contains_splat + │ ├── flags: newline, contains_splat │ ├── elements: (length: 2) │ │ ├── @ SplatNode (location: (70,1)-(70,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (70,1)-(70,2) = "*" │ │ │ └── expression: │ │ │ @ InstanceVariableReadNode (location: (70,2)-(70,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :@foo │ │ └── @ IntegerNode (location: (70,8)-(70,9)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── opening_loc: (70,0)-(70,1) = "[" │ └── closing_loc: (70,9)-(70,10) = "]" ├── @ ArrayNode (location: (71,0)-(71,14)) - │ ├── flags: contains_splat + │ ├── flags: newline, contains_splat │ ├── elements: (length: 2) │ │ ├── @ SplatNode (location: (71,1)-(71,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (71,1)-(71,2) = "*" │ │ │ └── expression: │ │ │ @ InstanceVariableReadNode (location: (71,2)-(71,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :@foo │ │ └── @ SplatNode (location: (71,8)-(71,13)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (71,8)-(71,9) = "*" │ │ └── expression: │ │ @ InstanceVariableReadNode (location: (71,9)-(71,13)) + │ │ ├── flags: ∅ │ │ └── name: :@baz │ ├── opening_loc: (71,0)-(71,1) = "[" │ └── closing_loc: (71,13)-(71,14) = "]" ├── @ HashNode (location: (72,0)-(72,2)) + │ ├── flags: newline, static_literal │ ├── opening_loc: (72,0)-(72,1) = "{" │ ├── elements: (length: 0) │ └── closing_loc: (72,1)-(72,2) = "}" ├── @ HashNode (location: (73,0)-(73,12)) + │ ├── flags: newline │ ├── opening_loc: (73,0)-(73,1) = "{" │ ├── elements: (length: 1) │ │ └── @ AssocNode (location: (73,2)-(73,10)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ ParenthesesNode (location: (73,2)-(73,4)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: ∅ │ │ │ ├── opening_loc: (73,2)-(73,3) = "(" │ │ │ └── closing_loc: (73,3)-(73,4) = ")" │ │ ├── value: │ │ │ @ ParenthesesNode (location: (73,8)-(73,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: ∅ │ │ │ ├── opening_loc: (73,8)-(73,9) = "(" │ │ │ └── closing_loc: (73,9)-(73,10) = ")" │ │ └── operator_loc: (73,5)-(73,7) = "=>" │ └── closing_loc: (73,11)-(73,12) = "}" ├── @ HashNode (location: (74,0)-(74,10)) + │ ├── flags: newline, static_literal │ ├── opening_loc: (74,0)-(74,1) = "{" │ ├── elements: (length: 1) │ │ └── @ AssocNode (location: (74,2)-(74,8)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ IntegerNode (location: (74,2)-(74,3)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── value: │ │ │ @ IntegerNode (location: (74,7)-(74,8)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: (74,4)-(74,6) = "=>" │ └── closing_loc: (74,9)-(74,10) = "}" ├── @ HashNode (location: (75,0)-(75,18)) + │ ├── flags: newline, static_literal │ ├── opening_loc: (75,0)-(75,1) = "{" │ ├── elements: (length: 2) │ │ ├── @ AssocNode (location: (75,2)-(75,8)) + │ │ │ ├── flags: static_literal │ │ │ ├── key: │ │ │ │ @ IntegerNode (location: (75,2)-(75,3)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (75,7)-(75,8)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ └── operator_loc: (75,4)-(75,6) = "=>" │ │ └── @ AssocNode (location: (75,10)-(75,16)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ IntegerNode (location: (75,10)-(75,11)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 3 │ │ ├── value: │ │ │ @ IntegerNode (location: (75,15)-(75,16)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 4 │ │ └── operator_loc: (75,12)-(75,14) = "=>" │ └── closing_loc: (75,17)-(75,18) = "}" ├── @ HashNode (location: (76,0)-(76,27)) + │ ├── flags: newline │ ├── opening_loc: (76,0)-(76,1) = "{" │ ├── elements: (length: 2) │ │ ├── @ AssocNode (location: (76,2)-(76,19)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (76,2)-(76,4)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (76,2)-(76,3) = "a" │ │ │ │ ├── closing_loc: (76,3)-(76,4) = ":" │ │ │ │ └── unescaped: "a" │ │ │ ├── value: │ │ │ │ @ ParenthesesNode (location: (76,5)-(76,19)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── body: │ │ │ │ │ @ StatementsNode (location: (76,6)-(76,18)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ RescueModifierNode (location: (76,6)-(76,18)) + │ │ │ │ │ ├── flags: newline │ │ │ │ │ ├── expression: │ │ │ │ │ │ @ IntegerNode (location: (76,6)-(76,7)) - │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ │ └── value: 1 │ │ │ │ │ ├── keyword_loc: (76,8)-(76,14) = "rescue" │ │ │ │ │ └── rescue_expression: @@ -993,63 +1085,69 @@ │ │ │ │ └── closing_loc: (76,18)-(76,19) = ")" │ │ │ └── operator_loc: ∅ │ │ └── @ AssocNode (location: (76,21)-(76,25)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (76,21)-(76,23)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (76,21)-(76,22) = "b" │ │ │ ├── closing_loc: (76,22)-(76,23) = ":" │ │ │ └── unescaped: "b" │ │ ├── value: │ │ │ @ IntegerNode (location: (76,24)-(76,25)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: ∅ │ └── closing_loc: (76,26)-(76,27) = "}" ├── @ HashNode (location: (77,0)-(77,14)) + │ ├── flags: newline, static_literal │ ├── opening_loc: (77,0)-(77,1) = "{" │ ├── elements: (length: 2) │ │ ├── @ AssocNode (location: (77,2)-(77,6)) + │ │ │ ├── flags: static_literal │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (77,2)-(77,4)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (77,2)-(77,3) = "a" │ │ │ │ ├── closing_loc: (77,3)-(77,4) = ":" │ │ │ │ └── unescaped: "a" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (77,5)-(77,6)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── operator_loc: ∅ │ │ └── @ AssocNode (location: (77,8)-(77,12)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (77,8)-(77,10)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (77,8)-(77,9) = "b" │ │ │ ├── closing_loc: (77,9)-(77,10) = ":" │ │ │ └── unescaped: "b" │ │ ├── value: │ │ │ @ IntegerNode (location: (77,11)-(77,12)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: ∅ │ └── closing_loc: (77,13)-(77,14) = "}" ├── @ HashNode (location: (78,0)-(78,9)) + │ ├── flags: newline, static_literal │ ├── opening_loc: (78,0)-(78,1) = "{" │ ├── elements: (length: 1) │ │ └── @ AssocNode (location: (78,2)-(78,7)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (78,2)-(78,4)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (78,2)-(78,3) = "a" │ │ │ ├── closing_loc: (78,3)-(78,4) = ":" │ │ │ └── unescaped: "a" │ │ ├── value: │ │ │ @ SymbolNode (location: (78,5)-(78,7)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (78,5)-(78,6) = ":" │ │ │ ├── value_loc: (78,6)-(78,7) = "a" │ │ │ ├── closing_loc: ∅ @@ -1057,66 +1155,72 @@ │ │ └── operator_loc: ∅ │ └── closing_loc: (78,8)-(78,9) = "}" ├── @ HashNode (location: (79,0)-(79,15)) + │ ├── flags: newline, static_literal │ ├── opening_loc: (79,0)-(79,1) = "{" │ ├── elements: (length: 1) │ │ └── @ AssocNode (location: (79,2)-(79,13)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (79,2)-(79,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (79,2)-(79,4) = ":\"" │ │ │ ├── value_loc: (79,4)-(79,7) = "a b" │ │ │ ├── closing_loc: (79,7)-(79,8) = "\"" │ │ │ └── unescaped: "a b" │ │ ├── value: │ │ │ @ IntegerNode (location: (79,12)-(79,13)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── operator_loc: (79,9)-(79,11) = "=>" │ └── closing_loc: (79,14)-(79,15) = "}" ├── @ HashNode (location: (80,0)-(80,12)) + │ ├── flags: newline, static_literal │ ├── opening_loc: (80,0)-(80,1) = "{" │ ├── elements: (length: 1) │ │ └── @ AssocNode (location: (80,2)-(80,10)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (80,2)-(80,5)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (80,2)-(80,3) = ":" │ │ │ ├── value_loc: (80,3)-(80,5) = "-@" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "-@" │ │ ├── value: │ │ │ @ IntegerNode (location: (80,9)-(80,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── operator_loc: (80,6)-(80,8) = "=>" │ └── closing_loc: (80,11)-(80,12) = "}" ├── @ InterpolatedStringNode (location: (81,0)-(82,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (81,0)-(81,1) = "\"" │ ├── parts: (length: 4) │ │ ├── @ EmbeddedStatementsNode (location: (81,1)-(81,4)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (81,1)-(81,3) = "\#{" │ │ │ ├── statements: ∅ │ │ │ └── closing_loc: (81,3)-(81,4) = "}" │ │ ├── @ StringNode (location: (81,4)-(82,0)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (81,4)-(82,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" │ │ ├── @ EmbeddedStatementsNode (location: (82,0)-(82,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (82,0)-(82,2) = "\#{" │ │ │ ├── statements: ∅ │ │ │ └── closing_loc: (82,2)-(82,3) = "}" │ │ └── @ StringNode (location: (82,3)-(82,6)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (82,3)-(82,6) = "\\na" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\na" │ └── closing_loc: (82,6)-(82,7) = "\"" ├── @ CallNode (location: (83,0)-(86,1)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1126,31 +1230,35 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (83,4)-(86,1)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (84,2)-(85,7)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ InterpolatedStringNode (location: (84,2)-(85,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── opening_loc: (84,2)-(84,3) = "\"" │ │ ├── parts: (length: 4) │ │ │ ├── @ EmbeddedStatementsNode (location: (84,3)-(84,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: (84,3)-(84,5) = "\#{" │ │ │ │ ├── statements: ∅ │ │ │ │ └── closing_loc: (84,5)-(84,6) = "}" │ │ │ ├── @ StringNode (location: (84,6)-(85,0)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (84,6)-(85,0) = "\n" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "\n" │ │ │ ├── @ EmbeddedStatementsNode (location: (85,0)-(85,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: (85,0)-(85,2) = "\#{" │ │ │ │ ├── statements: ∅ │ │ │ │ └── closing_loc: (85,2)-(85,3) = "}" │ │ │ └── @ StringNode (location: (85,3)-(85,6)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (85,3)-(85,6) = "\\na" │ │ │ ├── closing_loc: ∅ @@ -1159,24 +1267,27 @@ │ ├── opening_loc: (83,4)-(83,5) = "{" │ └── closing_loc: (86,0)-(86,1) = "}" ├── @ SymbolNode (location: (87,0)-(88,2)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (87,0)-(87,2) = ":\"" │ ├── value_loc: (87,2)-(88,1) = "a\\\\\nb" │ ├── closing_loc: (88,1)-(88,2) = "\"" │ └── unescaped: "a\\\nb" └── @ InterpolatedXStringNode (location: (89,0)-(91,2)) + ├── flags: newline ├── opening_loc: (89,0)-(89,1) = "`" ├── parts: (length: 3) │ ├── @ StringNode (location: (89,1)-(90,0)) - │ │ ├── flags: frozen + │ │ ├── flags: static_literal, frozen │ │ ├── opening_loc: ∅ │ │ ├── content_loc: (89,1)-(90,0) = " x\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: " x\n" │ ├── @ EmbeddedStatementsNode (location: (90,0)-(90,6)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (90,0)-(90,2) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (90,2)-(90,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (90,2)-(90,5)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -1190,7 +1301,7 @@ │ │ │ └── block: ∅ │ │ └── closing_loc: (90,5)-(90,6) = "}" │ └── @ StringNode (location: (90,6)-(91,1)) - │ ├── flags: frozen + │ ├── flags: static_literal, frozen │ ├── opening_loc: ∅ │ ├── content_loc: (90,6)-(91,1) = "\n#" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/module.txt b/test/prism/snapshots/unparser/corpus/literal/module.txt index 6428aeea82e..9ad15d2dcd1 100644 --- a/test/prism/snapshots/unparser/corpus/literal/module.txt +++ b/test/prism/snapshots/unparser/corpus/literal/module.txt @@ -1,24 +1,31 @@ @ ProgramNode (location: (1,0)-(16,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(16,3)) + ├── flags: ∅ └── body: (length: 4) ├── @ ModuleNode (location: (1,0)-(2,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── module_keyword_loc: (1,0)-(1,6) = "module" │ ├── constant_path: │ │ @ ConstantReadNode (location: (1,7)-(1,8)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── body: ∅ │ ├── end_keyword_loc: (2,0)-(2,3) = "end" │ └── name: :A ├── @ ModuleNode (location: (4,0)-(5,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── module_keyword_loc: (4,0)-(4,6) = "module" │ ├── constant_path: │ │ @ ConstantPathNode (location: (4,7)-(4,11)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantReadNode (location: (4,7)-(4,8)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── name: :B │ │ ├── delimiter_loc: (4,8)-(4,10) = "::" @@ -27,14 +34,18 @@ │ ├── end_keyword_loc: (5,0)-(5,3) = "end" │ └── name: :B ├── @ ModuleNode (location: (7,0)-(8,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── module_keyword_loc: (7,0)-(7,6) = "module" │ ├── constant_path: │ │ @ ConstantPathNode (location: (7,7)-(7,14)) + │ │ ├── flags: ∅ │ │ ├── parent: │ │ │ @ ConstantPathNode (location: (7,7)-(7,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── parent: │ │ │ │ @ ConstantReadNode (location: (7,7)-(7,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :A │ │ │ ├── name: :B │ │ │ ├── delimiter_loc: (7,8)-(7,10) = "::" @@ -46,16 +57,19 @@ │ ├── end_keyword_loc: (8,0)-(8,3) = "end" │ └── name: :C └── @ ModuleNode (location: (10,0)-(16,3)) + ├── flags: newline ├── locals: [] ├── module_keyword_loc: (10,0)-(10,6) = "module" ├── constant_path: │ @ ConstantReadNode (location: (10,7)-(10,8)) + │ ├── flags: ∅ │ └── name: :A ├── body: │ @ StatementsNode (location: (11,2)-(15,5)) + │ ├── flags: ∅ │ └── body: (length: 2) │ ├── @ CallNode (location: (11,2)-(11,16)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :include @@ -69,6 +83,7 @@ │ │ │ ├── flags: ∅ │ │ │ ├── receiver: │ │ │ │ @ ConstantReadNode (location: (11,10)-(11,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :B │ │ │ ├── call_operator_loc: (11,11)-(11,12) = "." │ │ │ ├── name: :new @@ -80,15 +95,17 @@ │ │ ├── closing_loc: (11,15)-(11,16) = ")" │ │ └── block: ∅ │ └── @ DefNode (location: (13,2)-(15,5)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (13,6)-(13,9) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (14,4)-(14,8)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (14,4)-(14,8)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (14,4)-(14,5) = ":" │ │ ├── value_loc: (14,5)-(14,8) = "bar" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/opasgn.txt b/test/prism/snapshots/unparser/corpus/literal/opasgn.txt index 8dc08496381..3df6248d4ba 100644 --- a/test/prism/snapshots/unparser/corpus/literal/opasgn.txt +++ b/test/prism/snapshots/unparser/corpus/literal/opasgn.txt @@ -1,59 +1,67 @@ @ ProgramNode (location: (1,0)-(24,10)) +├── flags: ∅ ├── locals: [:a, :h] └── statements: @ StatementsNode (location: (1,0)-(24,10)) + ├── flags: ∅ └── body: (length: 24) ├── @ LocalVariableOperatorWriteNode (location: (1,0)-(1,6)) + │ ├── flags: newline │ ├── name_loc: (1,0)-(1,1) = "a" - │ ├── operator_loc: (1,2)-(1,4) = "+=" + │ ├── binary_operator_loc: (1,2)-(1,4) = "+=" │ ├── value: │ │ @ IntegerNode (location: (1,5)-(1,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── name: :a - │ ├── operator: :+ + │ ├── binary_operator: :+ │ └── depth: 0 ├── @ LocalVariableOperatorWriteNode (location: (2,0)-(2,6)) + │ ├── flags: newline │ ├── name_loc: (2,0)-(2,1) = "a" - │ ├── operator_loc: (2,2)-(2,4) = "-=" + │ ├── binary_operator_loc: (2,2)-(2,4) = "-=" │ ├── value: │ │ @ IntegerNode (location: (2,5)-(2,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── name: :a - │ ├── operator: :- + │ ├── binary_operator: :- │ └── depth: 0 ├── @ LocalVariableOperatorWriteNode (location: (3,0)-(3,7)) + │ ├── flags: newline │ ├── name_loc: (3,0)-(3,1) = "a" - │ ├── operator_loc: (3,2)-(3,5) = "**=" + │ ├── binary_operator_loc: (3,2)-(3,5) = "**=" │ ├── value: │ │ @ IntegerNode (location: (3,6)-(3,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── name: :a - │ ├── operator: :** + │ ├── binary_operator: :** │ └── depth: 0 ├── @ LocalVariableOperatorWriteNode (location: (4,0)-(4,6)) + │ ├── flags: newline │ ├── name_loc: (4,0)-(4,1) = "a" - │ ├── operator_loc: (4,2)-(4,4) = "*=" + │ ├── binary_operator_loc: (4,2)-(4,4) = "*=" │ ├── value: │ │ @ IntegerNode (location: (4,5)-(4,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── name: :a - │ ├── operator: :* + │ ├── binary_operator: :* │ └── depth: 0 ├── @ LocalVariableOperatorWriteNode (location: (5,0)-(5,6)) + │ ├── flags: newline │ ├── name_loc: (5,0)-(5,1) = "a" - │ ├── operator_loc: (5,2)-(5,4) = "/=" + │ ├── binary_operator_loc: (5,2)-(5,4) = "/=" │ ├── value: │ │ @ IntegerNode (location: (5,5)-(5,6)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── name: :a - │ ├── operator: :/ + │ ├── binary_operator: :/ │ └── depth: 0 ├── @ LocalVariableAndWriteNode (location: (6,0)-(6,7)) + │ ├── flags: newline │ ├── name_loc: (6,0)-(6,1) = "a" │ ├── operator_loc: (6,2)-(6,5) = "&&=" │ ├── value: @@ -70,27 +78,31 @@ │ ├── name: :a │ └── depth: 0 ├── @ LocalVariableOrWriteNode (location: (7,0)-(7,7)) + │ ├── flags: newline │ ├── name_loc: (7,0)-(7,1) = "a" │ ├── operator_loc: (7,2)-(7,5) = "||=" │ ├── value: │ │ @ IntegerNode (location: (7,6)-(7,7)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── name: :a │ └── depth: 0 ├── @ CallNode (location: (8,0)-(8,13)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ParenthesesNode (location: (8,0)-(8,9)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (8,1)-(8,8)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ LocalVariableOrWriteNode (location: (8,1)-(8,8)) + │ │ │ ├── flags: newline │ │ │ ├── name_loc: (8,1)-(8,2) = "a" │ │ │ ├── operator_loc: (8,3)-(8,6) = "||=" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (8,7)-(8,8)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ ├── name: :a │ │ │ └── depth: 0 @@ -104,17 +116,21 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (9,0)-(9,17)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ ParenthesesNode (location: (9,0)-(9,10)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (9,1)-(9,9)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ LocalVariableOrWriteNode (location: (9,1)-(9,9)) + │ │ │ ├── flags: newline │ │ │ ├── name_loc: (9,1)-(9,2) = "h" │ │ │ ├── operator_loc: (9,3)-(9,6) = "||=" │ │ │ ├── value: │ │ │ │ @ HashNode (location: (9,7)-(9,9)) + │ │ │ │ ├── flags: static_literal │ │ │ │ ├── opening_loc: (9,7)-(9,8) = "{" │ │ │ │ ├── elements: (length: 0) │ │ │ │ └── closing_loc: (9,8)-(9,9) = "}" @@ -153,89 +169,95 @@ │ ├── closing_loc: (9,12)-(9,13) = "]" │ └── block: ∅ ├── @ CallOperatorWriteNode (location: (10,0)-(10,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (10,0)-(10,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: (10,1)-(10,2) = "." │ ├── message_loc: (10,2)-(10,3) = "b" │ ├── read_name: :b │ ├── write_name: :b= - │ ├── operator: :+ - │ ├── operator_loc: (10,4)-(10,6) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (10,4)-(10,6) = "+=" │ └── value: │ @ IntegerNode (location: (10,7)-(10,8)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── @ CallOperatorWriteNode (location: (11,0)-(11,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (11,0)-(11,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: (11,1)-(11,2) = "." │ ├── message_loc: (11,2)-(11,3) = "b" │ ├── read_name: :b │ ├── write_name: :b= - │ ├── operator: :- - │ ├── operator_loc: (11,4)-(11,6) = "-=" + │ ├── binary_operator: :- + │ ├── binary_operator_loc: (11,4)-(11,6) = "-=" │ └── value: │ @ IntegerNode (location: (11,7)-(11,8)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── @ CallOperatorWriteNode (location: (12,0)-(12,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (12,0)-(12,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: (12,1)-(12,2) = "." │ ├── message_loc: (12,2)-(12,3) = "b" │ ├── read_name: :b │ ├── write_name: :b= - │ ├── operator: :** - │ ├── operator_loc: (12,4)-(12,7) = "**=" + │ ├── binary_operator: :** + │ ├── binary_operator_loc: (12,4)-(12,7) = "**=" │ └── value: │ @ IntegerNode (location: (12,8)-(12,9)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── @ CallOperatorWriteNode (location: (13,0)-(13,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (13,0)-(13,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: (13,1)-(13,2) = "." │ ├── message_loc: (13,2)-(13,3) = "b" │ ├── read_name: :b │ ├── write_name: :b= - │ ├── operator: :* - │ ├── operator_loc: (13,4)-(13,6) = "*=" + │ ├── binary_operator: :* + │ ├── binary_operator_loc: (13,4)-(13,6) = "*=" │ └── value: │ @ IntegerNode (location: (13,7)-(13,8)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── @ CallOperatorWriteNode (location: (14,0)-(14,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (14,0)-(14,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: (14,1)-(14,2) = "." │ ├── message_loc: (14,2)-(14,3) = "b" │ ├── read_name: :b │ ├── write_name: :b= - │ ├── operator: :/ - │ ├── operator_loc: (14,4)-(14,6) = "/=" + │ ├── binary_operator: :/ + │ ├── binary_operator_loc: (14,4)-(14,6) = "/=" │ └── value: │ @ IntegerNode (location: (14,7)-(14,8)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── @ CallAndWriteNode (location: (15,0)-(15,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (15,0)-(15,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: (15,1)-(15,2) = "." @@ -255,9 +277,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallOrWriteNode (location: (16,0)-(16,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (16,0)-(16,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: (16,1)-(16,2) = "." @@ -267,12 +290,13 @@ │ ├── operator_loc: (16,4)-(16,7) = "||=" │ └── value: │ @ IntegerNode (location: (16,8)-(16,9)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── @ IndexOperatorWriteNode (location: (17,0)-(17,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (17,0)-(17,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -293,16 +317,17 @@ │ │ └── block: ∅ │ ├── closing_loc: (17,3)-(17,4) = "]" │ ├── block: ∅ - │ ├── operator: :+ - │ ├── operator_loc: (17,5)-(17,7) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (17,5)-(17,7) = "+=" │ └── value: │ @ IntegerNode (location: (17,8)-(17,9)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── @ IndexOperatorWriteNode (location: (18,0)-(18,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (18,0)-(18,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -323,16 +348,17 @@ │ │ └── block: ∅ │ ├── closing_loc: (18,3)-(18,4) = "]" │ ├── block: ∅ - │ ├── operator: :- - │ ├── operator_loc: (18,5)-(18,7) = "-=" + │ ├── binary_operator: :- + │ ├── binary_operator_loc: (18,5)-(18,7) = "-=" │ └── value: │ @ IntegerNode (location: (18,8)-(18,9)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── @ IndexOperatorWriteNode (location: (19,0)-(19,10)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (19,0)-(19,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -353,16 +379,17 @@ │ │ └── block: ∅ │ ├── closing_loc: (19,3)-(19,4) = "]" │ ├── block: ∅ - │ ├── operator: :** - │ ├── operator_loc: (19,5)-(19,8) = "**=" + │ ├── binary_operator: :** + │ ├── binary_operator_loc: (19,5)-(19,8) = "**=" │ └── value: │ @ IntegerNode (location: (19,9)-(19,10)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── @ IndexOperatorWriteNode (location: (20,0)-(20,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (20,0)-(20,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -383,16 +410,17 @@ │ │ └── block: ∅ │ ├── closing_loc: (20,3)-(20,4) = "]" │ ├── block: ∅ - │ ├── operator: :* - │ ├── operator_loc: (20,5)-(20,7) = "*=" + │ ├── binary_operator: :* + │ ├── binary_operator_loc: (20,5)-(20,7) = "*=" │ └── value: │ @ IntegerNode (location: (20,8)-(20,9)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── @ IndexOperatorWriteNode (location: (21,0)-(21,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (21,0)-(21,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -413,16 +441,17 @@ │ │ └── block: ∅ │ ├── closing_loc: (21,3)-(21,4) = "]" │ ├── block: ∅ - │ ├── operator: :/ - │ ├── operator_loc: (21,5)-(21,7) = "/=" + │ ├── binary_operator: :/ + │ ├── binary_operator_loc: (21,5)-(21,7) = "/=" │ └── value: │ @ IntegerNode (location: (21,8)-(21,9)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── @ IndexAndWriteNode (location: (22,0)-(22,10)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (22,0)-(22,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -456,9 +485,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ IndexOrWriteNode (location: (23,0)-(23,10)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (23,0)-(23,1)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -482,10 +512,10 @@ │ ├── operator_loc: (23,5)-(23,8) = "||=" │ └── value: │ @ IntegerNode (location: (23,9)-(23,10)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 └── @ CallOperatorWriteNode (location: (24,0)-(24,10)) - ├── flags: ∅ + ├── flags: newline ├── receiver: │ @ CallNode (location: (24,0)-(24,3)) │ ├── flags: variable_call, ignore_visibility @@ -501,9 +531,9 @@ ├── message_loc: (24,4)-(24,5) = "A" ├── read_name: :A ├── write_name: :A= - ├── operator: :+ - ├── operator_loc: (24,6)-(24,8) = "+=" + ├── binary_operator: :+ + ├── binary_operator_loc: (24,6)-(24,8) = "+=" └── value: @ IntegerNode (location: (24,9)-(24,10)) - ├── flags: decimal + ├── flags: static_literal, decimal └── value: 1 diff --git a/test/prism/snapshots/unparser/corpus/literal/pattern.txt b/test/prism/snapshots/unparser/corpus/literal/pattern.txt index 5a0b4bb7336..200837c4503 100644 --- a/test/prism/snapshots/unparser/corpus/literal/pattern.txt +++ b/test/prism/snapshots/unparser/corpus/literal/pattern.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(41,8)) +├── flags: ∅ ├── locals: [:a, :x, :y] └── statements: @ StatementsNode (location: (1,0)-(41,8)) + ├── flags: ∅ └── body: (length: 4) ├── @ CaseMatchNode (location: (1,0)-(33,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (1,5)-(1,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -17,58 +20,69 @@ │ │ └── block: ∅ │ ├── conditions: (length: 15) │ │ ├── @ InNode (location: (2,0)-(3,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── pattern: │ │ │ │ @ ArrayPatternNode (location: (2,3)-(2,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: │ │ │ │ │ @ ConstantReadNode (location: (2,3)-(2,4)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :A │ │ │ │ ├── requireds: (length: 2) │ │ │ │ │ ├── @ IntegerNode (location: (2,5)-(2,6)) - │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ │ └── value: 1 │ │ │ │ │ └── @ IntegerNode (location: (2,8)-(2,9)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 2 │ │ │ │ ├── rest: │ │ │ │ │ @ SplatNode (location: (2,11)-(2,13)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── operator_loc: (2,11)-(2,12) = "*" │ │ │ │ │ └── expression: │ │ │ │ │ @ LocalVariableTargetNode (location: (2,12)-(2,13)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :a │ │ │ │ │ └── depth: 0 │ │ │ │ ├── posts: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (2,15)-(2,16)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 3 │ │ │ │ ├── opening_loc: (2,4)-(2,5) = "[" │ │ │ │ └── closing_loc: (2,16)-(2,17) = "]" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (3,2)-(3,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ TrueNode (location: (3,2)-(3,6)) + │ │ │ │ └── flags: newline, static_literal │ │ │ ├── in_loc: (2,0)-(2,2) = "in" │ │ │ └── then_loc: (2,18)-(2,22) = "then" │ │ ├── @ InNode (location: (4,0)-(5,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── pattern: │ │ │ │ @ ArrayPatternNode (location: (4,3)-(4,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── requireds: (length: 2) │ │ │ │ │ ├── @ IntegerNode (location: (4,4)-(4,5)) - │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ │ └── value: 1 │ │ │ │ │ └── @ IntegerNode (location: (4,7)-(4,8)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 2 │ │ │ │ ├── rest: │ │ │ │ │ @ ImplicitRestNode (location: (4,8)-(4,9)) + │ │ │ │ │ └── flags: ∅ │ │ │ │ ├── posts: (length: 0) │ │ │ │ ├── opening_loc: (4,3)-(4,4) = "[" │ │ │ │ └── closing_loc: (4,10)-(4,11) = "]" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (5,2)-(5,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (5,2)-(5,3)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :y @@ -80,24 +94,30 @@ │ │ │ ├── in_loc: (4,0)-(4,2) = "in" │ │ │ └── then_loc: (4,12)-(4,16) = "then" │ │ ├── @ InNode (location: (6,0)-(7,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── pattern: │ │ │ │ @ HashPatternNode (location: (6,3)-(6,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: │ │ │ │ │ @ ConstantReadNode (location: (6,3)-(6,4)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :A │ │ │ │ ├── elements: (length: 1) │ │ │ │ │ └── @ AssocNode (location: (6,5)-(6,7)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── key: │ │ │ │ │ │ @ SymbolNode (location: (6,5)-(6,7)) - │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ │ ├── value_loc: (6,5)-(6,6) = "x" │ │ │ │ │ │ ├── closing_loc: (6,6)-(6,7) = ":" │ │ │ │ │ │ └── unescaped: "x" │ │ │ │ │ ├── value: │ │ │ │ │ │ @ ImplicitNode (location: (6,5)-(6,6)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── value: │ │ │ │ │ │ @ LocalVariableTargetNode (location: (6,5)-(6,6)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── name: :x │ │ │ │ │ │ └── depth: 0 │ │ │ │ │ └── operator_loc: ∅ @@ -106,19 +126,25 @@ │ │ │ │ └── closing_loc: (6,7)-(6,8) = ")" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (7,2)-(7,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ TrueNode (location: (7,2)-(7,6)) + │ │ │ │ └── flags: newline, static_literal │ │ │ ├── in_loc: (6,0)-(6,2) = "in" │ │ │ └── then_loc: (6,9)-(6,13) = "then" │ │ ├── @ InNode (location: (8,0)-(9,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── pattern: │ │ │ │ @ HashPatternNode (location: (8,3)-(8,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── elements: (length: 0) │ │ │ │ ├── rest: │ │ │ │ │ @ AssocSplatNode (location: (8,4)-(8,7)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── value: │ │ │ │ │ │ @ LocalVariableTargetNode (location: (8,6)-(8,7)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── name: :a │ │ │ │ │ │ └── depth: 0 │ │ │ │ │ └── operator_loc: (8,4)-(8,6) = "**" @@ -126,47 +152,61 @@ │ │ │ │ └── closing_loc: (8,7)-(8,8) = "}" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (9,2)-(9,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ TrueNode (location: (9,2)-(9,6)) + │ │ │ │ └── flags: newline, static_literal │ │ │ ├── in_loc: (8,0)-(8,2) = "in" │ │ │ └── then_loc: (8,9)-(8,13) = "then" │ │ ├── @ InNode (location: (10,0)-(11,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── pattern: │ │ │ │ @ IfNode (location: (10,3)-(10,13)) + │ │ │ │ ├── flags: newline │ │ │ │ ├── if_keyword_loc: (10,6)-(10,8) = "if" │ │ │ │ ├── predicate: │ │ │ │ │ @ TrueNode (location: (10,9)-(10,13)) + │ │ │ │ │ └── flags: static_literal │ │ │ │ ├── then_keyword_loc: ∅ │ │ │ │ ├── statements: │ │ │ │ │ @ StatementsNode (location: (10,3)-(10,5)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ HashPatternNode (location: (10,3)-(10,5)) + │ │ │ │ │ ├── flags: newline │ │ │ │ │ ├── constant: ∅ │ │ │ │ │ ├── elements: (length: 0) │ │ │ │ │ ├── rest: ∅ │ │ │ │ │ ├── opening_loc: (10,3)-(10,4) = "{" │ │ │ │ │ └── closing_loc: (10,4)-(10,5) = "}" - │ │ │ │ ├── consequent: ∅ + │ │ │ │ ├── subsequent: ∅ │ │ │ │ └── end_keyword_loc: ∅ │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (11,2)-(11,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ TrueNode (location: (11,2)-(11,6)) + │ │ │ │ └── flags: newline, static_literal │ │ │ ├── in_loc: (10,0)-(10,2) = "in" │ │ │ └── then_loc: (10,14)-(10,18) = "then" │ │ ├── @ InNode (location: (12,0)-(13,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── pattern: │ │ │ │ @ ArrayPatternNode (location: (12,3)-(12,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── requireds: (length: 2) │ │ │ │ │ ├── @ LocalVariableTargetNode (location: (12,4)-(12,5)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── name: :x │ │ │ │ │ │ └── depth: 0 │ │ │ │ │ └── @ LocalVariableTargetNode (location: (12,7)-(12,8)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :y │ │ │ │ │ └── depth: 0 │ │ │ │ ├── rest: │ │ │ │ │ @ SplatNode (location: (12,10)-(12,11)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── operator_loc: (12,10)-(12,11) = "*" │ │ │ │ │ └── expression: ∅ │ │ │ │ ├── posts: (length: 0) @@ -174,39 +214,45 @@ │ │ │ │ └── closing_loc: (12,11)-(12,12) = "]" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (13,2)-(13,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ TrueNode (location: (13,2)-(13,6)) + │ │ │ │ └── flags: newline, static_literal │ │ │ ├── in_loc: (12,0)-(12,2) = "in" │ │ │ └── then_loc: (12,13)-(12,17) = "then" │ │ ├── @ InNode (location: (14,0)-(15,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── pattern: │ │ │ │ @ HashPatternNode (location: (14,3)-(14,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── elements: (length: 2) │ │ │ │ │ ├── @ AssocNode (location: (14,4)-(14,8)) + │ │ │ │ │ │ ├── flags: static_literal │ │ │ │ │ │ ├── key: │ │ │ │ │ │ │ @ SymbolNode (location: (14,4)-(14,6)) - │ │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ │ │ ├── value_loc: (14,4)-(14,5) = "a" │ │ │ │ │ │ │ ├── closing_loc: (14,5)-(14,6) = ":" │ │ │ │ │ │ │ └── unescaped: "a" │ │ │ │ │ │ ├── value: │ │ │ │ │ │ │ @ IntegerNode (location: (14,7)-(14,8)) - │ │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ │ │ └── value: 1 │ │ │ │ │ │ └── operator_loc: ∅ │ │ │ │ │ └── @ AssocNode (location: (14,10)-(14,15)) + │ │ │ │ │ ├── flags: static_literal │ │ │ │ │ ├── key: │ │ │ │ │ │ @ SymbolNode (location: (14,10)-(14,13)) - │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ │ ├── value_loc: (14,10)-(14,12) = "aa" │ │ │ │ │ │ ├── closing_loc: (14,12)-(14,13) = ":" │ │ │ │ │ │ └── unescaped: "aa" │ │ │ │ │ ├── value: │ │ │ │ │ │ @ IntegerNode (location: (14,14)-(14,15)) - │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ │ └── value: 2 │ │ │ │ │ └── operator_loc: ∅ │ │ │ │ ├── rest: ∅ @@ -214,13 +260,17 @@ │ │ │ │ └── closing_loc: (14,15)-(14,16) = "}" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (15,2)-(15,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ TrueNode (location: (15,2)-(15,6)) + │ │ │ │ └── flags: newline, static_literal │ │ │ ├── in_loc: (14,0)-(14,2) = "in" │ │ │ └── then_loc: (14,17)-(14,21) = "then" │ │ ├── @ InNode (location: (16,0)-(17,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── pattern: │ │ │ │ @ HashPatternNode (location: (16,3)-(16,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── elements: (length: 0) │ │ │ │ ├── rest: ∅ @@ -228,43 +278,53 @@ │ │ │ │ └── closing_loc: (16,4)-(16,5) = "}" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (17,2)-(17,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ TrueNode (location: (17,2)-(17,6)) + │ │ │ │ └── flags: newline, static_literal │ │ │ ├── in_loc: (16,0)-(16,2) = "in" │ │ │ └── then_loc: (16,6)-(16,10) = "then" │ │ ├── @ InNode (location: (18,0)-(19,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── pattern: │ │ │ │ @ HashPatternNode (location: (18,3)-(18,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── elements: (length: 0) │ │ │ │ ├── rest: │ │ │ │ │ @ NoKeywordsParameterNode (location: (18,4)-(18,9)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── operator_loc: (18,4)-(18,6) = "**" │ │ │ │ │ └── keyword_loc: (18,6)-(18,9) = "nil" │ │ │ │ ├── opening_loc: (18,3)-(18,4) = "{" │ │ │ │ └── closing_loc: (18,9)-(18,10) = "}" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (19,2)-(19,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ TrueNode (location: (19,2)-(19,6)) + │ │ │ │ └── flags: newline, static_literal │ │ │ ├── in_loc: (18,0)-(18,2) = "in" │ │ │ └── then_loc: (18,11)-(18,15) = "then" │ │ ├── @ InNode (location: (20,0)-(21,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── pattern: │ │ │ │ @ HashPatternNode (location: (20,3)-(20,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── elements: (length: 1) │ │ │ │ │ └── @ AssocNode (location: (20,4)-(20,10)) + │ │ │ │ │ ├── flags: static_literal │ │ │ │ │ ├── key: │ │ │ │ │ │ @ SymbolNode (location: (20,4)-(20,8)) - │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ │ ├── opening_loc: (20,4)-(20,5) = "\"" │ │ │ │ │ │ ├── value_loc: (20,5)-(20,6) = "a" │ │ │ │ │ │ ├── closing_loc: (20,6)-(20,8) = "\":" │ │ │ │ │ │ └── unescaped: "a" │ │ │ │ │ ├── value: │ │ │ │ │ │ @ IntegerNode (location: (20,9)-(20,10)) - │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ │ └── value: 1 │ │ │ │ │ └── operator_loc: ∅ │ │ │ │ ├── rest: ∅ @@ -272,90 +332,114 @@ │ │ │ │ └── closing_loc: (20,10)-(20,11) = "}" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (21,2)-(21,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ TrueNode (location: (21,2)-(21,6)) + │ │ │ │ └── flags: newline, static_literal │ │ │ ├── in_loc: (20,0)-(20,2) = "in" │ │ │ └── then_loc: (20,12)-(20,16) = "then" │ │ ├── @ InNode (location: (22,0)-(23,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── pattern: │ │ │ │ @ AlternationPatternNode (location: (22,3)-(22,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── left: │ │ │ │ │ @ IntegerNode (location: (22,3)-(22,4)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── right: │ │ │ │ │ @ IntegerNode (location: (22,7)-(22,8)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 2 │ │ │ │ └── operator_loc: (22,5)-(22,6) = "|" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (23,2)-(23,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ TrueNode (location: (23,2)-(23,6)) + │ │ │ │ └── flags: newline, static_literal │ │ │ ├── in_loc: (22,0)-(22,2) = "in" │ │ │ └── then_loc: (22,9)-(22,13) = "then" │ │ ├── @ InNode (location: (24,0)-(25,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── pattern: │ │ │ │ @ CapturePatternNode (location: (24,3)-(24,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── value: │ │ │ │ │ @ IntegerNode (location: (24,3)-(24,4)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── target: │ │ │ │ │ @ LocalVariableTargetNode (location: (24,8)-(24,9)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :a │ │ │ │ │ └── depth: 0 │ │ │ │ └── operator_loc: (24,5)-(24,7) = "=>" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (25,2)-(25,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ TrueNode (location: (25,2)-(25,6)) + │ │ │ │ └── flags: newline, static_literal │ │ │ ├── in_loc: (24,0)-(24,2) = "in" │ │ │ └── then_loc: (24,10)-(24,14) = "then" │ │ ├── @ InNode (location: (26,0)-(27,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── pattern: │ │ │ │ @ PinnedVariableNode (location: (26,3)-(26,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── variable: │ │ │ │ │ @ LocalVariableReadNode (location: (26,4)-(26,5)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :x │ │ │ │ │ └── depth: 0 │ │ │ │ └── operator_loc: (26,3)-(26,4) = "^" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (27,2)-(27,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ TrueNode (location: (27,2)-(27,6)) + │ │ │ │ └── flags: newline, static_literal │ │ │ ├── in_loc: (26,0)-(26,2) = "in" │ │ │ └── then_loc: (26,6)-(26,10) = "then" │ │ ├── @ InNode (location: (28,0)-(28,4)) + │ │ │ ├── flags: ∅ │ │ │ ├── pattern: │ │ │ │ @ IntegerNode (location: (28,3)-(28,4)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── statements: ∅ │ │ │ ├── in_loc: (28,0)-(28,2) = "in" │ │ │ └── then_loc: ∅ │ │ └── @ InNode (location: (29,0)-(30,6)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ IntegerNode (location: (29,3)-(29,4)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── statements: │ │ │ @ StatementsNode (location: (30,2)-(30,6)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ TrueNode (location: (30,2)-(30,6)) + │ │ │ └── flags: newline, static_literal │ │ ├── in_loc: (29,0)-(29,2) = "in" │ │ └── then_loc: (29,5)-(29,9) = "then" - │ ├── consequent: + │ ├── else_clause: │ │ @ ElseNode (location: (31,0)-(33,3)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (31,0)-(31,4) = "else" │ │ ├── statements: │ │ │ @ StatementsNode (location: (32,2)-(32,6)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ TrueNode (location: (32,2)-(32,6)) + │ │ │ └── flags: newline, static_literal │ │ └── end_keyword_loc: (33,0)-(33,3) = "end" │ ├── case_keyword_loc: (1,0)-(1,4) = "case" │ └── end_keyword_loc: (33,0)-(33,3) = "end" ├── @ CaseMatchNode (location: (34,0)-(36,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (34,5)-(34,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -369,38 +453,44 @@ │ │ └── block: ∅ │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (35,0)-(35,17)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ArrayPatternNode (location: (35,3)-(35,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── constant: │ │ │ │ @ ConstantReadNode (location: (35,3)-(35,4)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :A │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ IntegerNode (location: (35,5)-(35,6)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ └── @ IntegerNode (location: (35,8)-(35,9)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (35,11)-(35,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── operator_loc: (35,11)-(35,12) = "*" │ │ │ │ └── expression: │ │ │ │ @ LocalVariableTargetNode (location: (35,12)-(35,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ └── depth: 0 │ │ │ ├── posts: (length: 1) │ │ │ │ └── @ IntegerNode (location: (35,15)-(35,16)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 3 │ │ │ ├── opening_loc: (35,4)-(35,5) = "[" │ │ │ └── closing_loc: (35,16)-(35,17) = "]" │ │ ├── statements: ∅ │ │ ├── in_loc: (35,0)-(35,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: ∅ + │ ├── else_clause: ∅ │ ├── case_keyword_loc: (34,0)-(34,4) = "case" │ └── end_keyword_loc: (36,0)-(36,3) = "end" ├── @ CaseMatchNode (location: (37,0)-(40,3)) + │ ├── flags: newline │ ├── predicate: │ │ @ CallNode (location: (37,5)-(37,8)) │ │ ├── flags: variable_call, ignore_visibility @@ -414,29 +504,35 @@ │ │ └── block: ∅ │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (38,0)-(38,4)) + │ │ ├── flags: ∅ │ │ ├── pattern: │ │ │ @ ConstantReadNode (location: (38,3)-(38,4)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── statements: ∅ │ │ ├── in_loc: (38,0)-(38,2) = "in" │ │ └── then_loc: ∅ - │ ├── consequent: + │ ├── else_clause: │ │ @ ElseNode (location: (39,0)-(40,3)) + │ │ ├── flags: ∅ │ │ ├── else_keyword_loc: (39,0)-(39,4) = "else" │ │ ├── statements: ∅ │ │ └── end_keyword_loc: (40,0)-(40,3) = "end" │ ├── case_keyword_loc: (37,0)-(37,4) = "case" │ └── end_keyword_loc: (40,0)-(40,3) = "end" └── @ MatchPredicateNode (location: (41,0)-(41,8)) + ├── flags: newline ├── value: │ @ IntegerNode (location: (41,0)-(41,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── pattern: │ @ ArrayPatternNode (location: (41,5)-(41,8)) + │ ├── flags: ∅ │ ├── constant: ∅ │ ├── requireds: (length: 1) │ │ └── @ LocalVariableTargetNode (location: (41,6)-(41,7)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── rest: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/pragma.txt b/test/prism/snapshots/unparser/corpus/literal/pragma.txt index 08e386b872b..2a82f0c860e 100644 --- a/test/prism/snapshots/unparser/corpus/literal/pragma.txt +++ b/test/prism/snapshots/unparser/corpus/literal/pragma.txt @@ -1,15 +1,19 @@ @ ProgramNode (location: (1,0)-(4,7)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,7)) + ├── flags: ∅ └── body: (length: 4) ├── @ SourceEncodingNode (location: (1,0)-(1,12)) + │ └── flags: newline, static_literal ├── @ SourceFileNode (location: (2,0)-(2,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ └── filepath: "unparser/corpus/literal/pragma.txt" ├── @ SourceLineNode (location: (3,0)-(3,8)) + │ └── flags: newline, static_literal └── @ CallNode (location: (4,0)-(4,7)) - ├── flags: variable_call, ignore_visibility + ├── flags: newline, variable_call, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :__dir__ diff --git a/test/prism/snapshots/unparser/corpus/literal/range.txt b/test/prism/snapshots/unparser/corpus/literal/range.txt index ab015d04fce..d6bbe34b343 100644 --- a/test/prism/snapshots/unparser/corpus/literal/range.txt +++ b/test/prism/snapshots/unparser/corpus/literal/range.txt @@ -1,55 +1,61 @@ @ ProgramNode (location: (1,0)-(4,5)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,5)) + ├── flags: ∅ └── body: (length: 4) ├── @ ParenthesesNode (location: (1,0)-(1,5)) + │ ├── flags: newline │ ├── body: │ │ @ StatementsNode (location: (1,1)-(1,4)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RangeNode (location: (1,1)-(1,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline, static_literal │ │ ├── left: │ │ │ @ IntegerNode (location: (1,1)-(1,2)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (1,2)-(1,4) = ".." │ ├── opening_loc: (1,0)-(1,1) = "(" │ └── closing_loc: (1,4)-(1,5) = ")" ├── @ RangeNode (location: (2,0)-(2,4)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── left: │ │ @ IntegerNode (location: (2,0)-(2,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (2,3)-(2,4)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ └── operator_loc: (2,1)-(2,3) = ".." ├── @ ParenthesesNode (location: (3,0)-(3,6)) + │ ├── flags: newline │ ├── body: │ │ @ StatementsNode (location: (3,1)-(3,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RangeNode (location: (3,1)-(3,5)) - │ │ ├── flags: exclude_end + │ │ ├── flags: newline, static_literal, exclude_end │ │ ├── left: │ │ │ @ IntegerNode (location: (3,1)-(3,2)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (3,2)-(3,5) = "..." │ ├── opening_loc: (3,0)-(3,1) = "(" │ └── closing_loc: (3,5)-(3,6) = ")" └── @ RangeNode (location: (4,0)-(4,5)) - ├── flags: exclude_end + ├── flags: newline, static_literal, exclude_end ├── left: │ @ IntegerNode (location: (4,0)-(4,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── right: │ @ IntegerNode (location: (4,4)-(4,5)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 └── operator_loc: (4,1)-(4,4) = "..." diff --git a/test/prism/snapshots/unparser/corpus/literal/rescue.txt b/test/prism/snapshots/unparser/corpus/literal/rescue.txt index d3c9d62166e..78801c1d90a 100644 --- a/test/prism/snapshots/unparser/corpus/literal/rescue.txt +++ b/test/prism/snapshots/unparser/corpus/literal/rescue.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(3,27)) +├── flags: ∅ ├── locals: [:x] └── statements: @ StatementsNode (location: (1,0)-(3,27)) + ├── flags: ∅ └── body: (length: 3) ├── @ RescueModifierNode (location: (1,0)-(1,14)) + │ ├── flags: newline │ ├── expression: │ │ @ CallNode (location: (1,0)-(1,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -28,6 +31,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ RescueModifierNode (location: (2,0)-(2,21)) + │ ├── flags: newline │ ├── expression: │ │ @ CallNode (location: (2,0)-(2,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -59,15 +63,19 @@ │ ├── closing_loc: ∅ │ └── block: ∅ └── @ LocalVariableWriteNode (location: (3,0)-(3,27)) + ├── flags: newline ├── name: :x ├── depth: 0 ├── name_loc: (3,0)-(3,1) = "x" ├── value: │ @ ParenthesesNode (location: (3,4)-(3,27)) + │ ├── flags: ∅ │ ├── body: │ │ @ StatementsNode (location: (3,5)-(3,26)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RescueModifierNode (location: (3,5)-(3,26)) + │ │ ├── flags: newline │ │ ├── expression: │ │ │ @ CallNode (location: (3,5)-(3,8)) │ │ │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/unparser/corpus/literal/send.txt b/test/prism/snapshots/unparser/corpus/literal/send.txt index 3fd7f719a1d..4800b4e2e65 100644 --- a/test/prism/snapshots/unparser/corpus/literal/send.txt +++ b/test/prism/snapshots/unparser/corpus/literal/send.txt @@ -1,31 +1,42 @@ @ ProgramNode (location: (1,0)-(84,7)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(84,7)) + ├── flags: ∅ └── body: (length: 62) ├── @ ModuleNode (location: (1,0)-(3,3)) + │ ├── flags: newline │ ├── locals: [:foo, :a, :_] │ ├── module_keyword_loc: (1,0)-(1,6) = "module" │ ├── constant_path: │ │ @ ConstantReadNode (location: (1,7)-(1,8)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── body: │ │ @ StatementsNode (location: (2,2)-(2,22)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableOrWriteNode (location: (2,2)-(2,22)) + │ │ ├── flags: newline │ │ ├── name_loc: (2,2)-(2,5) = "foo" │ │ ├── operator_loc: (2,6)-(2,9) = "||=" │ │ ├── value: │ │ │ @ ParenthesesNode (location: (2,10)-(2,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (2,11)-(2,21)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ MultiWriteNode (location: (2,11)-(2,21)) + │ │ │ │ ├── flags: newline │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ ├── @ LocalVariableTargetNode (location: (2,12)-(2,13)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── name: :a │ │ │ │ │ │ └── depth: 0 │ │ │ │ │ └── @ LocalVariableTargetNode (location: (2,15)-(2,16)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :_ │ │ │ │ │ └── depth: 0 │ │ │ │ ├── rest: ∅ @@ -51,27 +62,32 @@ │ ├── end_keyword_loc: (3,0)-(3,3) = "end" │ └── name: :A ├── @ ModuleNode (location: (5,0)-(8,3)) + │ ├── flags: newline │ ├── locals: [:local] │ ├── module_keyword_loc: (5,0)-(5,6) = "module" │ ├── constant_path: │ │ @ ConstantReadNode (location: (5,7)-(5,8)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── body: │ │ @ StatementsNode (location: (6,2)-(7,11)) + │ │ ├── flags: ∅ │ │ └── body: (length: 2) │ │ ├── @ LocalVariableWriteNode (location: (6,2)-(6,11)) + │ │ │ ├── flags: newline │ │ │ ├── name: :local │ │ │ ├── depth: 0 │ │ │ ├── name_loc: (6,2)-(6,7) = "local" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (6,10)-(6,11)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── operator_loc: (6,8)-(6,9) = "=" │ │ └── @ CallNode (location: (7,2)-(7,11)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── receiver: │ │ │ @ LocalVariableReadNode (location: (7,2)-(7,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :local │ │ │ └── depth: 0 │ │ ├── call_operator_loc: (7,7)-(7,8) = "." @@ -84,13 +100,15 @@ │ ├── end_keyword_loc: (8,0)-(8,3) = "end" │ └── name: :A ├── @ CallNode (location: (9,0)-(10,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ClassNode (location: (9,0)-(10,3)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── class_keyword_loc: (9,0)-(9,5) = "class" │ │ ├── constant_path: │ │ │ @ ConstantReadNode (location: (9,6)-(9,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── inheritance_operator_loc: ∅ │ │ ├── superclass: ∅ @@ -105,13 +123,15 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (11,0)-(12,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ModuleNode (location: (11,0)-(12,3)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── module_keyword_loc: (11,0)-(11,6) = "module" │ │ ├── constant_path: │ │ │ @ ConstantReadNode (location: (11,7)-(11,8)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :A │ │ ├── body: ∅ │ │ ├── end_keyword_loc: (12,0)-(12,3) = "end" @@ -124,19 +144,21 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (13,0)-(15,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ BeginNode (location: (13,0)-(15,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: (13,0)-(13,5) = "begin" │ │ ├── statements: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (14,0)-(14,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (14,0)-(14,6) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (15,0)-(15,3) = "end" @@ -148,15 +170,19 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (16,0)-(19,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CaseNode (location: (16,0)-(19,3)) + │ │ ├── flags: ∅ │ │ ├── predicate: │ │ │ @ ParenthesesNode (location: (16,5)-(17,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (16,6)-(17,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 2) │ │ │ │ ├── @ DefNode (location: (16,6)-(17,3)) + │ │ │ │ │ ├── flags: newline │ │ │ │ │ ├── name: :foo │ │ │ │ │ ├── name_loc: (16,10)-(16,13) = "foo" │ │ │ │ │ ├── receiver: ∅ @@ -170,7 +196,7 @@ │ │ │ │ │ ├── equal_loc: ∅ │ │ │ │ │ └── end_keyword_loc: (17,0)-(17,3) = "end" │ │ │ │ └── @ SymbolNode (location: (17,5)-(17,9)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (17,5)-(17,6) = ":" │ │ │ │ ├── value_loc: (17,6)-(17,9) = "bar" │ │ │ │ ├── closing_loc: ∅ @@ -179,6 +205,7 @@ │ │ │ └── closing_loc: (17,9)-(17,10) = ")" │ │ ├── conditions: (length: 1) │ │ │ └── @ WhenNode (location: (18,0)-(18,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (18,0)-(18,4) = "when" │ │ │ ├── conditions: (length: 1) │ │ │ │ └── @ CallNode (location: (18,5)-(18,8)) @@ -193,7 +220,7 @@ │ │ │ │ └── block: ∅ │ │ │ ├── then_keyword_loc: ∅ │ │ │ └── statements: ∅ - │ │ ├── consequent: ∅ + │ │ ├── else_clause: ∅ │ │ ├── case_keyword_loc: (16,0)-(16,4) = "case" │ │ └── end_keyword_loc: (19,0)-(19,3) = "end" │ ├── call_operator_loc: (19,3)-(19,4) = "." @@ -204,9 +231,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (20,0)-(22,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CaseNode (location: (20,0)-(22,3)) + │ │ ├── flags: ∅ │ │ ├── predicate: │ │ │ @ CallNode (location: (20,5)-(20,8)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -220,6 +248,7 @@ │ │ │ └── block: ∅ │ │ ├── conditions: (length: 1) │ │ │ └── @ WhenNode (location: (21,0)-(21,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (21,0)-(21,4) = "when" │ │ │ ├── conditions: (length: 1) │ │ │ │ └── @ CallNode (location: (21,5)-(21,8)) @@ -234,7 +263,7 @@ │ │ │ │ └── block: ∅ │ │ │ ├── then_keyword_loc: ∅ │ │ │ └── statements: ∅ - │ │ ├── consequent: ∅ + │ │ ├── else_clause: ∅ │ │ ├── case_keyword_loc: (20,0)-(20,4) = "case" │ │ └── end_keyword_loc: (22,0)-(22,3) = "end" │ ├── call_operator_loc: (22,3)-(22,4) = "." @@ -245,14 +274,16 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (23,0)-(24,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ SingletonClassNode (location: (23,0)-(24,3)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── class_keyword_loc: (23,0)-(23,5) = "class" │ │ ├── operator_loc: (23,6)-(23,8) = "<<" │ │ ├── expression: │ │ │ @ SelfNode (location: (23,9)-(23,13)) + │ │ │ └── flags: ∅ │ │ ├── body: ∅ │ │ └── end_keyword_loc: (24,0)-(24,3) = "end" │ ├── call_operator_loc: (24,3)-(24,4) = "." @@ -263,13 +294,15 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (25,0)-(26,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ DefNode (location: (25,0)-(26,3)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ ├── name_loc: (25,9)-(25,12) = "foo" │ │ ├── receiver: │ │ │ @ SelfNode (location: (25,4)-(25,8)) + │ │ │ └── flags: ∅ │ │ ├── parameters: ∅ │ │ ├── body: ∅ │ │ ├── locals: [] @@ -287,9 +320,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (27,0)-(28,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ DefNode (location: (27,0)-(28,3)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ ├── name_loc: (27,4)-(27,7) = "foo" │ │ ├── receiver: ∅ @@ -310,7 +344,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (29,0)-(30,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ UntilNode (location: (29,0)-(30,3)) │ │ ├── flags: ∅ @@ -336,7 +370,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (31,0)-(32,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ WhileNode (location: (31,0)-(32,3)) │ │ ├── flags: ∅ @@ -362,7 +396,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (33,0)-(34,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (33,0)-(34,1)) │ │ ├── flags: ignore_visibility @@ -375,6 +409,7 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (33,5)-(34,1)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: ∅ @@ -388,9 +423,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (35,0)-(36,7)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ IfNode (location: (35,0)-(36,3)) + │ │ ├── flags: newline │ │ ├── if_keyword_loc: (35,0)-(35,2) = "if" │ │ ├── predicate: │ │ │ @ CallNode (location: (35,3)-(35,6)) @@ -405,7 +441,7 @@ │ │ │ └── block: ∅ │ │ ├── then_keyword_loc: ∅ │ │ ├── statements: ∅ - │ │ ├── consequent: ∅ + │ │ ├── subsequent: ∅ │ │ └── end_keyword_loc: (36,0)-(36,3) = "end" │ ├── call_operator_loc: (36,3)-(36,4) = "." │ ├── name: :baz @@ -415,17 +451,19 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (37,0)-(37,19)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ParenthesesNode (location: (37,0)-(37,15)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (37,1)-(37,14)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (37,1)-(37,14)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ RegularExpressionNode (location: (37,1)-(37,6)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (37,1)-(37,2) = "/" │ │ │ │ ├── content_loc: (37,2)-(37,5) = "bar" │ │ │ │ ├── closing_loc: (37,5)-(37,6) = "/" @@ -439,7 +477,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ SymbolNode (location: (37,10)-(37,14)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (37,10)-(37,11) = ":" │ │ │ │ ├── value_loc: (37,11)-(37,14) = "foo" │ │ │ │ ├── closing_loc: ∅ @@ -456,21 +494,23 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (38,0)-(38,10)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ParenthesesNode (location: (38,0)-(38,6)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (38,1)-(38,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ RangeNode (location: (38,1)-(38,5)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline, static_literal │ │ │ ├── left: │ │ │ │ @ IntegerNode (location: (38,1)-(38,2)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── right: │ │ │ │ @ IntegerNode (location: (38,4)-(38,5)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 2 │ │ │ └── operator_loc: (38,2)-(38,4) = ".." │ │ ├── opening_loc: (38,0)-(38,1) = "(" @@ -483,14 +523,16 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (39,0)-(39,18)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ParenthesesNode (location: (39,0)-(39,14)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (39,1)-(39,13)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (39,1)-(39,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ CallNode (location: (39,1)-(39,4)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -511,7 +553,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ RegularExpressionNode (location: (39,8)-(39,13)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (39,8)-(39,9) = "/" │ │ │ │ ├── content_loc: (39,9)-(39,12) = "bar" │ │ │ │ ├── closing_loc: (39,12)-(39,13) = "/" @@ -528,10 +570,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (40,0)-(40,13)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RegularExpressionNode (location: (40,0)-(40,5)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (40,0)-(40,1) = "/" │ │ ├── content_loc: (40,1)-(40,4) = "bar" │ │ ├── closing_loc: (40,4)-(40,5) = "/" @@ -545,7 +587,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (40,9)-(40,13)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (40,9)-(40,10) = ":" │ │ ├── value_loc: (40,10)-(40,13) = "foo" │ │ ├── closing_loc: ∅ @@ -553,10 +595,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (41,0)-(41,12)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ RegularExpressionNode (location: (41,0)-(41,5)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (41,0)-(41,1) = "/" │ │ ├── content_loc: (41,1)-(41,4) = "bar" │ │ ├── closing_loc: (41,4)-(41,5) = "/" @@ -582,17 +624,17 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ RangeNode (location: (42,0)-(42,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── left: │ │ @ IntegerNode (location: (42,0)-(42,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── right: │ │ @ CallNode (location: (42,3)-(42,8)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (42,3)-(42,4)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ ├── call_operator_loc: (42,4)-(42,5) = "." │ │ ├── name: :max @@ -603,9 +645,10 @@ │ │ └── block: ∅ │ └── operator_loc: (42,1)-(42,3) = ".." ├── @ CallNode (location: (43,0)-(43,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ConstantReadNode (location: (43,0)-(43,1)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── call_operator_loc: (43,1)-(43,2) = "." │ ├── name: :foo @@ -615,7 +658,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (44,0)-(44,5)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :FOO @@ -625,7 +668,7 @@ │ ├── closing_loc: (44,4)-(44,5) = ")" │ └── block: ∅ ├── @ CallNode (location: (45,0)-(45,4)) - │ ├── flags: safe_navigation + │ ├── flags: newline, safe_navigation │ ├── receiver: │ │ @ CallNode (location: (45,0)-(45,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -645,7 +688,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (46,0)-(46,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (46,0)-(46,1)) │ │ ├── flags: variable_call, ignore_visibility @@ -665,7 +708,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (47,0)-(47,3)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -675,7 +718,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (48,0)-(48,18)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (48,0)-(48,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -696,11 +739,13 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ ParenthesesNode (location: (48,7)-(48,18)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (48,8)-(48,17)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (48,8)-(48,17)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ CallNode (location: (48,8)-(48,11)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -737,7 +782,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (49,0)-(49,12)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (49,0)-(49,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -758,7 +803,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ RegularExpressionNode (location: (49,7)-(49,12)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (49,7)-(49,8) = "/" │ │ ├── content_loc: (49,8)-(49,11) = "bar" │ │ ├── closing_loc: (49,11)-(49,12) = "/" @@ -766,7 +811,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (50,0)-(50,17)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -776,12 +821,16 @@ │ ├── closing_loc: (50,17)-(50,18) = ")" │ └── block: │ @ BlockArgumentNode (location: (50,4)-(50,17)) + │ ├── flags: ∅ │ ├── expression: │ │ @ ParenthesesNode (location: (50,5)-(50,17)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (50,6)-(50,16)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ OrNode (location: (50,6)-(50,16)) + │ │ │ ├── flags: newline │ │ │ ├── left: │ │ │ │ @ CallNode (location: (50,6)-(50,9)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -809,7 +858,7 @@ │ │ └── closing_loc: (50,16)-(50,17) = ")" │ └── operator_loc: (50,4)-(50,5) = "&" ├── @ CallNode (location: (51,0)-(51,10)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -819,6 +868,7 @@ │ ├── closing_loc: (51,10)-(51,11) = ")" │ └── block: │ @ BlockArgumentNode (location: (51,4)-(51,10)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (51,5)-(51,10)) │ │ ├── flags: variable_call, ignore_visibility @@ -832,7 +882,7 @@ │ │ └── block: ∅ │ └── operator_loc: (51,4)-(51,5) = "&" ├── @ CallNode (location: (52,0)-(52,17)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -840,9 +890,10 @@ │ ├── opening_loc: (52,3)-(52,4) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (52,4)-(52,9)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat │ │ └── arguments: (length: 1) │ │ └── @ SplatNode (location: (52,4)-(52,9)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (52,4)-(52,5) = "*" │ │ └── expression: │ │ @ CallNode (location: (52,5)-(52,9)) @@ -858,6 +909,7 @@ │ ├── closing_loc: (52,17)-(52,18) = ")" │ └── block: │ @ BlockArgumentNode (location: (52,11)-(52,17)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (52,12)-(52,17)) │ │ ├── flags: variable_call, ignore_visibility @@ -871,7 +923,7 @@ │ │ └── block: ∅ │ └── operator_loc: (52,11)-(52,12) = "&" ├── @ CallNode (location: (53,0)-(53,15)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -879,9 +931,10 @@ │ ├── opening_loc: (53,3)-(53,4) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (53,4)-(53,14)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat │ │ └── arguments: (length: 1) │ │ └── @ SplatNode (location: (53,4)-(53,14)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (53,4)-(53,5) = "*" │ │ └── expression: │ │ @ CallNode (location: (53,5)-(53,14)) @@ -897,7 +950,7 @@ │ ├── closing_loc: (53,14)-(53,15) = ")" │ └── block: ∅ ├── @ CallNode (location: (54,0)-(54,9)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -908,15 +961,15 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (54,4)-(54,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (54,7)-(54,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: (54,8)-(54,9) = ")" │ └── block: ∅ ├── @ CallNode (location: (55,0)-(55,8)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -939,7 +992,7 @@ │ ├── closing_loc: (55,7)-(55,8) = ")" │ └── block: ∅ ├── @ CallNode (location: (56,0)-(56,15)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -947,7 +1000,7 @@ │ ├── opening_loc: (56,3)-(56,4) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (56,4)-(56,14)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat │ │ └── arguments: (length: 2) │ │ ├── @ CallNode (location: (56,4)-(56,7)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -960,6 +1013,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ SplatNode (location: (56,9)-(56,14)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (56,9)-(56,10) = "*" │ │ └── expression: │ │ @ CallNode (location: (56,10)-(56,14)) @@ -975,7 +1029,7 @@ │ ├── closing_loc: (56,14)-(56,15) = ")" │ └── block: ∅ ├── @ CallNode (location: (57,0)-(57,17)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1007,7 +1061,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ RegularExpressionNode (location: (57,11)-(57,16)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (57,11)-(57,12) = "/" │ │ │ ├── content_loc: (57,12)-(57,15) = "bar" │ │ │ ├── closing_loc: (57,15)-(57,16) = "/" @@ -1017,7 +1071,7 @@ │ ├── closing_loc: (57,16)-(57,17) = ")" │ └── block: ∅ ├── @ CallNode (location: (58,0)-(58,13)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (58,0)-(58,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1037,6 +1091,7 @@ │ ├── closing_loc: (58,12)-(58,13) = ")" │ └── block: │ @ BlockArgumentNode (location: (58,8)-(58,12)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (58,9)-(58,12)) │ │ ├── flags: variable_call, ignore_visibility @@ -1050,7 +1105,7 @@ │ │ └── block: ∅ │ └── operator_loc: (58,8)-(58,9) = "&" ├── @ CallNode (location: (59,0)-(59,26)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (59,0)-(59,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1068,9 +1123,10 @@ │ ├── opening_loc: (59,7)-(59,8) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (59,8)-(59,25)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat, contains_multiple_splats │ │ └── arguments: (length: 3) │ │ ├── @ SplatNode (location: (59,8)-(59,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (59,8)-(59,9) = "*" │ │ │ └── expression: │ │ │ @ CallNode (location: (59,9)-(59,13)) @@ -1094,6 +1150,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ SplatNode (location: (59,20)-(59,25)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (59,20)-(59,21) = "*" │ │ └── expression: │ │ @ CallNode (location: (59,21)-(59,25)) @@ -1109,7 +1166,7 @@ │ ├── closing_loc: (59,25)-(59,26) = ")" │ └── block: ∅ ├── @ CallNode (location: (60,0)-(60,14)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (60,0)-(60,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1127,9 +1184,10 @@ │ ├── opening_loc: (60,7)-(60,8) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (60,8)-(60,13)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat │ │ └── arguments: (length: 1) │ │ └── @ SplatNode (location: (60,8)-(60,13)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (60,8)-(60,9) = "*" │ │ └── expression: │ │ @ CallNode (location: (60,9)-(60,13)) @@ -1145,7 +1203,7 @@ │ ├── closing_loc: (60,13)-(60,14) = ")" │ └── block: ∅ ├── @ CallNode (location: (61,0)-(61,19)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (61,0)-(61,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1163,9 +1221,10 @@ │ ├── opening_loc: (61,7)-(61,8) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (61,8)-(61,18)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat │ │ └── arguments: (length: 2) │ │ ├── @ SplatNode (location: (61,8)-(61,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (61,8)-(61,9) = "*" │ │ │ └── expression: │ │ │ @ CallNode (location: (61,9)-(61,13)) @@ -1191,7 +1250,7 @@ │ ├── closing_loc: (61,18)-(61,19) = ")" │ └── block: ∅ ├── @ CallNode (location: (62,0)-(62,19)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (62,0)-(62,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1212,7 +1271,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (62,8)-(62,12)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (62,8)-(62,9) = ":" │ │ ├── value_loc: (62,9)-(62,12) = "baz" │ │ ├── closing_loc: ∅ @@ -1220,6 +1279,7 @@ │ ├── closing_loc: (62,18)-(62,19) = ")" │ └── block: │ @ BlockArgumentNode (location: (62,14)-(62,18)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (62,15)-(62,18)) │ │ ├── flags: variable_call, ignore_visibility @@ -1233,7 +1293,7 @@ │ │ └── block: ∅ │ └── operator_loc: (62,14)-(62,15) = "&" ├── @ CallNode (location: (63,0)-(63,17)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (63,0)-(63,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1257,9 +1317,10 @@ │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (63,8)-(63,16)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ SymbolNode (location: (63,8)-(63,12)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (63,8)-(63,11) = "baz" │ │ │ ├── closing_loc: (63,11)-(63,12) = ":" @@ -1279,7 +1340,7 @@ │ ├── closing_loc: (63,16)-(63,17) = ")" │ └── block: ∅ ├── @ CallNode (location: (64,0)-(64,26)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (64,0)-(64,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1313,9 +1374,10 @@ │ │ ├── flags: ∅ │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (64,13)-(64,25)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ StringNode (location: (64,13)-(64,18)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: (64,13)-(64,14) = "\"" │ │ │ ├── content_loc: (64,14)-(64,17) = "baz" │ │ │ ├── closing_loc: (64,17)-(64,18) = "\"" @@ -1335,7 +1397,7 @@ │ ├── closing_loc: (64,25)-(64,26) = ")" │ └── block: ∅ ├── @ CallNode (location: (65,0)-(65,19)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (65,0)-(65,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1353,7 +1415,7 @@ │ ├── opening_loc: (65,7)-(65,8) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (65,8)-(65,18)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat │ │ └── arguments: (length: 2) │ │ ├── @ CallNode (location: (65,8)-(65,11)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -1366,6 +1428,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ SplatNode (location: (65,13)-(65,18)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (65,13)-(65,14) = "*" │ │ └── expression: │ │ @ CallNode (location: (65,14)-(65,18)) @@ -1381,7 +1444,7 @@ │ ├── closing_loc: (65,18)-(65,19) = ")" │ └── block: ∅ ├── @ CallNode (location: (66,0)-(66,27)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (66,0)-(66,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1399,7 +1462,7 @@ │ ├── opening_loc: (66,7)-(66,8) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (66,8)-(66,18)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat │ │ └── arguments: (length: 2) │ │ ├── @ CallNode (location: (66,8)-(66,11)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -1412,6 +1475,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ SplatNode (location: (66,13)-(66,18)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (66,13)-(66,14) = "*" │ │ └── expression: │ │ @ CallNode (location: (66,14)-(66,18)) @@ -1427,6 +1491,7 @@ │ ├── closing_loc: (66,26)-(66,27) = ")" │ └── block: │ @ BlockArgumentNode (location: (66,20)-(66,26)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (66,21)-(66,26)) │ │ ├── flags: variable_call, ignore_visibility @@ -1440,7 +1505,7 @@ │ │ └── block: ∅ │ └── operator_loc: (66,20)-(66,21) = "&" ├── @ CallNode (location: (67,0)-(67,16)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (67,0)-(67,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1471,13 +1536,14 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ HashNode (location: (67,13)-(67,15)) + │ │ ├── flags: static_literal │ │ ├── opening_loc: (67,13)-(67,14) = "{" │ │ ├── elements: (length: 0) │ │ └── closing_loc: (67,14)-(67,15) = "}" │ ├── closing_loc: (67,15)-(67,16) = ")" │ └── block: ∅ ├── @ CallNode (location: (68,0)-(68,26)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (68,0)-(68,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1498,12 +1564,14 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ HashNode (location: (68,8)-(68,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (68,8)-(68,9) = "{" │ │ │ ├── elements: (length: 1) │ │ │ │ └── @ AssocNode (location: (68,10)-(68,18)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (68,10)-(68,14)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (68,10)-(68,13) = "foo" │ │ │ │ │ ├── closing_loc: (68,13)-(68,14) = ":" @@ -1534,7 +1602,7 @@ │ ├── closing_loc: (68,25)-(68,26) = ")" │ └── block: ∅ ├── @ CallNode (location: (69,0)-(69,12)) - │ ├── flags: attribute_write + │ ├── flags: newline, attribute_write │ ├── receiver: │ │ @ CallNode (location: (69,0)-(69,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1555,7 +1623,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (69,8)-(69,12)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (69,8)-(69,9) = ":" │ │ ├── value_loc: (69,9)-(69,12) = "baz" │ │ ├── closing_loc: ∅ @@ -1563,7 +1631,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (70,0)-(70,9)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -1577,9 +1645,10 @@ │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (70,4)-(70,8)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ SymbolNode (location: (70,4)-(70,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (70,4)-(70,5) = "a" │ │ │ ├── closing_loc: (70,5)-(70,6) = ":" @@ -1599,7 +1668,7 @@ │ ├── closing_loc: (70,8)-(70,9) = ")" │ └── block: ∅ ├── @ CallNode (location: (71,0)-(71,11)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (71,0)-(71,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1623,9 +1692,10 @@ │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) │ │ └── @ AssocNode (location: (71,6)-(71,10)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ SymbolNode (location: (71,6)-(71,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (71,6)-(71,7) = "a" │ │ │ ├── closing_loc: (71,7)-(71,8) = ":" @@ -1645,7 +1715,7 @@ │ ├── closing_loc: (71,10)-(71,11) = ")" │ └── block: ∅ ├── @ CallNode (location: (72,0)-(72,10)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (72,0)-(72,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1669,6 +1739,7 @@ │ │ ├── flags: ∅ │ │ └── elements: (length: 1) │ │ └── @ AssocSplatNode (location: (72,6)-(72,9)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ CallNode (location: (72,8)-(72,9)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -1684,7 +1755,7 @@ │ ├── closing_loc: (72,9)-(72,10) = ")" │ └── block: ∅ ├── @ CallNode (location: (73,0)-(73,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (73,0)-(73,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1702,9 +1773,10 @@ │ ├── opening_loc: (73,3)-(73,4) = "[" │ ├── arguments: │ │ @ ArgumentsNode (location: (73,4)-(73,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat │ │ └── arguments: (length: 1) │ │ └── @ SplatNode (location: (73,4)-(73,8)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (73,4)-(73,5) = "*" │ │ └── expression: │ │ @ CallNode (location: (73,5)-(73,8)) @@ -1720,7 +1792,7 @@ │ ├── closing_loc: (73,8)-(73,9) = "]" │ └── block: ∅ ├── @ CallNode (location: (74,0)-(74,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (74,0)-(74,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1741,15 +1813,15 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (74,4)-(74,5)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (74,7)-(74,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── closing_loc: (74,8)-(74,9) = "]" │ └── block: ∅ ├── @ CallNode (location: (75,0)-(75,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (75,0)-(75,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -1769,9 +1841,10 @@ │ ├── closing_loc: (75,4)-(75,5) = "]" │ └── block: ∅ ├── @ CallNode (location: (76,0)-(76,8)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: │ │ @ SelfNode (location: (76,0)-(76,4)) + │ │ └── flags: ∅ │ ├── call_operator_loc: (76,4)-(76,5) = "." │ ├── name: :foo │ ├── message_loc: (76,5)-(76,8) = "foo" @@ -1780,9 +1853,10 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (77,0)-(77,13)) - │ ├── flags: attribute_write, ignore_visibility + │ ├── flags: newline, attribute_write, ignore_visibility │ ├── receiver: │ │ @ SelfNode (location: (77,0)-(77,4)) + │ │ └── flags: ∅ │ ├── call_operator_loc: (77,4)-(77,5) = "." │ ├── name: :foo= │ ├── message_loc: (77,5)-(77,8) = "foo" @@ -1792,7 +1866,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (77,9)-(77,13)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (77,9)-(77,10) = ":" │ │ ├── value_loc: (77,10)-(77,13) = "bar" │ │ ├── closing_loc: ∅ @@ -1800,14 +1874,16 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (78,0)-(78,17)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ParenthesesNode (location: (78,0)-(78,7)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (78,1)-(78,6)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (78,1)-(78,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ CallNode (location: (78,1)-(78,2)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -1850,11 +1926,13 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ ParenthesesNode (location: (78,10)-(78,17)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (78,11)-(78,16)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (78,11)-(78,16)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ CallNode (location: (78,11)-(78,12)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -1891,14 +1969,16 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (79,0)-(79,19)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ParenthesesNode (location: (79,0)-(79,7)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (79,1)-(79,6)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (79,1)-(79,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ CallNode (location: (79,1)-(79,2)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -1986,14 +2066,16 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (80,0)-(80,17)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ParenthesesNode (location: (80,0)-(80,7)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (80,1)-(80,6)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (80,1)-(80,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ CallNode (location: (80,1)-(80,2)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -2054,9 +2136,10 @@ │ │ ├── opening_loc: (80,13)-(80,14) = "(" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (80,14)-(80,16)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_splat │ │ │ └── arguments: (length: 1) │ │ │ └── @ SplatNode (location: (80,14)-(80,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (80,14)-(80,15) = "*" │ │ │ └── expression: │ │ │ @ CallNode (location: (80,15)-(80,16)) @@ -2074,7 +2157,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (81,0)-(81,8)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :x @@ -2088,6 +2171,7 @@ │ │ ├── flags: ∅ │ │ └── elements: (length: 1) │ │ └── @ AssocSplatNode (location: (81,2)-(81,7)) + │ │ ├── flags: ∅ │ │ ├── value: │ │ │ @ CallNode (location: (81,4)-(81,7)) │ │ │ ├── flags: variable_call, ignore_visibility @@ -2103,7 +2187,7 @@ │ ├── closing_loc: (81,7)-(81,8) = ")" │ └── block: ∅ ├── @ CallNode (location: (82,0)-(82,6)) - │ ├── flags: safe_navigation + │ ├── flags: newline, safe_navigation │ ├── receiver: │ │ @ CallNode (location: (82,0)-(82,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2123,7 +2207,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (83,0)-(83,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (83,0)-(83,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -2156,7 +2240,7 @@ │ ├── closing_loc: (83,7)-(83,8) = ")" │ └── block: ∅ └── @ CallNode (location: (84,0)-(84,7)) - ├── flags: safe_navigation + ├── flags: newline, safe_navigation ├── receiver: │ @ CallNode (location: (84,0)-(84,1)) │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/unparser/corpus/literal/since/27.txt b/test/prism/snapshots/unparser/corpus/literal/since/27.txt index 60edc18604f..e4cda312f83 100644 --- a/test/prism/snapshots/unparser/corpus/literal/since/27.txt +++ b/test/prism/snapshots/unparser/corpus/literal/since/27.txt @@ -1,23 +1,29 @@ @ ProgramNode (location: (1,0)-(4,5)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,5)) + ├── flags: ∅ └── body: (length: 2) ├── @ LambdaNode (location: (1,0)-(3,1)) + │ ├── flags: newline │ ├── locals: [:_1, :_2] │ ├── operator_loc: (1,0)-(1,2) = "->" │ ├── opening_loc: (1,3)-(1,4) = "{" │ ├── closing_loc: (3,0)-(3,1) = "}" │ ├── parameters: │ │ @ NumberedParametersNode (location: (1,0)-(3,1)) + │ │ ├── flags: ∅ │ │ └── maximum: 2 │ └── body: │ @ StatementsNode (location: (2,2)-(2,9)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (2,2)-(2,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ LocalVariableReadNode (location: (2,2)-(2,4)) + │ │ ├── flags: ∅ │ │ ├── name: :_1 │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -29,20 +35,23 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ LocalVariableReadNode (location: (2,7)-(2,9)) + │ │ ├── flags: ∅ │ │ ├── name: :_2 │ │ └── depth: 0 │ ├── closing_loc: ∅ │ └── block: ∅ └── @ ParenthesesNode (location: (4,0)-(4,5)) + ├── flags: newline ├── body: │ @ StatementsNode (location: (4,1)-(4,4)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ RangeNode (location: (4,1)-(4,4)) - │ ├── flags: ∅ + │ ├── flags: newline, static_literal │ ├── left: ∅ │ ├── right: │ │ @ IntegerNode (location: (4,3)-(4,4)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ └── operator_loc: (4,1)-(4,3) = ".." ├── opening_loc: (4,0)-(4,1) = "(" diff --git a/test/prism/snapshots/unparser/corpus/literal/since/30.txt b/test/prism/snapshots/unparser/corpus/literal/since/30.txt index 300dd869f5a..0102b2c97b4 100644 --- a/test/prism/snapshots/unparser/corpus/literal/since/30.txt +++ b/test/prism/snapshots/unparser/corpus/literal/since/30.txt @@ -1,18 +1,23 @@ @ ProgramNode (location: (1,0)-(4,17)) +├── flags: ∅ ├── locals: [:a, :foo] └── statements: @ StatementsNode (location: (1,0)-(4,17)) + ├── flags: ∅ └── body: (length: 4) ├── @ MatchRequiredNode (location: (1,0)-(1,8)) + │ ├── flags: newline │ ├── value: │ │ @ IntegerNode (location: (1,0)-(1,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── pattern: │ │ @ ArrayPatternNode (location: (1,5)-(1,8)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ LocalVariableTargetNode (location: (1,6)-(1,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── rest: ∅ @@ -21,16 +26,19 @@ │ │ └── closing_loc: (1,7)-(1,8) = "]" │ └── operator_loc: (1,2)-(1,4) = "=>" ├── @ MatchRequiredNode (location: (2,0)-(2,8)) + │ ├── flags: newline │ ├── value: │ │ @ IntegerNode (location: (2,0)-(2,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── pattern: │ │ @ ArrayPatternNode (location: (2,5)-(2,8)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 0) │ │ ├── rest: │ │ │ @ SplatNode (location: (2,6)-(2,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (2,6)-(2,7) = "*" │ │ │ └── expression: ∅ │ │ ├── posts: (length: 0) @@ -38,49 +46,59 @@ │ │ └── closing_loc: (2,7)-(2,8) = "]" │ └── operator_loc: (2,2)-(2,4) = "=>" ├── @ MatchPredicateNode (location: (3,0)-(3,15)) + │ ├── flags: newline │ ├── value: │ │ @ IntegerNode (location: (3,0)-(3,1)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── pattern: │ │ @ FindPatternNode (location: (3,5)-(3,15)) + │ │ ├── flags: ∅ │ │ ├── constant: ∅ │ │ ├── left: │ │ │ @ SplatNode (location: (3,6)-(3,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (3,6)-(3,7) = "*" │ │ │ └── expression: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ IntegerNode (location: (3,9)-(3,11)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 42 │ │ ├── right: │ │ │ @ SplatNode (location: (3,13)-(3,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (3,13)-(3,14) = "*" │ │ │ └── expression: ∅ │ │ ├── opening_loc: (3,5)-(3,6) = "[" │ │ └── closing_loc: (3,14)-(3,15) = "]" │ └── operator_loc: (3,2)-(3,4) = "in" └── @ MatchPredicateNode (location: (4,0)-(4,17)) + ├── flags: newline ├── value: │ @ IntegerNode (location: (4,0)-(4,1)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 1 ├── pattern: │ @ FindPatternNode (location: (4,5)-(4,17)) + │ ├── flags: ∅ │ ├── constant: ∅ │ ├── left: │ │ @ SplatNode (location: (4,6)-(4,7)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (4,6)-(4,7) = "*" │ │ └── expression: ∅ │ ├── requireds: (length: 1) │ │ └── @ LocalVariableTargetNode (location: (4,9)-(4,10)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── right: │ │ @ SplatNode (location: (4,12)-(4,16)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (4,12)-(4,13) = "*" │ │ └── expression: │ │ @ LocalVariableTargetNode (location: (4,13)-(4,16)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── depth: 0 │ ├── opening_loc: (4,5)-(4,6) = "[" diff --git a/test/prism/snapshots/unparser/corpus/literal/since/31.txt b/test/prism/snapshots/unparser/corpus/literal/since/31.txt index 142a56ae832..81bcd9662bd 100644 --- a/test/prism/snapshots/unparser/corpus/literal/since/31.txt +++ b/test/prism/snapshots/unparser/corpus/literal/since/31.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(7,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(7,3)) + ├── flags: ∅ └── body: (length: 2) ├── @ DefNode (location: (1,0)-(3,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (1,4)-(1,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,8)-(1,9)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -23,9 +27,10 @@ │ │ └── operator_loc: (1,8)-(1,9) = "&" │ ├── body: │ │ @ StatementsNode (location: (2,2)-(2,7)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (2,2)-(2,7)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -35,6 +40,7 @@ │ │ ├── closing_loc: (2,7)-(2,8) = ")" │ │ └── block: │ │ @ BlockArgumentNode (location: (2,6)-(2,7)) + │ │ ├── flags: ∅ │ │ ├── expression: ∅ │ │ └── operator_loc: (2,6)-(2,7) = "&" │ ├── locals: [] @@ -45,11 +51,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (3,0)-(3,3) = "end" └── @ DefNode (location: (5,0)-(7,3)) + ├── flags: newline ├── name: :foo ├── name_loc: (5,4)-(5,7) = "foo" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (5,8)-(5,12)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (5,8)-(5,9)) │ │ ├── flags: ∅ @@ -67,9 +75,10 @@ │ └── operator_loc: (5,11)-(5,12) = "&" ├── body: │ @ StatementsNode (location: (6,2)-(6,7)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (6,2)-(6,7)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :bar @@ -79,6 +88,7 @@ │ ├── closing_loc: (6,7)-(6,8) = ")" │ └── block: │ @ BlockArgumentNode (location: (6,6)-(6,7)) + │ ├── flags: ∅ │ ├── expression: ∅ │ └── operator_loc: (6,6)-(6,7) = "&" ├── locals: [:a] diff --git a/test/prism/snapshots/unparser/corpus/literal/since/32.txt b/test/prism/snapshots/unparser/corpus/literal/since/32.txt index 2b28be2fa80..2b126a0cc55 100644 --- a/test/prism/snapshots/unparser/corpus/literal/since/32.txt +++ b/test/prism/snapshots/unparser/corpus/literal/since/32.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(11,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(11,3)) + ├── flags: ∅ └── body: (length: 3) ├── @ DefNode (location: (1,0)-(3,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (1,4)-(1,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,8)-(1,20)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,8)-(1,16)) │ │ │ ├── flags: ∅ @@ -26,9 +30,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (2,2)-(2,19)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (2,2)-(2,19)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -39,12 +44,14 @@ │ │ │ ├── flags: contains_keywords, contains_keyword_splat │ │ │ └── arguments: (length: 2) │ │ │ ├── @ LocalVariableReadNode (location: (2,6)-(2,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :argument │ │ │ │ └── depth: 0 │ │ │ └── @ KeywordHashNode (location: (2,16)-(2,18)) │ │ │ ├── flags: ∅ │ │ │ └── elements: (length: 1) │ │ │ └── @ AssocSplatNode (location: (2,16)-(2,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── value: ∅ │ │ │ └── operator_loc: (2,16)-(2,18) = "**" │ │ ├── closing_loc: (2,18)-(2,19) = ")" @@ -57,11 +64,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (3,0)-(3,3) = "end" ├── @ DefNode (location: (5,0)-(7,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (5,4)-(5,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (5,8)-(5,19)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (5,8)-(5,16)) │ │ │ ├── flags: ∅ @@ -79,9 +88,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (6,2)-(6,18)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (6,2)-(6,18)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -89,12 +99,14 @@ │ │ ├── opening_loc: (6,5)-(6,6) = "(" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (6,6)-(6,17)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_splat │ │ │ └── arguments: (length: 2) │ │ │ ├── @ LocalVariableReadNode (location: (6,6)-(6,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :argument │ │ │ │ └── depth: 0 │ │ │ └── @ SplatNode (location: (6,16)-(6,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── operator_loc: (6,16)-(6,17) = "*" │ │ │ └── expression: ∅ │ │ ├── closing_loc: (6,17)-(6,18) = ")" @@ -107,11 +119,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (7,0)-(7,3) = "end" └── @ DefNode (location: (9,0)-(11,3)) + ├── flags: newline ├── name: :foo ├── name_loc: (9,4)-(9,7) = "foo" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (9,8)-(9,10)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -126,24 +140,28 @@ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (10,2)-(10,20)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ HashNode (location: (10,2)-(10,20)) + │ ├── flags: newline │ ├── opening_loc: (10,2)-(10,3) = "{" │ ├── elements: (length: 2) │ │ ├── @ AssocNode (location: (10,4)-(10,14)) + │ │ │ ├── flags: static_literal │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (10,4)-(10,12)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (10,4)-(10,11) = "default" │ │ │ │ ├── closing_loc: (10,11)-(10,12) = ":" │ │ │ │ └── unescaped: "default" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (10,13)-(10,14)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── operator_loc: ∅ │ │ └── @ AssocSplatNode (location: (10,16)-(10,18)) + │ │ ├── flags: ∅ │ │ ├── value: ∅ │ │ └── operator_loc: (10,16)-(10,18) = "**" │ └── closing_loc: (10,19)-(10,20) = "}" diff --git a/test/prism/snapshots/unparser/corpus/literal/singletons.txt b/test/prism/snapshots/unparser/corpus/literal/singletons.txt index 45c06f7b07d..23069207c93 100644 --- a/test/prism/snapshots/unparser/corpus/literal/singletons.txt +++ b/test/prism/snapshots/unparser/corpus/literal/singletons.txt @@ -1,9 +1,15 @@ @ ProgramNode (location: (1,0)-(4,4)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(4,4)) + ├── flags: ∅ └── body: (length: 4) ├── @ FalseNode (location: (1,0)-(1,5)) + │ └── flags: newline, static_literal ├── @ NilNode (location: (2,0)-(2,3)) + │ └── flags: newline, static_literal ├── @ SelfNode (location: (3,0)-(3,4)) + │ └── flags: newline └── @ TrueNode (location: (4,0)-(4,4)) + └── flags: newline, static_literal diff --git a/test/prism/snapshots/unparser/corpus/literal/super.txt b/test/prism/snapshots/unparser/corpus/literal/super.txt index d5a78899197..a6311116ca5 100644 --- a/test/prism/snapshots/unparser/corpus/literal/super.txt +++ b/test/prism/snapshots/unparser/corpus/literal/super.txt @@ -1,17 +1,22 @@ @ ProgramNode (location: (1,0)-(21,1)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(21,1)) + ├── flags: ∅ └── body: (length: 11) ├── @ ForwardingSuperNode (location: (1,0)-(1,5)) + │ ├── flags: newline │ └── block: ∅ ├── @ SuperNode (location: (2,0)-(2,7)) + │ ├── flags: newline │ ├── keyword_loc: (2,0)-(2,5) = "super" │ ├── lparen_loc: (2,5)-(2,6) = "(" │ ├── arguments: ∅ │ ├── rparen_loc: (2,6)-(2,7) = ")" │ └── block: ∅ ├── @ SuperNode (location: (3,0)-(3,8)) + │ ├── flags: newline │ ├── keyword_loc: (3,0)-(3,5) = "super" │ ├── lparen_loc: (3,5)-(3,6) = "(" │ ├── arguments: @@ -31,6 +36,7 @@ │ ├── rparen_loc: (3,7)-(3,8) = ")" │ └── block: ∅ ├── @ SuperNode (location: (4,0)-(4,11)) + │ ├── flags: newline │ ├── keyword_loc: (4,0)-(4,5) = "super" │ ├── lparen_loc: (4,5)-(4,6) = "(" │ ├── arguments: @@ -60,12 +66,14 @@ │ ├── rparen_loc: (4,10)-(4,11) = ")" │ └── block: ∅ ├── @ SuperNode (location: (5,0)-(5,13)) + │ ├── flags: newline │ ├── keyword_loc: (5,0)-(5,5) = "super" │ ├── lparen_loc: (5,5)-(5,6) = "(" │ ├── arguments: ∅ │ ├── rparen_loc: (5,12)-(5,13) = ")" │ └── block: │ @ BlockArgumentNode (location: (5,6)-(5,12)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (5,7)-(5,12)) │ │ ├── flags: variable_call, ignore_visibility @@ -79,6 +87,7 @@ │ │ └── block: ∅ │ └── operator_loc: (5,6)-(5,7) = "&" ├── @ SuperNode (location: (6,0)-(6,16)) + │ ├── flags: newline │ ├── keyword_loc: (6,0)-(6,5) = "super" │ ├── lparen_loc: (6,5)-(6,6) = "(" │ ├── arguments: @@ -98,6 +107,7 @@ │ ├── rparen_loc: (6,15)-(6,16) = ")" │ └── block: │ @ BlockArgumentNode (location: (6,9)-(6,15)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (6,10)-(6,15)) │ │ ├── flags: variable_call, ignore_visibility @@ -111,6 +121,7 @@ │ │ └── block: ∅ │ └── operator_loc: (6,9)-(6,10) = "&" ├── @ SuperNode (location: (7,0)-(9,2)) + │ ├── flags: newline │ ├── keyword_loc: (7,0)-(7,5) = "super" │ ├── lparen_loc: (7,5)-(7,6) = "(" │ ├── arguments: @@ -128,13 +139,15 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (7,8)-(9,1)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (8,2)-(8,5)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (8,2)-(8,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :foo @@ -148,15 +161,18 @@ │ ├── rparen_loc: (9,1)-(9,2) = ")" │ └── block: ∅ ├── @ ForwardingSuperNode (location: (10,0)-(12,1)) + │ ├── flags: newline │ └── block: │ @ BlockNode (location: (10,6)-(12,1)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (11,2)-(11,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (11,2)-(11,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo @@ -168,6 +184,7 @@ │ ├── opening_loc: (10,6)-(10,7) = "{" │ └── closing_loc: (12,0)-(12,1) = "}" ├── @ SuperNode (location: (13,0)-(15,1)) + │ ├── flags: newline │ ├── keyword_loc: (13,0)-(13,5) = "super" │ ├── lparen_loc: (13,5)-(13,6) = "(" │ ├── arguments: @@ -187,13 +204,15 @@ │ ├── rparen_loc: (13,7)-(13,8) = ")" │ └── block: │ @ BlockNode (location: (13,9)-(15,1)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (14,2)-(14,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (14,2)-(14,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo @@ -205,19 +224,22 @@ │ ├── opening_loc: (13,9)-(13,10) = "{" │ └── closing_loc: (15,0)-(15,1) = "}" ├── @ SuperNode (location: (16,0)-(18,1)) + │ ├── flags: newline │ ├── keyword_loc: (16,0)-(16,5) = "super" │ ├── lparen_loc: (16,5)-(16,6) = "(" │ ├── arguments: ∅ │ ├── rparen_loc: (16,6)-(16,7) = ")" │ └── block: │ @ BlockNode (location: (16,8)-(18,1)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (17,2)-(17,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (17,2)-(17,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo @@ -229,6 +251,7 @@ │ ├── opening_loc: (16,8)-(16,9) = "{" │ └── closing_loc: (18,0)-(18,1) = "}" └── @ SuperNode (location: (19,0)-(21,1)) + ├── flags: newline ├── keyword_loc: (19,0)-(19,5) = "super" ├── lparen_loc: (19,5)-(19,6) = "(" ├── arguments: @@ -258,13 +281,15 @@ ├── rparen_loc: (19,10)-(19,11) = ")" └── block: @ BlockNode (location: (19,12)-(21,1)) + ├── flags: ∅ ├── locals: [] ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (20,2)-(20,5)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (20,2)-(20,5)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo diff --git a/test/prism/snapshots/unparser/corpus/literal/unary.txt b/test/prism/snapshots/unparser/corpus/literal/unary.txt index 5e9563d811d..ec2115e4119 100644 --- a/test/prism/snapshots/unparser/corpus/literal/unary.txt +++ b/test/prism/snapshots/unparser/corpus/literal/unary.txt @@ -1,13 +1,15 @@ -@ ProgramNode (location: (1,0)-(8,9)) +@ ProgramNode (location: (1,0)-(9,9)) +├── flags: ∅ ├── locals: [] └── statements: - @ StatementsNode (location: (1,0)-(8,9)) - └── body: (length: 8) + @ StatementsNode (location: (1,0)-(9,9)) + ├── flags: ∅ + └── body: (length: 9) ├── @ CallNode (location: (1,0)-(1,2)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ IntegerNode (location: (1,1)-(1,2)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :! @@ -17,17 +19,19 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (2,0)-(2,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ParenthesesNode (location: (2,1)-(2,5)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (2,2)-(2,4)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (2,2)-(2,4)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ IntegerNode (location: (2,3)-(2,4)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ └── value: 1 │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :! @@ -46,20 +50,25 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (3,0)-(3,16)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ ParenthesesNode (location: (3,1)-(3,16)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (3,2)-(3,15)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (3,2)-(3,15)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ ParenthesesNode (location: (3,3)-(3,15)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── body: │ │ │ │ │ @ StatementsNode (location: (3,4)-(3,14)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ OrNode (location: (3,4)-(3,14)) + │ │ │ │ │ ├── flags: newline │ │ │ │ │ ├── left: │ │ │ │ │ │ @ CallNode (location: (3,4)-(3,7)) │ │ │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -102,20 +111,22 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (4,0)-(4,9)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (4,1)-(4,9)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ ParenthesesNode (location: (4,1)-(4,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── body: │ │ │ │ @ StatementsNode (location: (4,2)-(4,4)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (4,2)-(4,4)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: newline │ │ │ │ ├── receiver: │ │ │ │ │ @ IntegerNode (location: (4,3)-(4,4)) - │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ ├── flags: static_literal, decimal │ │ │ │ │ └── value: 1 │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :! @@ -141,7 +152,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (5,0)-(5,2)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (5,1)-(5,2)) │ │ ├── flags: variable_call, ignore_visibility @@ -161,7 +172,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (6,0)-(6,2)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (6,1)-(6,2)) │ │ ├── flags: variable_call, ignore_visibility @@ -181,7 +192,7 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (7,0)-(7,2)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── receiver: │ │ @ CallNode (location: (7,1)-(7,2)) │ │ ├── flags: variable_call, ignore_visibility @@ -200,48 +211,98 @@ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - └── @ CallNode (location: (8,0)-(8,9)) - ├── flags: ∅ + ├── @ CallNode (location: (8,0)-(8,9)) + │ ├── flags: newline + │ ├── receiver: + │ │ @ CallNode (location: (8,1)-(8,9)) + │ │ ├── flags: ∅ + │ │ ├── receiver: + │ │ │ @ ParenthesesNode (location: (8,1)-(8,5)) + │ │ │ ├── flags: ∅ + │ │ │ ├── body: + │ │ │ │ @ StatementsNode (location: (8,2)-(8,4)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── body: (length: 1) + │ │ │ │ └── @ CallNode (location: (8,2)-(8,4)) + │ │ │ │ ├── flags: newline + │ │ │ │ ├── receiver: + │ │ │ │ │ @ CallNode (location: (8,3)-(8,4)) + │ │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ │ ├── receiver: ∅ + │ │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ │ ├── name: :a + │ │ │ │ │ ├── message_loc: (8,3)-(8,4) = "a" + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── arguments: ∅ + │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ └── block: ∅ + │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ ├── name: :-@ + │ │ │ │ ├── message_loc: (8,2)-(8,3) = "-" + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── arguments: ∅ + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── block: ∅ + │ │ │ ├── opening_loc: (8,1)-(8,2) = "(" + │ │ │ └── closing_loc: (8,4)-(8,5) = ")" + │ │ ├── call_operator_loc: (8,5)-(8,6) = "." + │ │ ├── name: :foo + │ │ ├── message_loc: (8,6)-(8,9) = "foo" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :-@ + │ ├── message_loc: (8,0)-(8,1) = "-" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ └── block: ∅ + └── @ CallNode (location: (9,0)-(9,9)) + ├── flags: newline ├── receiver: - │ @ CallNode (location: (8,1)-(8,9)) + │ @ CallNode (location: (9,1)-(9,9)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ ParenthesesNode (location: (8,1)-(8,5)) + │ │ @ ParenthesesNode (location: (9,1)-(9,5)) + │ │ ├── flags: ∅ │ │ ├── body: - │ │ │ @ StatementsNode (location: (8,2)-(8,4)) + │ │ │ @ StatementsNode (location: (9,2)-(9,4)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) - │ │ │ └── @ CallNode (location: (8,2)-(8,4)) - │ │ │ ├── flags: ∅ + │ │ │ └── @ CallNode (location: (9,2)-(9,4)) + │ │ │ ├── flags: newline │ │ │ ├── receiver: - │ │ │ │ @ CallNode (location: (8,3)-(8,4)) + │ │ │ │ @ CallNode (location: (9,3)-(9,4)) │ │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :a - │ │ │ │ ├── message_loc: (8,3)-(8,4) = "a" + │ │ │ │ ├── message_loc: (9,3)-(9,4) = "a" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ ├── call_operator_loc: ∅ - │ │ │ ├── name: :-@ - │ │ │ ├── message_loc: (8,2)-(8,3) = "-" + │ │ │ ├── name: :+@ + │ │ │ ├── message_loc: (9,2)-(9,3) = "+" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ ├── opening_loc: (8,1)-(8,2) = "(" - │ │ └── closing_loc: (8,4)-(8,5) = ")" - │ ├── call_operator_loc: (8,5)-(8,6) = "." + │ │ ├── opening_loc: (9,1)-(9,2) = "(" + │ │ └── closing_loc: (9,4)-(9,5) = ")" + │ ├── call_operator_loc: (9,5)-(9,6) = "." │ ├── name: :foo - │ ├── message_loc: (8,6)-(8,9) = "foo" + │ ├── message_loc: (9,6)-(9,9) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ ├── call_operator_loc: ∅ - ├── name: :-@ - ├── message_loc: (8,0)-(8,1) = "-" + ├── name: :+@ + ├── message_loc: (9,0)-(9,1) = "+" ├── opening_loc: ∅ ├── arguments: ∅ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/undef.txt b/test/prism/snapshots/unparser/corpus/literal/undef.txt index 282cbe8f872..b7ccf68e27e 100644 --- a/test/prism/snapshots/unparser/corpus/literal/undef.txt +++ b/test/prism/snapshots/unparser/corpus/literal/undef.txt @@ -1,27 +1,31 @@ @ ProgramNode (location: (1,0)-(2,16)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(2,16)) + ├── flags: ∅ └── body: (length: 2) ├── @ UndefNode (location: (1,0)-(1,10)) + │ ├── flags: newline │ ├── names: (length: 1) │ │ └── @ SymbolNode (location: (1,6)-(1,10)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (1,6)-(1,7) = ":" │ │ ├── value_loc: (1,7)-(1,10) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ └── keyword_loc: (1,0)-(1,5) = "undef" └── @ UndefNode (location: (2,0)-(2,16)) + ├── flags: newline ├── names: (length: 2) │ ├── @ SymbolNode (location: (2,6)-(2,10)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (2,6)-(2,7) = ":" │ │ ├── value_loc: (2,7)-(2,10) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ └── @ SymbolNode (location: (2,12)-(2,16)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: static_literal, forced_us_ascii_encoding │ ├── opening_loc: (2,12)-(2,13) = ":" │ ├── value_loc: (2,13)-(2,16) = "bar" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/variables.txt b/test/prism/snapshots/unparser/corpus/literal/variables.txt index 9ae8ad12071..3861af1a462 100644 --- a/test/prism/snapshots/unparser/corpus/literal/variables.txt +++ b/test/prism/snapshots/unparser/corpus/literal/variables.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(10,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(10,17)) + ├── flags: ∅ └── body: (length: 10) ├── @ CallNode (location: (1,0)-(1,1)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a @@ -14,32 +16,43 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ InstanceVariableReadNode (location: (2,0)-(2,2)) + │ ├── flags: newline │ └── name: :@a ├── @ ClassVariableReadNode (location: (3,0)-(3,3)) + │ ├── flags: newline │ └── name: :@@a ├── @ GlobalVariableReadNode (location: (4,0)-(4,2)) + │ ├── flags: newline │ └── name: :$a ├── @ NumberedReferenceReadNode (location: (5,0)-(5,2)) + │ ├── flags: newline │ └── number: 1 ├── @ BackReferenceReadNode (location: (6,0)-(6,2)) + │ ├── flags: newline │ └── name: :$` ├── @ ConstantReadNode (location: (7,0)-(7,5)) + │ ├── flags: newline │ └── name: :CONST ├── @ ConstantPathNode (location: (8,0)-(8,13)) + │ ├── flags: newline │ ├── parent: │ │ @ ConstantReadNode (location: (8,0)-(8,6)) + │ │ ├── flags: ∅ │ │ └── name: :SCOPED │ ├── name: :CONST │ ├── delimiter_loc: (8,6)-(8,8) = "::" │ └── name_loc: (8,8)-(8,13) = "CONST" ├── @ ConstantPathNode (location: (9,0)-(9,10)) + │ ├── flags: newline │ ├── parent: ∅ │ ├── name: :TOPLEVEL │ ├── delimiter_loc: (9,0)-(9,2) = "::" │ └── name_loc: (9,2)-(9,10) = "TOPLEVEL" └── @ ConstantPathNode (location: (10,0)-(10,17)) + ├── flags: newline ├── parent: │ @ ConstantPathNode (location: (10,0)-(10,10)) + │ ├── flags: ∅ │ ├── parent: ∅ │ ├── name: :TOPLEVEL │ ├── delimiter_loc: (10,0)-(10,2) = "::" diff --git a/test/prism/snapshots/unparser/corpus/literal/while.txt b/test/prism/snapshots/unparser/corpus/literal/while.txt index 0f752f3392d..7d9a24ec624 100644 --- a/test/prism/snapshots/unparser/corpus/literal/while.txt +++ b/test/prism/snapshots/unparser/corpus/literal/while.txt @@ -1,19 +1,24 @@ @ ProgramNode (location: (1,0)-(73,3)) +├── flags: ∅ ├── locals: [:x] └── statements: @ StatementsNode (location: (1,0)-(73,3)) + ├── flags: ∅ └── body: (length: 17) ├── @ ModuleNode (location: (1,0)-(7,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── module_keyword_loc: (1,0)-(1,6) = "module" │ ├── constant_path: │ │ @ ConstantReadNode (location: (1,7)-(1,8)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── body: │ │ @ StatementsNode (location: (2,2)-(6,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (2,2)-(6,3)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo @@ -23,11 +28,14 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (2,6)-(6,3)) + │ │ ├── flags: ∅ │ │ ├── locals: [:bar, :foo] │ │ ├── parameters: │ │ │ @ BlockParametersNode (location: (2,8)-(2,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── parameters: │ │ │ │ @ ParametersNode (location: (2,9)-(2,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ └── @ RequiredParameterNode (location: (2,9)-(2,12)) │ │ │ │ │ ├── flags: ∅ @@ -43,9 +51,10 @@ │ │ │ └── closing_loc: (2,12)-(2,13) = "|" │ │ ├── body: │ │ │ @ StatementsNode (location: (3,4)-(5,7)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ WhileNode (location: (3,4)-(5,7)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── keyword_loc: (3,4)-(3,9) = "while" │ │ │ ├── closing_loc: (5,4)-(5,7) = "end" │ │ │ ├── predicate: @@ -61,13 +70,16 @@ │ │ │ │ └── block: ∅ │ │ │ └── statements: │ │ │ @ StatementsNode (location: (4,6)-(4,15)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ LocalVariableWriteNode (location: (4,6)-(4,15)) + │ │ │ ├── flags: newline │ │ │ ├── name: :foo │ │ │ ├── depth: 0 │ │ │ ├── name_loc: (4,6)-(4,9) = "foo" │ │ │ ├── value: │ │ │ │ @ LocalVariableReadNode (location: (4,12)-(4,15)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :bar │ │ │ │ └── depth: 0 │ │ │ └── operator_loc: (4,10)-(4,11) = "=" @@ -76,15 +88,17 @@ │ ├── end_keyword_loc: (7,0)-(7,3) = "end" │ └── name: :A ├── @ DefNode (location: (9,0)-(11,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (9,4)-(9,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (10,2)-(10,28)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ WhileNode (location: (10,2)-(10,28)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── keyword_loc: (10,12)-(10,17) = "while" │ │ ├── closing_loc: ∅ │ │ ├── predicate: @@ -92,6 +106,7 @@ │ │ │ ├── flags: ∅ │ │ │ ├── receiver: │ │ │ │ @ LocalVariableReadNode (location: (10,18)-(10,21)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :foo │ │ │ │ └── depth: 0 │ │ │ ├── call_operator_loc: ∅ @@ -116,8 +131,10 @@ │ │ │ └── block: ∅ │ │ └── statements: │ │ @ StatementsNode (location: (10,2)-(10,11)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableWriteNode (location: (10,2)-(10,11)) + │ │ ├── flags: newline │ │ ├── name: :foo │ │ ├── depth: 0 │ │ ├── name_loc: (10,2)-(10,5) = "foo" @@ -141,26 +158,32 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (11,0)-(11,3) = "end" ├── @ ModuleNode (location: (13,0)-(15,3)) + │ ├── flags: newline │ ├── locals: [:foo] │ ├── module_keyword_loc: (13,0)-(13,6) = "module" │ ├── constant_path: │ │ @ ConstantReadNode (location: (13,7)-(13,8)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── body: │ │ @ StatementsNode (location: (14,2)-(14,21)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ WhileNode (location: (14,2)-(14,21)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── keyword_loc: (14,12)-(14,17) = "while" │ │ ├── closing_loc: ∅ │ │ ├── predicate: │ │ │ @ LocalVariableReadNode (location: (14,18)-(14,21)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :foo │ │ │ └── depth: 0 │ │ └── statements: │ │ @ StatementsNode (location: (14,2)-(14,11)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableWriteNode (location: (14,2)-(14,11)) + │ │ ├── flags: newline │ │ ├── name: :foo │ │ ├── depth: 0 │ │ ├── name_loc: (14,2)-(14,5) = "foo" @@ -179,26 +202,32 @@ │ ├── end_keyword_loc: (15,0)-(15,3) = "end" │ └── name: :A ├── @ ModuleNode (location: (17,0)-(19,3)) + │ ├── flags: newline │ ├── locals: [:foo] │ ├── module_keyword_loc: (17,0)-(17,6) = "module" │ ├── constant_path: │ │ @ ConstantReadNode (location: (17,7)-(17,8)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── body: │ │ @ StatementsNode (location: (18,2)-(18,21)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ UntilNode (location: (18,2)-(18,21)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── keyword_loc: (18,12)-(18,17) = "until" │ │ ├── closing_loc: ∅ │ │ ├── predicate: │ │ │ @ LocalVariableReadNode (location: (18,18)-(18,21)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :foo │ │ │ └── depth: 0 │ │ └── statements: │ │ @ StatementsNode (location: (18,2)-(18,11)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableWriteNode (location: (18,2)-(18,11)) + │ │ ├── flags: newline │ │ ├── name: :foo │ │ ├── depth: 0 │ │ ├── name_loc: (18,2)-(18,5) = "foo" @@ -217,16 +246,19 @@ │ ├── end_keyword_loc: (19,0)-(19,3) = "end" │ └── name: :A ├── @ ModuleNode (location: (21,0)-(25,3)) + │ ├── flags: newline │ ├── locals: [:foo] │ ├── module_keyword_loc: (21,0)-(21,6) = "module" │ ├── constant_path: │ │ @ ConstantReadNode (location: (21,7)-(21,8)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── body: │ │ @ StatementsNode (location: (22,2)-(24,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ WhileNode (location: (22,2)-(24,5)) - │ │ ├── flags: ∅ + │ │ ├── flags: newline │ │ ├── keyword_loc: (22,2)-(22,7) = "while" │ │ ├── closing_loc: (24,2)-(24,5) = "end" │ │ ├── predicate: @@ -242,8 +274,10 @@ │ │ │ └── block: ∅ │ │ └── statements: │ │ @ StatementsNode (location: (23,4)-(23,13)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableWriteNode (location: (23,4)-(23,13)) + │ │ ├── flags: newline │ │ ├── name: :foo │ │ ├── depth: 0 │ │ ├── name_loc: (23,4)-(23,7) = "foo" @@ -262,16 +296,19 @@ │ ├── end_keyword_loc: (25,0)-(25,3) = "end" │ └── name: :A ├── @ ModuleNode (location: (27,0)-(33,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── module_keyword_loc: (27,0)-(27,6) = "module" │ ├── constant_path: │ │ @ ConstantReadNode (location: (27,7)-(27,8)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── body: │ │ @ StatementsNode (location: (28,2)-(32,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (28,2)-(32,3)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :each @@ -281,11 +318,14 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (28,7)-(32,3)) + │ │ ├── flags: ∅ │ │ ├── locals: [:baz, :foo] │ │ ├── parameters: │ │ │ @ BlockParametersNode (location: (28,9)-(28,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── parameters: │ │ │ │ @ ParametersNode (location: (28,10)-(28,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ └── @ RequiredParameterNode (location: (28,10)-(28,13)) │ │ │ │ │ ├── flags: ∅ @@ -301,9 +341,10 @@ │ │ │ └── closing_loc: (28,13)-(28,14) = "|" │ │ ├── body: │ │ │ @ StatementsNode (location: (29,4)-(31,7)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ WhileNode (location: (29,4)-(31,7)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── keyword_loc: (29,4)-(29,9) = "while" │ │ │ ├── closing_loc: (31,4)-(31,7) = "end" │ │ │ ├── predicate: @@ -319,8 +360,10 @@ │ │ │ │ └── block: ∅ │ │ │ └── statements: │ │ │ @ StatementsNode (location: (30,6)-(30,15)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ LocalVariableWriteNode (location: (30,6)-(30,15)) + │ │ │ ├── flags: newline │ │ │ ├── name: :foo │ │ │ ├── depth: 0 │ │ │ ├── name_loc: (30,6)-(30,9) = "foo" @@ -341,16 +384,19 @@ │ ├── end_keyword_loc: (33,0)-(33,3) = "end" │ └── name: :A ├── @ ModuleNode (location: (35,0)-(41,3)) + │ ├── flags: newline │ ├── locals: [] │ ├── module_keyword_loc: (35,0)-(35,6) = "module" │ ├── constant_path: │ │ @ ConstantReadNode (location: (35,7)-(35,8)) + │ │ ├── flags: ∅ │ │ └── name: :A │ ├── body: │ │ @ StatementsNode (location: (36,2)-(40,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (36,2)-(40,3)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :each @@ -360,11 +406,14 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (36,7)-(40,3)) + │ │ ├── flags: ∅ │ │ ├── locals: [:foo] │ │ ├── parameters: │ │ │ @ BlockParametersNode (location: (36,9)-(36,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── parameters: │ │ │ │ @ ParametersNode (location: (36,10)-(36,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ └── @ RequiredParameterNode (location: (36,10)-(36,13)) │ │ │ │ │ ├── flags: ∅ @@ -380,19 +429,23 @@ │ │ │ └── closing_loc: (36,13)-(36,14) = "|" │ │ ├── body: │ │ │ @ StatementsNode (location: (37,4)-(39,7)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ WhileNode (location: (37,4)-(39,7)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── keyword_loc: (37,4)-(37,9) = "while" │ │ │ ├── closing_loc: (39,4)-(39,7) = "end" │ │ │ ├── predicate: │ │ │ │ @ LocalVariableReadNode (location: (37,10)-(37,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :foo │ │ │ │ └── depth: 0 │ │ │ └── statements: │ │ │ @ StatementsNode (location: (38,6)-(38,15)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ LocalVariableWriteNode (location: (38,6)-(38,15)) + │ │ │ ├── flags: newline │ │ │ ├── name: :foo │ │ │ ├── depth: 0 │ │ │ ├── name_loc: (38,6)-(38,9) = "foo" @@ -413,16 +466,19 @@ │ ├── end_keyword_loc: (41,0)-(41,3) = "end" │ └── name: :A ├── @ LocalVariableWriteNode (location: (42,0)-(44,14)) + │ ├── flags: newline │ ├── name: :x │ ├── depth: 0 │ ├── name_loc: (42,0)-(42,1) = "x" │ ├── value: │ │ @ ParenthesesNode (location: (42,4)-(44,14)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (42,5)-(44,13)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ WhileNode (location: (42,5)-(44,13)) - │ │ │ ├── flags: begin_modifier + │ │ │ ├── flags: newline, begin_modifier │ │ │ ├── keyword_loc: (44,4)-(44,9) = "while" │ │ │ ├── closing_loc: ∅ │ │ │ ├── predicate: @@ -438,14 +494,17 @@ │ │ │ │ └── block: ∅ │ │ │ └── statements: │ │ │ @ StatementsNode (location: (42,5)-(44,3)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ BeginNode (location: (42,5)-(44,3)) + │ │ │ ├── flags: newline │ │ │ ├── begin_keyword_loc: (42,5)-(42,10) = "begin" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (43,2)-(43,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ CallNode (location: (43,2)-(43,5)) - │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :foo @@ -462,7 +521,7 @@ │ │ └── closing_loc: (44,13)-(44,14) = ")" │ └── operator_loc: (42,2)-(42,3) = "=" ├── @ WhileNode (location: (45,0)-(47,13)) - │ ├── flags: begin_modifier + │ ├── flags: newline, begin_modifier │ ├── keyword_loc: (47,4)-(47,9) = "while" │ ├── closing_loc: ∅ │ ├── predicate: @@ -478,14 +537,17 @@ │ │ └── block: ∅ │ └── statements: │ @ StatementsNode (location: (45,0)-(47,3)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ BeginNode (location: (45,0)-(47,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (45,0)-(45,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (46,2)-(46,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (46,2)-(46,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo @@ -499,7 +561,7 @@ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (47,0)-(47,3) = "end" ├── @ UntilNode (location: (48,0)-(51,13)) - │ ├── flags: begin_modifier + │ ├── flags: newline, begin_modifier │ ├── keyword_loc: (51,4)-(51,9) = "until" │ ├── closing_loc: ∅ │ ├── predicate: @@ -515,14 +577,17 @@ │ │ └── block: ∅ │ └── statements: │ @ StatementsNode (location: (48,0)-(51,3)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ BeginNode (location: (48,0)-(51,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (48,0)-(48,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (49,2)-(50,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 2) │ │ ├── @ CallNode (location: (49,2)-(49,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :foo @@ -532,7 +597,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ CallNode (location: (50,2)-(50,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -546,7 +611,7 @@ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (51,0)-(51,3) = "end" ├── @ WhileNode (location: (52,0)-(55,13)) - │ ├── flags: begin_modifier + │ ├── flags: newline, begin_modifier │ ├── keyword_loc: (55,4)-(55,9) = "while" │ ├── closing_loc: ∅ │ ├── predicate: @@ -562,14 +627,17 @@ │ │ └── block: ∅ │ └── statements: │ @ StatementsNode (location: (52,0)-(55,3)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ BeginNode (location: (52,0)-(55,3)) + │ ├── flags: newline │ ├── begin_keyword_loc: (52,0)-(52,5) = "begin" │ ├── statements: │ │ @ StatementsNode (location: (53,2)-(54,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 2) │ │ ├── @ CallNode (location: (53,2)-(53,5)) - │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── flags: newline, variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :foo @@ -579,7 +647,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ CallNode (location: (54,2)-(54,5)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -593,35 +661,40 @@ │ ├── ensure_clause: ∅ │ └── end_keyword_loc: (55,0)-(55,3) = "end" ├── @ WhileNode (location: (56,0)-(57,3)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (56,0)-(56,5) = "while" │ ├── closing_loc: (57,0)-(57,3) = "end" │ ├── predicate: │ │ @ FalseNode (location: (56,6)-(56,11)) + │ │ └── flags: static_literal │ └── statements: ∅ ├── @ WhileNode (location: (58,0)-(60,3)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (58,0)-(58,5) = "while" │ ├── closing_loc: (60,0)-(60,3) = "end" │ ├── predicate: │ │ @ FalseNode (location: (58,6)-(58,11)) + │ │ └── flags: static_literal │ └── statements: │ @ StatementsNode (location: (59,2)-(59,3)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ IntegerNode (location: (59,2)-(59,3)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 3 ├── @ WhileNode (location: (61,0)-(64,3)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (61,0)-(61,5) = "while" │ ├── closing_loc: (64,0)-(64,3) = "end" │ ├── predicate: │ │ @ ParenthesesNode (location: (61,6)-(62,2)) + │ │ ├── flags: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (61,7)-(62,1)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (61,7)-(62,1)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :foo @@ -631,6 +704,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: │ │ │ @ BlockNode (location: (61,11)-(62,1)) + │ │ │ ├── flags: ∅ │ │ │ ├── locals: [] │ │ │ ├── parameters: ∅ │ │ │ ├── body: ∅ @@ -640,43 +714,49 @@ │ │ └── closing_loc: (62,1)-(62,2) = ")" │ └── statements: │ @ StatementsNode (location: (63,2)-(63,7)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ SymbolNode (location: (63,2)-(63,7)) - │ ├── flags: forced_us_ascii_encoding + │ ├── flags: newline, static_literal, forced_us_ascii_encoding │ ├── opening_loc: (63,2)-(63,3) = ":" │ ├── value_loc: (63,3)-(63,7) = "body" │ ├── closing_loc: ∅ │ └── unescaped: "body" ├── @ UntilNode (location: (65,0)-(66,3)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (65,0)-(65,5) = "until" │ ├── closing_loc: (66,0)-(66,3) = "end" │ ├── predicate: │ │ @ FalseNode (location: (65,6)-(65,11)) + │ │ └── flags: static_literal │ └── statements: ∅ ├── @ UntilNode (location: (67,0)-(69,3)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── keyword_loc: (67,0)-(67,5) = "until" │ ├── closing_loc: (69,0)-(69,3) = "end" │ ├── predicate: │ │ @ FalseNode (location: (67,6)-(67,11)) + │ │ └── flags: static_literal │ └── statements: │ @ StatementsNode (location: (68,2)-(68,3)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ IntegerNode (location: (68,2)-(68,3)) - │ ├── flags: decimal + │ ├── flags: newline, static_literal, decimal │ └── value: 3 └── @ UntilNode (location: (70,0)-(73,3)) - ├── flags: ∅ + ├── flags: newline ├── keyword_loc: (70,0)-(70,5) = "until" ├── closing_loc: (73,0)-(73,3) = "end" ├── predicate: │ @ ParenthesesNode (location: (70,6)-(71,2)) + │ ├── flags: ∅ │ ├── body: │ │ @ StatementsNode (location: (70,7)-(71,1)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (70,7)-(71,1)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo @@ -686,6 +766,7 @@ │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (70,11)-(71,1)) + │ │ ├── flags: ∅ │ │ ├── locals: [] │ │ ├── parameters: ∅ │ │ ├── body: ∅ @@ -695,9 +776,10 @@ │ └── closing_loc: (71,1)-(71,2) = ")" └── statements: @ StatementsNode (location: (72,2)-(72,7)) + ├── flags: ∅ └── body: (length: 1) └── @ SymbolNode (location: (72,2)-(72,7)) - ├── flags: forced_us_ascii_encoding + ├── flags: newline, static_literal, forced_us_ascii_encoding ├── opening_loc: (72,2)-(72,3) = ":" ├── value_loc: (72,3)-(72,7) = "body" ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/yield.txt b/test/prism/snapshots/unparser/corpus/literal/yield.txt deleted file mode 100644 index 4d2b272e35e..00000000000 --- a/test/prism/snapshots/unparser/corpus/literal/yield.txt +++ /dev/null @@ -1,56 +0,0 @@ -@ ProgramNode (location: (1,0)-(3,11)) -├── locals: [] -└── statements: - @ StatementsNode (location: (1,0)-(3,11)) - └── body: (length: 3) - ├── @ YieldNode (location: (1,0)-(1,5)) - │ ├── keyword_loc: (1,0)-(1,5) = "yield" - │ ├── lparen_loc: ∅ - │ ├── arguments: ∅ - │ └── rparen_loc: ∅ - ├── @ YieldNode (location: (2,0)-(2,8)) - │ ├── keyword_loc: (2,0)-(2,5) = "yield" - │ ├── lparen_loc: (2,5)-(2,6) = "(" - │ ├── arguments: - │ │ @ ArgumentsNode (location: (2,6)-(2,7)) - │ │ ├── flags: ∅ - │ │ └── arguments: (length: 1) - │ │ └── @ CallNode (location: (2,6)-(2,7)) - │ │ ├── flags: variable_call, ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :a - │ │ ├── message_loc: (2,6)-(2,7) = "a" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: ∅ - │ │ ├── closing_loc: ∅ - │ │ └── block: ∅ - │ └── rparen_loc: (2,7)-(2,8) = ")" - └── @ YieldNode (location: (3,0)-(3,11)) - ├── keyword_loc: (3,0)-(3,5) = "yield" - ├── lparen_loc: (3,5)-(3,6) = "(" - ├── arguments: - │ @ ArgumentsNode (location: (3,6)-(3,10)) - │ ├── flags: ∅ - │ └── arguments: (length: 2) - │ ├── @ CallNode (location: (3,6)-(3,7)) - │ │ ├── flags: variable_call, ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :a - │ │ ├── message_loc: (3,6)-(3,7) = "a" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: ∅ - │ │ ├── closing_loc: ∅ - │ │ └── block: ∅ - │ └── @ CallNode (location: (3,9)-(3,10)) - │ ├── flags: variable_call, ignore_visibility - │ ├── receiver: ∅ - │ ├── call_operator_loc: ∅ - │ ├── name: :b - │ ├── message_loc: (3,9)-(3,10) = "b" - │ ├── opening_loc: ∅ - │ ├── arguments: ∅ - │ ├── closing_loc: ∅ - │ └── block: ∅ - └── rparen_loc: (3,10)-(3,11) = ")" diff --git a/test/prism/snapshots/unparser/corpus/semantic/and.txt b/test/prism/snapshots/unparser/corpus/semantic/and.txt index bc9d674e44e..ad2b6397773 100644 --- a/test/prism/snapshots/unparser/corpus/semantic/and.txt +++ b/test/prism/snapshots/unparser/corpus/semantic/and.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(8,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(8,3)) + ├── flags: ∅ └── body: (length: 4) ├── @ OrNode (location: (1,0)-(1,14)) + │ ├── flags: newline │ ├── left: │ │ @ RangeNode (location: (1,0)-(1,5)) │ │ ├── flags: exclude_end @@ -58,6 +61,7 @@ │ │ └── operator_loc: (1,10)-(1,13) = "..." │ └── operator_loc: (1,6)-(1,8) = "or" ├── @ AndNode (location: (2,0)-(2,15)) + │ ├── flags: newline │ ├── left: │ │ @ RangeNode (location: (2,0)-(2,5)) │ │ ├── flags: exclude_end @@ -112,9 +116,11 @@ │ │ └── operator_loc: (2,11)-(2,14) = "..." │ └── operator_loc: (2,6)-(2,9) = "and" ├── @ IfNode (location: (4,0)-(5,3)) + │ ├── flags: newline │ ├── if_keyword_loc: (4,0)-(4,2) = "if" │ ├── predicate: │ │ @ OrNode (location: (4,3)-(4,17)) + │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ FlipFlopNode (location: (4,3)-(4,8)) │ │ │ ├── flags: exclude_end @@ -170,12 +176,14 @@ │ │ └── operator_loc: (4,9)-(4,11) = "or" │ ├── then_keyword_loc: ∅ │ ├── statements: ∅ - │ ├── consequent: ∅ + │ ├── subsequent: ∅ │ └── end_keyword_loc: (5,0)-(5,3) = "end" └── @ IfNode (location: (7,0)-(8,3)) + ├── flags: newline ├── if_keyword_loc: (7,0)-(7,2) = "if" ├── predicate: │ @ AndNode (location: (7,3)-(7,18)) + │ ├── flags: ∅ │ ├── left: │ │ @ FlipFlopNode (location: (7,3)-(7,8)) │ │ ├── flags: exclude_end @@ -231,5 +239,5 @@ │ └── operator_loc: (7,9)-(7,12) = "and" ├── then_keyword_loc: ∅ ├── statements: ∅ - ├── consequent: ∅ + ├── subsequent: ∅ └── end_keyword_loc: (8,0)-(8,3) = "end" diff --git a/test/prism/snapshots/unparser/corpus/semantic/block.txt b/test/prism/snapshots/unparser/corpus/semantic/block.txt index b9aa6b21844..ea87b101ec0 100644 --- a/test/prism/snapshots/unparser/corpus/semantic/block.txt +++ b/test/prism/snapshots/unparser/corpus/semantic/block.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(26,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(26,3)) + ├── flags: ∅ └── body: (length: 6) ├── @ CallNode (location: (1,0)-(2,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -14,13 +16,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (1,4)-(2,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: ∅ │ ├── opening_loc: (1,4)-(1,6) = "do" │ └── closing_loc: (2,0)-(2,3) = "end" ├── @ CallNode (location: (4,0)-(6,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -30,27 +33,30 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (4,4)-(6,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ BeginNode (location: (4,4)-(6,3)) + │ │ ├── flags: ∅ │ │ ├── begin_keyword_loc: ∅ │ │ ├── statements: ∅ │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (5,0)-(5,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── keyword_loc: (5,0)-(5,6) = "rescue" │ │ │ ├── exceptions: (length: 0) │ │ │ ├── operator_loc: ∅ │ │ │ ├── reference: ∅ │ │ │ ├── statements: ∅ - │ │ │ └── consequent: ∅ + │ │ │ └── subsequent: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ │ │ └── end_keyword_loc: (6,0)-(6,3) = "end" │ ├── opening_loc: (4,4)-(4,6) = "do" │ └── closing_loc: (6,0)-(6,3) = "end" ├── @ CallNode (location: (8,0)-(11,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -60,22 +66,28 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (8,4)-(11,3)) + │ ├── flags: ∅ │ ├── locals: [] │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (9,2)-(10,5)) + │ │ ├── flags: ∅ │ │ └── body: (length: 2) │ │ ├── @ RescueModifierNode (location: (9,2)-(9,16)) + │ │ │ ├── flags: newline │ │ │ ├── expression: │ │ │ │ @ NilNode (location: (9,2)-(9,5)) + │ │ │ │ └── flags: static_literal │ │ │ ├── keyword_loc: (9,6)-(9,12) = "rescue" │ │ │ └── rescue_expression: │ │ │ @ NilNode (location: (9,13)-(9,16)) + │ │ │ └── flags: static_literal │ │ └── @ NilNode (location: (10,2)-(10,5)) + │ │ └── flags: newline, static_literal │ ├── opening_loc: (8,4)-(8,6) = "do" │ └── closing_loc: (11,0)-(11,3) = "end" ├── @ CallNode (location: (13,0)-(14,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -85,11 +97,14 @@ │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (13,4)-(14,3)) + │ ├── flags: ∅ │ ├── locals: [:a] │ ├── parameters: │ │ @ BlockParametersNode (location: (13,7)-(13,10)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (13,8)-(13,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (13,8)-(13,9)) │ │ │ │ ├── flags: ∅ @@ -107,7 +122,7 @@ │ ├── opening_loc: (13,4)-(13,6) = "do" │ └── closing_loc: (14,0)-(14,3) = "end" ├── @ CallNode (location: (16,0)-(20,3)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo @@ -126,11 +141,14 @@ │ ├── closing_loc: (16,10)-(16,11) = ")" │ └── block: │ @ BlockNode (location: (16,12)-(20,3)) + │ ├── flags: ∅ │ ├── locals: [:a] │ ├── parameters: │ │ @ BlockParametersNode (location: (16,15)-(16,18)) + │ │ ├── flags: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (16,16)-(16,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (16,16)-(16,17)) │ │ │ │ ├── flags: ∅ @@ -146,14 +164,16 @@ │ │ └── closing_loc: (16,17)-(16,18) = "|" │ ├── body: │ │ @ StatementsNode (location: (19,2)-(19,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (19,2)-(19,3)) + │ │ ├── flags: newline │ │ ├── name: :a │ │ └── depth: 0 │ ├── opening_loc: (16,12)-(16,14) = "do" │ └── closing_loc: (20,0)-(20,3) = "end" └── @ CallNode (location: (22,0)-(26,3)) - ├── flags: ignore_visibility + ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :foo @@ -172,13 +192,15 @@ ├── closing_loc: (22,10)-(22,11) = ")" └── block: @ BlockNode (location: (22,12)-(26,3)) + ├── flags: ∅ ├── locals: [] ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (25,2)-(25,3)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (25,2)-(25,3)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a diff --git a/test/prism/snapshots/unparser/corpus/semantic/def.txt b/test/prism/snapshots/unparser/corpus/semantic/def.txt index b44983c2f37..f05ce02bca7 100644 --- a/test/prism/snapshots/unparser/corpus/semantic/def.txt +++ b/test/prism/snapshots/unparser/corpus/semantic/def.txt @@ -1,22 +1,28 @@ @ ProgramNode (location: (1,0)-(7,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(7,3)) + ├── flags: ∅ └── body: (length: 2) ├── @ DefNode (location: (1,0)-(3,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (1,4)-(1,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (2,2)-(2,9)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ ParenthesesNode (location: (2,2)-(2,9)) + │ │ ├── flags: newline │ │ ├── body: │ │ │ @ StatementsNode (location: (2,3)-(2,8)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (2,3)-(2,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── receiver: │ │ │ │ @ CallNode (location: (2,3)-(2,4)) │ │ │ │ ├── flags: variable_call, ignore_visibility @@ -58,14 +64,17 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (3,0)-(3,3) = "end" └── @ DefNode (location: (5,0)-(7,3)) + ├── flags: newline ├── name: :foo ├── name_loc: (5,4)-(5,7) = "foo" ├── receiver: ∅ ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (6,2)-(6,20)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ RescueModifierNode (location: (6,2)-(6,20)) + │ ├── flags: newline │ ├── expression: │ │ @ CallNode (location: (6,2)-(6,3)) │ │ ├── flags: variable_call, ignore_visibility @@ -80,6 +89,7 @@ │ ├── keyword_loc: (6,4)-(6,10) = "rescue" │ └── rescue_expression: │ @ ConstantReadNode (location: (6,11)-(6,20)) + │ ├── flags: ∅ │ └── name: :Exception ├── locals: [] ├── def_keyword_loc: (5,0)-(5,3) = "def" diff --git a/test/prism/snapshots/unparser/corpus/semantic/dstr.txt b/test/prism/snapshots/unparser/corpus/semantic/dstr.txt index 499bf59d1ab..b1bfbefc8ba 100644 --- a/test/prism/snapshots/unparser/corpus/semantic/dstr.txt +++ b/test/prism/snapshots/unparser/corpus/semantic/dstr.txt @@ -1,453 +1,484 @@ @ ProgramNode (location: (1,0)-(127,11)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(127,11)) + ├── flags: ∅ └── body: (length: 33) ├── @ StringNode (location: (1,0)-(1,5)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (1,0)-(1,5) = "<= ├── name_loc: (11,4)-(11,6) = ">=" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (11,7)-(11,12)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (11,7)-(11,12)) │ │ ├── flags: ∅ @@ -201,6 +220,7 @@ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (11,16)-(11,28)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (11,16)-(11,28)) │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/whitequark/endless_method.txt b/test/prism/snapshots/whitequark/endless_method.txt index 17d3873b663..3c24ab2a7dc 100644 --- a/test/prism/snapshots/whitequark/endless_method.txt +++ b/test/prism/snapshots/whitequark/endless_method.txt @@ -1,18 +1,22 @@ @ ProgramNode (location: (1,0)-(7,22)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(7,22)) + ├── flags: ∅ └── body: (length: 4) ├── @ DefNode (location: (1,0)-(1,14)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (1,4)-(1,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,12)-(1,14)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,12)-(1,14)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 42 │ ├── locals: [] │ ├── def_keyword_loc: (1,0)-(1,3) = "def" @@ -22,11 +26,13 @@ │ ├── equal_loc: (1,10)-(1,11) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (3,0)-(3,18)) + │ ├── flags: newline │ ├── name: :inc │ ├── name_loc: (3,4)-(3,7) = "inc" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (3,8)-(3,9)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (3,8)-(3,9)) │ │ │ ├── flags: ∅ @@ -39,11 +45,13 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (3,13)-(3,18)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (3,13)-(3,18)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ LocalVariableReadNode (location: (3,13)-(3,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :x │ │ │ └── depth: 0 │ │ ├── call_operator_loc: ∅ @@ -55,7 +63,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (3,17)-(3,18)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ @@ -67,6 +75,7 @@ │ ├── equal_loc: (3,11)-(3,12) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (5,0)-(5,18)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (5,8)-(5,11) = "foo" │ ├── receiver: @@ -83,9 +92,10 @@ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (5,16)-(5,18)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (5,16)-(5,18)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 42 │ ├── locals: [] │ ├── def_keyword_loc: (5,0)-(5,3) = "def" @@ -95,6 +105,7 @@ │ ├── equal_loc: (5,14)-(5,15) = "=" │ └── end_keyword_loc: ∅ └── @ DefNode (location: (7,0)-(7,22)) + ├── flags: newline ├── name: :inc ├── name_loc: (7,8)-(7,11) = "inc" ├── receiver: @@ -110,6 +121,7 @@ │ └── block: ∅ ├── parameters: │ @ ParametersNode (location: (7,12)-(7,13)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (7,12)-(7,13)) │ │ ├── flags: ∅ @@ -122,11 +134,13 @@ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (7,17)-(7,22)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (7,17)-(7,22)) │ ├── flags: ∅ │ ├── receiver: │ │ @ LocalVariableReadNode (location: (7,17)-(7,18)) + │ │ ├── flags: ∅ │ │ ├── name: :x │ │ └── depth: 0 │ ├── call_operator_loc: ∅ @@ -138,7 +152,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (7,21)-(7,22)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ diff --git a/test/prism/snapshots/whitequark/endless_method_command_syntax.txt b/test/prism/snapshots/whitequark/endless_method_command_syntax.txt index 4ec57ccd35f..db2c0cec6fe 100644 --- a/test/prism/snapshots/whitequark/endless_method_command_syntax.txt +++ b/test/prism/snapshots/whitequark/endless_method_command_syntax.txt @@ -1,15 +1,19 @@ @ ProgramNode (location: (1,0)-(15,62)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(15,62)) + ├── flags: ∅ └── body: (length: 8) ├── @ DefNode (location: (1,0)-(1,22)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (1,4)-(1,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,10)-(1,22)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (1,10)-(1,22)) │ │ ├── flags: ignore_visibility @@ -38,12 +42,14 @@ │ ├── equal_loc: (1,8)-(1,9) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (3,0)-(3,24)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (3,4)-(3,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (3,12)-(3,24)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (3,12)-(3,24)) │ │ ├── flags: ignore_visibility @@ -72,11 +78,13 @@ │ ├── equal_loc: (3,10)-(3,11) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (5,0)-(5,19)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (5,4)-(5,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (5,8)-(5,9)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (5,8)-(5,9)) │ │ │ ├── flags: ∅ @@ -89,6 +97,7 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (5,13)-(5,19)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (5,13)-(5,19)) │ │ ├── flags: ignore_visibility @@ -102,6 +111,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ LocalVariableReadNode (location: (5,18)-(5,19)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :x │ │ │ └── depth: 0 │ │ ├── closing_loc: ∅ @@ -114,6 +124,7 @@ │ ├── equal_loc: (5,11)-(5,12) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (7,0)-(7,26)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (7,8)-(7,11) = "foo" │ ├── receiver: @@ -130,6 +141,7 @@ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (7,14)-(7,26)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (7,14)-(7,26)) │ │ ├── flags: ignore_visibility @@ -158,6 +170,7 @@ │ ├── equal_loc: (7,12)-(7,13) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (9,0)-(9,28)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (9,8)-(9,11) = "foo" │ ├── receiver: @@ -174,6 +187,7 @@ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (9,16)-(9,28)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (9,16)-(9,28)) │ │ ├── flags: ignore_visibility @@ -202,6 +216,7 @@ │ ├── equal_loc: (9,14)-(9,15) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (11,0)-(11,23)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (11,8)-(11,11) = "foo" │ ├── receiver: @@ -217,6 +232,7 @@ │ │ └── block: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (11,12)-(11,13)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (11,12)-(11,13)) │ │ │ ├── flags: ∅ @@ -229,6 +245,7 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (11,17)-(11,23)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (11,17)-(11,23)) │ │ ├── flags: ignore_visibility @@ -242,6 +259,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ LocalVariableReadNode (location: (11,22)-(11,23)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :x │ │ │ └── depth: 0 │ │ ├── closing_loc: ∅ @@ -254,11 +272,13 @@ │ ├── equal_loc: (11,15)-(11,16) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (13,0)-(13,60)) + │ ├── flags: newline │ ├── name: :rescued │ ├── name_loc: (13,4)-(13,11) = "rescued" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (13,12)-(13,13)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (13,12)-(13,13)) │ │ │ ├── flags: ∅ @@ -271,8 +291,10 @@ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (13,17)-(13,60)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RescueModifierNode (location: (13,17)-(13,60)) + │ │ ├── flags: ∅ │ │ ├── expression: │ │ │ @ CallNode (location: (13,17)-(13,37)) │ │ │ ├── flags: ignore_visibility @@ -300,17 +322,20 @@ │ │ ├── opening_loc: (13,45)-(13,46) = "\"" │ │ ├── parts: (length: 2) │ │ │ ├── @ StringNode (location: (13,46)-(13,55)) - │ │ │ │ ├── flags: frozen + │ │ │ │ ├── flags: static_literal, frozen │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── content_loc: (13,46)-(13,55) = "instance " │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "instance " │ │ │ └── @ EmbeddedStatementsNode (location: (13,55)-(13,59)) + │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: (13,55)-(13,57) = "\#{" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (13,57)-(13,58)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ LocalVariableReadNode (location: (13,57)-(13,58)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :x │ │ │ │ └── depth: 0 │ │ │ └── closing_loc: (13,58)-(13,59) = "}" @@ -323,12 +348,15 @@ │ ├── equal_loc: (13,15)-(13,16) = "=" │ └── end_keyword_loc: ∅ └── @ DefNode (location: (15,0)-(15,62)) + ├── flags: newline ├── name: :rescued ├── name_loc: (15,9)-(15,16) = "rescued" ├── receiver: │ @ SelfNode (location: (15,4)-(15,8)) + │ └── flags: ∅ ├── parameters: │ @ ParametersNode (location: (15,17)-(15,18)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (15,17)-(15,18)) │ │ ├── flags: ∅ @@ -341,8 +369,10 @@ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (15,22)-(15,62)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ RescueModifierNode (location: (15,22)-(15,62)) + │ ├── flags: ∅ │ ├── expression: │ │ @ CallNode (location: (15,22)-(15,42)) │ │ ├── flags: ignore_visibility @@ -370,17 +400,20 @@ │ ├── opening_loc: (15,50)-(15,51) = "\"" │ ├── parts: (length: 2) │ │ ├── @ StringNode (location: (15,51)-(15,57)) - │ │ │ ├── flags: frozen + │ │ │ ├── flags: static_literal, frozen │ │ │ ├── opening_loc: ∅ │ │ │ ├── content_loc: (15,51)-(15,57) = "class " │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "class " │ │ └── @ EmbeddedStatementsNode (location: (15,57)-(15,61)) + │ │ ├── flags: ∅ │ │ ├── opening_loc: (15,57)-(15,59) = "\#{" │ │ ├── statements: │ │ │ @ StatementsNode (location: (15,59)-(15,60)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ LocalVariableReadNode (location: (15,59)-(15,60)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :x │ │ │ └── depth: 0 │ │ └── closing_loc: (15,60)-(15,61) = "}" diff --git a/test/prism/snapshots/whitequark/endless_method_forwarded_args_legacy.txt b/test/prism/snapshots/whitequark/endless_method_forwarded_args_legacy.txt index 64a3ffa2520..eaa10610077 100644 --- a/test/prism/snapshots/whitequark/endless_method_forwarded_args_legacy.txt +++ b/test/prism/snapshots/whitequark/endless_method_forwarded_args_legacy.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,23)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,23)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,23)) + ├── flags: newline ├── name: :foo ├── name_loc: (1,4)-(1,7) = "foo" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,8)-(1,11)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -16,9 +20,11 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ ForwardingParameterNode (location: (1,8)-(1,11)) + │ │ └── flags: ∅ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (1,15)-(1,23)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,15)-(1,23)) │ ├── flags: ignore_visibility @@ -29,9 +35,10 @@ │ ├── opening_loc: (1,18)-(1,19) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (1,19)-(1,22)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_forwarding │ │ └── arguments: (length: 1) │ │ └── @ ForwardingArgumentsNode (location: (1,19)-(1,22)) + │ │ └── flags: ∅ │ ├── closing_loc: (1,22)-(1,23) = ")" │ └── block: ∅ ├── locals: [] diff --git a/test/prism/snapshots/whitequark/endless_method_with_rescue_mod.txt b/test/prism/snapshots/whitequark/endless_method_with_rescue_mod.txt index 2284b243549..c64ba634b73 100644 --- a/test/prism/snapshots/whitequark/endless_method_with_rescue_mod.txt +++ b/test/prism/snapshots/whitequark/endless_method_with_rescue_mod.txt @@ -1,25 +1,30 @@ @ ProgramNode (location: (1,0)-(3,25)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,25)) + ├── flags: ∅ └── body: (length: 2) ├── @ DefNode (location: (1,0)-(1,20)) + │ ├── flags: newline │ ├── name: :m │ ├── name_loc: (1,4)-(1,5) = "m" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,10)-(1,20)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RescueModifierNode (location: (1,10)-(1,20)) + │ │ ├── flags: ∅ │ │ ├── expression: │ │ │ @ IntegerNode (location: (1,10)-(1,11)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── keyword_loc: (1,12)-(1,18) = "rescue" │ │ └── rescue_expression: │ │ @ IntegerNode (location: (1,19)-(1,20)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ ├── locals: [] │ ├── def_keyword_loc: (1,0)-(1,3) = "def" @@ -29,23 +34,27 @@ │ ├── equal_loc: (1,8)-(1,9) = "=" │ └── end_keyword_loc: ∅ └── @ DefNode (location: (3,0)-(3,25)) + ├── flags: newline ├── name: :m ├── name_loc: (3,9)-(3,10) = "m" ├── receiver: │ @ SelfNode (location: (3,4)-(3,8)) + │ └── flags: ∅ ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (3,15)-(3,25)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ RescueModifierNode (location: (3,15)-(3,25)) + │ ├── flags: ∅ │ ├── expression: │ │ @ IntegerNode (location: (3,15)-(3,16)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 1 │ ├── keyword_loc: (3,17)-(3,23) = "rescue" │ └── rescue_expression: │ @ IntegerNode (location: (3,24)-(3,25)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 2 ├── locals: [] ├── def_keyword_loc: (3,0)-(3,3) = "def" diff --git a/test/prism/snapshots/whitequark/endless_method_without_args.txt b/test/prism/snapshots/whitequark/endless_method_without_args.txt index a7a9c93ef34..0be157df627 100644 --- a/test/prism/snapshots/whitequark/endless_method_without_args.txt +++ b/test/prism/snapshots/whitequark/endless_method_without_args.txt @@ -1,18 +1,22 @@ @ ProgramNode (location: (1,0)-(7,28)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(7,28)) + ├── flags: ∅ └── body: (length: 4) ├── @ DefNode (location: (1,0)-(1,12)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (1,4)-(1,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,10)-(1,12)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,10)-(1,12)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 42 │ ├── locals: [] │ ├── def_keyword_loc: (1,0)-(1,3) = "def" @@ -22,21 +26,25 @@ │ ├── equal_loc: (1,8)-(1,9) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (3,0)-(3,23)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (3,4)-(3,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (3,10)-(3,23)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ RescueModifierNode (location: (3,10)-(3,23)) + │ │ ├── flags: ∅ │ │ ├── expression: │ │ │ @ IntegerNode (location: (3,10)-(3,12)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 42 │ │ ├── keyword_loc: (3,13)-(3,19) = "rescue" │ │ └── rescue_expression: │ │ @ NilNode (location: (3,20)-(3,23)) + │ │ └── flags: static_literal │ ├── locals: [] │ ├── def_keyword_loc: (3,0)-(3,3) = "def" │ ├── operator_loc: ∅ @@ -45,16 +53,19 @@ │ ├── equal_loc: (3,8)-(3,9) = "=" │ └── end_keyword_loc: ∅ ├── @ DefNode (location: (5,0)-(5,17)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (5,9)-(5,12) = "foo" │ ├── receiver: │ │ @ SelfNode (location: (5,4)-(5,8)) + │ │ └── flags: ∅ │ ├── parameters: ∅ │ ├── body: │ │ @ StatementsNode (location: (5,15)-(5,17)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (5,15)-(5,17)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 42 │ ├── locals: [] │ ├── def_keyword_loc: (5,0)-(5,3) = "def" @@ -64,22 +75,27 @@ │ ├── equal_loc: (5,13)-(5,14) = "=" │ └── end_keyword_loc: ∅ └── @ DefNode (location: (7,0)-(7,28)) + ├── flags: newline ├── name: :foo ├── name_loc: (7,9)-(7,12) = "foo" ├── receiver: │ @ SelfNode (location: (7,4)-(7,8)) + │ └── flags: ∅ ├── parameters: ∅ ├── body: │ @ StatementsNode (location: (7,15)-(7,28)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ RescueModifierNode (location: (7,15)-(7,28)) + │ ├── flags: ∅ │ ├── expression: │ │ @ IntegerNode (location: (7,15)-(7,17)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 42 │ ├── keyword_loc: (7,18)-(7,24) = "rescue" │ └── rescue_expression: │ @ NilNode (location: (7,25)-(7,28)) + │ └── flags: static_literal ├── locals: [] ├── def_keyword_loc: (7,0)-(7,3) = "def" ├── operator_loc: (7,8)-(7,9) = "." diff --git a/test/prism/snapshots/whitequark/ensure.txt b/test/prism/snapshots/whitequark/ensure.txt index a48d2370e8d..63d4a3b05dc 100644 --- a/test/prism/snapshots/whitequark/ensure.txt +++ b/test/prism/snapshots/whitequark/ensure.txt @@ -1,15 +1,19 @@ @ ProgramNode (location: (1,0)-(1,29)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,29)) + ├── flags: ∅ └── body: (length: 1) └── @ BeginNode (location: (1,0)-(1,29)) + ├── flags: newline ├── begin_keyword_loc: (1,0)-(1,5) = "begin" ├── statements: │ @ StatementsNode (location: (1,7)-(1,11)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,7)-(1,11)) - │ ├── flags: variable_call, ignore_visibility + │ ├── flags: newline, variable_call, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :meth @@ -22,12 +26,14 @@ ├── else_clause: ∅ ├── ensure_clause: │ @ EnsureNode (location: (1,13)-(1,29)) + │ ├── flags: ∅ │ ├── ensure_keyword_loc: (1,13)-(1,19) = "ensure" │ ├── statements: │ │ @ StatementsNode (location: (1,21)-(1,24)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (1,21)-(1,24)) - │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── flags: newline, variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar diff --git a/test/prism/snapshots/whitequark/ensure_empty.txt b/test/prism/snapshots/whitequark/ensure_empty.txt index 0bab5d80c36..c7369b7b1f5 100644 --- a/test/prism/snapshots/whitequark/ensure_empty.txt +++ b/test/prism/snapshots/whitequark/ensure_empty.txt @@ -1,15 +1,19 @@ @ ProgramNode (location: (1,0)-(1,16)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,16)) + ├── flags: ∅ └── body: (length: 1) └── @ BeginNode (location: (1,0)-(1,16)) + ├── flags: newline ├── begin_keyword_loc: (1,0)-(1,5) = "begin" ├── statements: ∅ ├── rescue_clause: ∅ ├── else_clause: ∅ ├── ensure_clause: │ @ EnsureNode (location: (1,6)-(1,16)) + │ ├── flags: ∅ │ ├── ensure_keyword_loc: (1,6)-(1,12) = "ensure" │ ├── statements: ∅ │ └── end_keyword_loc: (1,13)-(1,16) = "end" diff --git a/test/prism/snapshots/whitequark/false.txt b/test/prism/snapshots/whitequark/false.txt index 00562f703a9..4686f6aa08a 100644 --- a/test/prism/snapshots/whitequark/false.txt +++ b/test/prism/snapshots/whitequark/false.txt @@ -1,6 +1,9 @@ @ ProgramNode (location: (1,0)-(1,5)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,5)) + ├── flags: ∅ └── body: (length: 1) └── @ FalseNode (location: (1,0)-(1,5)) + └── flags: newline, static_literal diff --git a/test/prism/snapshots/whitequark/float.txt b/test/prism/snapshots/whitequark/float.txt index 5e6a597db7d..7839f899625 100644 --- a/test/prism/snapshots/whitequark/float.txt +++ b/test/prism/snapshots/whitequark/float.txt @@ -1,9 +1,13 @@ @ ProgramNode (location: (1,0)-(3,4)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,4)) + ├── flags: ∅ └── body: (length: 2) ├── @ FloatNode (location: (1,0)-(1,5)) + │ ├── flags: newline, static_literal │ └── value: -1.33 └── @ FloatNode (location: (3,0)-(3,4)) + ├── flags: newline, static_literal └── value: 1.33 diff --git a/test/prism/snapshots/whitequark/for.txt b/test/prism/snapshots/whitequark/for.txt index fec8bdfd64f..8dca927c905 100644 --- a/test/prism/snapshots/whitequark/for.txt +++ b/test/prism/snapshots/whitequark/for.txt @@ -1,11 +1,15 @@ @ ProgramNode (location: (1,0)-(3,22)) +├── flags: ∅ ├── locals: [:a] └── statements: @ StatementsNode (location: (1,0)-(3,22)) + ├── flags: ∅ └── body: (length: 2) ├── @ ForNode (location: (1,0)-(1,24)) + │ ├── flags: newline │ ├── index: │ │ @ LocalVariableTargetNode (location: (1,4)-(1,5)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── collection: @@ -21,9 +25,10 @@ │ │ └── block: ∅ │ ├── statements: │ │ @ StatementsNode (location: (1,16)-(1,19)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (1,16)-(1,19)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :p @@ -34,6 +39,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ LocalVariableReadNode (location: (1,18)-(1,19)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── closing_loc: ∅ @@ -43,8 +49,10 @@ │ ├── do_keyword_loc: (1,13)-(1,15) = "do" │ └── end_keyword_loc: (1,21)-(1,24) = "end" └── @ ForNode (location: (3,0)-(3,22)) + ├── flags: newline ├── index: │ @ LocalVariableTargetNode (location: (3,4)-(3,5)) + │ ├── flags: ∅ │ ├── name: :a │ └── depth: 0 ├── collection: @@ -60,9 +68,10 @@ │ └── block: ∅ ├── statements: │ @ StatementsNode (location: (3,14)-(3,17)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (3,14)-(3,17)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :p @@ -73,6 +82,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ LocalVariableReadNode (location: (3,16)-(3,17)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ └── depth: 0 │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/for_mlhs.txt b/test/prism/snapshots/whitequark/for_mlhs.txt index 42d8fa22585..0f70dd8a7da 100644 --- a/test/prism/snapshots/whitequark/for_mlhs.txt +++ b/test/prism/snapshots/whitequark/for_mlhs.txt @@ -1,16 +1,22 @@ @ ProgramNode (location: (1,0)-(1,28)) +├── flags: ∅ ├── locals: [:a, :b] └── statements: @ StatementsNode (location: (1,0)-(1,28)) + ├── flags: ∅ └── body: (length: 1) └── @ ForNode (location: (1,0)-(1,28)) + ├── flags: newline ├── index: │ @ MultiTargetNode (location: (1,4)-(1,8)) + │ ├── flags: ∅ │ ├── lefts: (length: 2) │ │ ├── @ LocalVariableTargetNode (location: (1,4)-(1,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ └── @ LocalVariableTargetNode (location: (1,7)-(1,8)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ └── depth: 0 │ ├── rest: ∅ @@ -30,9 +36,10 @@ │ └── block: ∅ ├── statements: │ @ StatementsNode (location: (1,17)-(1,23)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,17)-(1,23)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :p @@ -43,9 +50,11 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ LocalVariableReadNode (location: (1,19)-(1,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ └── @ LocalVariableReadNode (location: (1,22)-(1,23)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ └── depth: 0 │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/forward_arg.txt b/test/prism/snapshots/whitequark/forward_arg.txt index 17504c64e02..3879314fa89 100644 --- a/test/prism/snapshots/whitequark/forward_arg.txt +++ b/test/prism/snapshots/whitequark/forward_arg.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,27)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,27)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,27)) + ├── flags: newline ├── name: :foo ├── name_loc: (1,4)-(1,7) = "foo" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,8)-(1,11)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -16,12 +20,14 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ ForwardingParameterNode (location: (1,8)-(1,11)) + │ │ └── flags: ∅ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (1,14)-(1,22)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,14)-(1,22)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :bar @@ -29,9 +35,10 @@ │ ├── opening_loc: (1,17)-(1,18) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (1,18)-(1,21)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_forwarding │ │ └── arguments: (length: 1) │ │ └── @ ForwardingArgumentsNode (location: (1,18)-(1,21)) + │ │ └── flags: ∅ │ ├── closing_loc: (1,21)-(1,22) = ")" │ └── block: ∅ ├── locals: [] diff --git a/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt b/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt index 7e58260b582..ea36abae7ea 100644 --- a/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt +++ b/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt @@ -1,18 +1,24 @@ @ ProgramNode (location: (1,0)-(27,28)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(27,28)) + ├── flags: ∅ └── body: (length: 10) ├── @ ParenthesesNode (location: (1,0)-(3,4)) + │ ├── flags: newline │ ├── body: │ │ @ StatementsNode (location: (1,1)-(3,3)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ DefNode (location: (1,1)-(3,3)) + │ │ ├── flags: newline │ │ ├── name: :foo │ │ ├── name_loc: (1,5)-(1,8) = "foo" │ │ ├── receiver: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (1,9)-(1,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -20,12 +26,14 @@ │ │ │ ├── keywords: (length: 0) │ │ │ ├── keyword_rest: │ │ │ │ @ ForwardingParameterNode (location: (1,9)-(1,12)) + │ │ │ │ └── flags: ∅ │ │ │ └── block: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (2,2)-(2,10)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (2,2)-(2,10)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -33,9 +41,10 @@ │ │ │ ├── opening_loc: (2,5)-(2,6) = "(" │ │ │ ├── arguments: │ │ │ │ @ ArgumentsNode (location: (2,6)-(2,9)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: contains_forwarding │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ ForwardingArgumentsNode (location: (2,6)-(2,9)) + │ │ │ │ └── flags: ∅ │ │ │ ├── closing_loc: (2,9)-(2,10) = ")" │ │ │ └── block: ∅ │ │ ├── locals: [] @@ -48,15 +57,19 @@ │ ├── opening_loc: (1,0)-(1,1) = "(" │ └── closing_loc: (3,3)-(3,4) = ")" ├── @ ParenthesesNode (location: (5,0)-(5,28)) + │ ├── flags: newline │ ├── body: │ │ @ StatementsNode (location: (5,1)-(5,27)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ DefNode (location: (5,1)-(5,27)) + │ │ ├── flags: newline │ │ ├── name: :foo │ │ ├── name_loc: (5,5)-(5,8) = "foo" │ │ ├── receiver: ∅ │ │ ├── parameters: │ │ │ @ ParametersNode (location: (5,9)-(5,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -64,12 +77,14 @@ │ │ │ ├── keywords: (length: 0) │ │ │ ├── keyword_rest: │ │ │ │ @ ForwardingParameterNode (location: (5,9)-(5,12)) + │ │ │ │ └── flags: ∅ │ │ │ └── block: ∅ │ │ ├── body: │ │ │ @ StatementsNode (location: (5,14)-(5,22)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ CallNode (location: (5,14)-(5,22)) - │ │ │ ├── flags: ignore_visibility + │ │ │ ├── flags: newline, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar @@ -77,9 +92,10 @@ │ │ │ ├── opening_loc: (5,17)-(5,18) = "(" │ │ │ ├── arguments: │ │ │ │ @ ArgumentsNode (location: (5,18)-(5,21)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: contains_forwarding │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ ForwardingArgumentsNode (location: (5,18)-(5,21)) + │ │ │ │ └── flags: ∅ │ │ │ ├── closing_loc: (5,21)-(5,22) = ")" │ │ │ └── block: ∅ │ │ ├── locals: [] @@ -92,11 +108,13 @@ │ ├── opening_loc: (5,0)-(5,1) = "(" │ └── closing_loc: (5,27)-(5,28) = ")" ├── @ DefNode (location: (7,0)-(8,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (7,4)-(7,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (7,8)-(7,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -104,6 +122,7 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ ForwardingParameterNode (location: (7,8)-(7,11)) + │ │ │ └── flags: ∅ │ │ └── block: ∅ │ ├── body: ∅ │ ├── locals: [] @@ -114,11 +133,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (8,0)-(8,3) = "end" ├── @ DefNode (location: (10,0)-(10,26)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (10,4)-(10,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (10,8)-(10,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -126,12 +147,14 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ ForwardingParameterNode (location: (10,8)-(10,11)) + │ │ │ └── flags: ∅ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (10,13)-(10,21)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (10,13)-(10,21)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -139,9 +162,10 @@ │ │ ├── opening_loc: (10,16)-(10,17) = "(" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (10,17)-(10,20)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_forwarding │ │ │ └── arguments: (length: 1) │ │ │ └── @ ForwardingArgumentsNode (location: (10,17)-(10,20)) + │ │ │ └── flags: ∅ │ │ ├── closing_loc: (10,20)-(10,21) = ")" │ │ └── block: ∅ │ ├── locals: [] @@ -152,11 +176,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (10,23)-(10,26) = "end" ├── @ DefNode (location: (12,0)-(14,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (12,4)-(12,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (12,8)-(12,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (12,8)-(12,9)) │ │ │ ├── flags: ∅ @@ -167,12 +193,14 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ ForwardingParameterNode (location: (12,11)-(12,14)) + │ │ │ └── flags: ∅ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (13,2)-(13,10)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (13,2)-(13,10)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -180,9 +208,10 @@ │ │ ├── opening_loc: (13,5)-(13,6) = "(" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (13,6)-(13,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_forwarding │ │ │ └── arguments: (length: 1) │ │ │ └── @ ForwardingArgumentsNode (location: (13,6)-(13,9)) + │ │ │ └── flags: ∅ │ │ ├── closing_loc: (13,9)-(13,10) = ")" │ │ └── block: ∅ │ ├── locals: [:a] @@ -193,11 +222,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (14,0)-(14,3) = "end" ├── @ DefNode (location: (16,0)-(16,29)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (16,4)-(16,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (16,8)-(16,14)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (16,8)-(16,9)) │ │ │ ├── flags: ∅ @@ -208,12 +239,14 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ ForwardingParameterNode (location: (16,11)-(16,14)) + │ │ │ └── flags: ∅ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (16,16)-(16,24)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (16,16)-(16,24)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -221,9 +254,10 @@ │ │ ├── opening_loc: (16,19)-(16,20) = "(" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (16,20)-(16,23)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_forwarding │ │ │ └── arguments: (length: 1) │ │ │ └── @ ForwardingArgumentsNode (location: (16,20)-(16,23)) + │ │ │ └── flags: ∅ │ │ ├── closing_loc: (16,23)-(16,24) = ")" │ │ └── block: ∅ │ ├── locals: [:a] @@ -234,11 +268,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (16,26)-(16,29) = "end" ├── @ DefNode (location: (18,0)-(19,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (18,4)-(18,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (18,8)-(18,21)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (18,8)-(18,9)) │ │ │ ├── flags: ∅ @@ -251,13 +287,14 @@ │ │ │ ├── operator_loc: (18,13)-(18,14) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (18,15)-(18,16)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ ForwardingParameterNode (location: (18,18)-(18,21)) + │ │ │ └── flags: ∅ │ │ └── block: ∅ │ ├── body: ∅ │ ├── locals: [:a, :b] @@ -268,11 +305,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (19,0)-(19,3) = "end" ├── @ DefNode (location: (21,0)-(23,3)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (21,4)-(21,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (21,8)-(21,18)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (21,8)-(21,13)) @@ -282,19 +321,21 @@ │ │ │ ├── operator_loc: (21,10)-(21,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (21,12)-(21,13)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ ForwardingParameterNode (location: (21,15)-(21,18)) + │ │ │ └── flags: ∅ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (22,2)-(22,10)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (22,2)-(22,10)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -302,9 +343,10 @@ │ │ ├── opening_loc: (22,5)-(22,6) = "(" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (22,6)-(22,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_forwarding │ │ │ └── arguments: (length: 1) │ │ │ └── @ ForwardingArgumentsNode (location: (22,6)-(22,9)) + │ │ │ └── flags: ∅ │ │ ├── closing_loc: (22,9)-(22,10) = ")" │ │ └── block: ∅ │ ├── locals: [:b] @@ -315,11 +357,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (23,0)-(23,3) = "end" ├── @ DefNode (location: (25,0)-(25,33)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (25,4)-(25,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (25,8)-(25,18)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (25,8)-(25,13)) @@ -329,19 +373,21 @@ │ │ │ ├── operator_loc: (25,10)-(25,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (25,12)-(25,13)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ ForwardingParameterNode (location: (25,15)-(25,18)) + │ │ │ └── flags: ∅ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (25,20)-(25,28)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (25,20)-(25,28)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -349,9 +395,10 @@ │ │ ├── opening_loc: (25,23)-(25,24) = "(" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (25,24)-(25,27)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_forwarding │ │ │ └── arguments: (length: 1) │ │ │ └── @ ForwardingArgumentsNode (location: (25,24)-(25,27)) + │ │ │ └── flags: ∅ │ │ ├── closing_loc: (25,27)-(25,28) = ")" │ │ └── block: ∅ │ ├── locals: [:b] @@ -362,11 +409,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (25,30)-(25,33) = "end" └── @ DefNode (location: (27,0)-(27,28)) + ├── flags: newline ├── name: :foo ├── name_loc: (27,4)-(27,7) = "foo" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (27,8)-(27,14)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (27,8)-(27,9)) │ │ ├── flags: ∅ @@ -377,12 +426,14 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ ForwardingParameterNode (location: (27,11)-(27,14)) + │ │ └── flags: ∅ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (27,16)-(27,24)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (27,16)-(27,24)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :bar @@ -390,9 +441,10 @@ │ ├── opening_loc: (27,19)-(27,20) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (27,20)-(27,23)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_forwarding │ │ └── arguments: (length: 1) │ │ └── @ ForwardingArgumentsNode (location: (27,20)-(27,23)) + │ │ └── flags: ∅ │ ├── closing_loc: (27,23)-(27,24) = ")" │ └── block: ∅ ├── locals: [:a] diff --git a/test/prism/snapshots/whitequark/forward_args_legacy.txt b/test/prism/snapshots/whitequark/forward_args_legacy.txt index f46967ba500..2fda9338f3f 100644 --- a/test/prism/snapshots/whitequark/forward_args_legacy.txt +++ b/test/prism/snapshots/whitequark/forward_args_legacy.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(5,29)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(5,29)) + ├── flags: ∅ └── body: (length: 3) ├── @ DefNode (location: (1,0)-(1,27)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (1,4)-(1,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (1,8)-(1,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -16,12 +20,14 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ ForwardingParameterNode (location: (1,8)-(1,11)) + │ │ │ └── flags: ∅ │ │ └── block: ∅ │ ├── body: │ │ @ StatementsNode (location: (1,14)-(1,22)) + │ │ ├── flags: ∅ │ │ └── body: (length: 1) │ │ └── @ CallNode (location: (1,14)-(1,22)) - │ │ ├── flags: ignore_visibility + │ │ ├── flags: newline, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar @@ -29,9 +35,10 @@ │ │ ├── opening_loc: (1,17)-(1,18) = "(" │ │ ├── arguments: │ │ │ @ ArgumentsNode (location: (1,18)-(1,21)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: contains_forwarding │ │ │ └── arguments: (length: 1) │ │ │ └── @ ForwardingArgumentsNode (location: (1,18)-(1,21)) + │ │ │ └── flags: ∅ │ │ ├── closing_loc: (1,21)-(1,22) = ")" │ │ └── block: ∅ │ ├── locals: [] @@ -42,11 +49,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (1,24)-(1,27) = "end" ├── @ DefNode (location: (3,0)-(3,17)) + │ ├── flags: newline │ ├── name: :foo │ ├── name_loc: (3,4)-(3,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: │ │ @ ParametersNode (location: (3,8)-(3,11)) + │ │ ├── flags: ∅ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -54,6 +63,7 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ ForwardingParameterNode (location: (3,8)-(3,11)) + │ │ │ └── flags: ∅ │ │ └── block: ∅ │ ├── body: ∅ │ ├── locals: [] @@ -64,11 +74,13 @@ │ ├── equal_loc: ∅ │ └── end_keyword_loc: (3,14)-(3,17) = "end" └── @ DefNode (location: (5,0)-(5,29)) + ├── flags: newline ├── name: :foo ├── name_loc: (5,4)-(5,7) = "foo" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (5,8)-(5,11)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -76,18 +88,22 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ ForwardingParameterNode (location: (5,8)-(5,11)) + │ │ └── flags: ∅ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (5,14)-(5,24)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ SuperNode (location: (5,14)-(5,24)) + │ ├── flags: newline │ ├── keyword_loc: (5,14)-(5,19) = "super" │ ├── lparen_loc: (5,19)-(5,20) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (5,20)-(5,23)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_forwarding │ │ └── arguments: (length: 1) │ │ └── @ ForwardingArgumentsNode (location: (5,20)-(5,23)) + │ │ └── flags: ∅ │ ├── rparen_loc: (5,23)-(5,24) = ")" │ └── block: ∅ ├── locals: [] diff --git a/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt b/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt index acaf9c052d1..d80ace6fbaf 100644 --- a/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt +++ b/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,45)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,45)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,45)) + ├── flags: newline ├── name: :foo ├── name_loc: (1,4)-(1,7) = "foo" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,8)-(1,20)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,8)-(1,16)) │ │ ├── flags: ∅ @@ -26,9 +30,10 @@ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (1,23)-(1,40)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,23)-(1,40)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :bar @@ -39,12 +44,14 @@ │ │ ├── flags: contains_keywords, contains_keyword_splat │ │ └── arguments: (length: 2) │ │ ├── @ LocalVariableReadNode (location: (1,27)-(1,35)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :argument │ │ │ └── depth: 0 │ │ └── @ KeywordHashNode (location: (1,37)-(1,39)) │ │ ├── flags: ∅ │ │ └── elements: (length: 1) │ │ └── @ AssocSplatNode (location: (1,37)-(1,39)) + │ │ ├── flags: ∅ │ │ ├── value: ∅ │ │ └── operator_loc: (1,37)-(1,39) = "**" │ ├── closing_loc: (1,39)-(1,40) = ")" diff --git a/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt b/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt index 367fad7fec8..2dd95c6cae1 100644 --- a/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt +++ b/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,43)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,43)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,43)) + ├── flags: newline ├── name: :foo ├── name_loc: (1,4)-(1,7) = "foo" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,8)-(1,19)) + │ ├── flags: ∅ │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,8)-(1,16)) │ │ ├── flags: ∅ @@ -26,9 +30,10 @@ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (1,22)-(1,38)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,22)-(1,38)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :bar @@ -36,12 +41,14 @@ │ ├── opening_loc: (1,25)-(1,26) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (1,26)-(1,37)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat │ │ └── arguments: (length: 2) │ │ ├── @ LocalVariableReadNode (location: (1,26)-(1,34)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :argument │ │ │ └── depth: 0 │ │ └── @ SplatNode (location: (1,36)-(1,37)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (1,36)-(1,37) = "*" │ │ └── expression: ∅ │ ├── closing_loc: (1,37)-(1,38) = ")" diff --git a/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt b/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt index b4235fb20ae..50cc9ca38b8 100644 --- a/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt +++ b/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,25)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,25)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,25)) + ├── flags: newline ├── name: :foo ├── name_loc: (1,4)-(1,7) = "foo" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,8)-(1,10)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -23,9 +27,10 @@ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (1,13)-(1,20)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,13)-(1,20)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :bar @@ -39,6 +44,7 @@ │ │ ├── flags: ∅ │ │ └── elements: (length: 1) │ │ └── @ AssocSplatNode (location: (1,17)-(1,19)) + │ │ ├── flags: ∅ │ │ ├── value: ∅ │ │ └── operator_loc: (1,17)-(1,19) = "**" │ ├── closing_loc: (1,19)-(1,20) = ")" diff --git a/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt b/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt index 33779abcc16..32ace5cb3d4 100644 --- a/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt +++ b/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,41)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,41)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,41)) + ├── flags: newline ├── name: :foo ├── name_loc: (1,4)-(1,7) = "foo" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,8)-(1,10)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -23,9 +27,10 @@ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (1,13)-(1,36)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,13)-(1,36)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :bar @@ -39,18 +44,21 @@ │ │ ├── flags: ∅ │ │ └── elements: (length: 2) │ │ ├── @ AssocSplatNode (location: (1,17)-(1,19)) + │ │ │ ├── flags: ∅ │ │ │ ├── value: ∅ │ │ │ └── operator_loc: (1,17)-(1,19) = "**" │ │ └── @ AssocNode (location: (1,21)-(1,35)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (1,21)-(1,30)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,21)-(1,29) = "from_foo" │ │ │ ├── closing_loc: (1,29)-(1,30) = ":" │ │ │ └── unescaped: "from_foo" │ │ ├── value: │ │ │ @ TrueNode (location: (1,31)-(1,35)) + │ │ │ └── flags: static_literal │ │ └── operator_loc: ∅ │ ├── closing_loc: (1,35)-(1,36) = ")" │ └── block: ∅ diff --git a/test/prism/snapshots/whitequark/forwarded_restarg.txt b/test/prism/snapshots/whitequark/forwarded_restarg.txt index 17ff8894afa..3e26b2b60ee 100644 --- a/test/prism/snapshots/whitequark/forwarded_restarg.txt +++ b/test/prism/snapshots/whitequark/forwarded_restarg.txt @@ -1,14 +1,18 @@ @ ProgramNode (location: (1,0)-(1,23)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,23)) + ├── flags: ∅ └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,23)) + ├── flags: newline ├── name: :foo ├── name_loc: (1,4)-(1,7) = "foo" ├── receiver: ∅ ├── parameters: │ @ ParametersNode (location: (1,8)-(1,9)) + │ ├── flags: ∅ │ ├── requireds: (length: 0) │ ├── optionals: (length: 0) │ ├── rest: @@ -23,9 +27,10 @@ │ └── block: ∅ ├── body: │ @ StatementsNode (location: (1,12)-(1,18)) + │ ├── flags: ∅ │ └── body: (length: 1) │ └── @ CallNode (location: (1,12)-(1,18)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :bar @@ -33,9 +38,10 @@ │ ├── opening_loc: (1,15)-(1,16) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (1,16)-(1,17)) - │ │ ├── flags: ∅ + │ │ ├── flags: contains_splat │ │ └── arguments: (length: 1) │ │ └── @ SplatNode (location: (1,16)-(1,17)) + │ │ ├── flags: ∅ │ │ ├── operator_loc: (1,16)-(1,17) = "*" │ │ └── expression: ∅ │ ├── closing_loc: (1,17)-(1,18) = ")" diff --git a/test/prism/snapshots/whitequark/gvar.txt b/test/prism/snapshots/whitequark/gvar.txt index f4401c4389b..5191f28e241 100644 --- a/test/prism/snapshots/whitequark/gvar.txt +++ b/test/prism/snapshots/whitequark/gvar.txt @@ -1,7 +1,10 @@ @ ProgramNode (location: (1,0)-(1,4)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,4)) + ├── flags: ∅ └── body: (length: 1) └── @ GlobalVariableReadNode (location: (1,0)-(1,4)) + ├── flags: newline └── name: :$foo diff --git a/test/prism/snapshots/whitequark/gvasgn.txt b/test/prism/snapshots/whitequark/gvasgn.txt index fc044054d88..e5bfe44d18a 100644 --- a/test/prism/snapshots/whitequark/gvasgn.txt +++ b/test/prism/snapshots/whitequark/gvasgn.txt @@ -1,13 +1,16 @@ @ ProgramNode (location: (1,0)-(1,9)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,9)) + ├── flags: ∅ └── body: (length: 1) └── @ GlobalVariableWriteNode (location: (1,0)-(1,9)) + ├── flags: newline ├── name: :$var ├── name_loc: (1,0)-(1,4) = "$var" ├── value: │ @ IntegerNode (location: (1,7)-(1,9)) - │ ├── flags: decimal + │ ├── flags: static_literal, decimal │ └── value: 10 └── operator_loc: (1,5)-(1,6) = "=" diff --git a/test/prism/snapshots/whitequark/hash_empty.txt b/test/prism/snapshots/whitequark/hash_empty.txt index 38a2c15a9ad..3f6fcdd171f 100644 --- a/test/prism/snapshots/whitequark/hash_empty.txt +++ b/test/prism/snapshots/whitequark/hash_empty.txt @@ -1,9 +1,12 @@ @ ProgramNode (location: (1,0)-(1,3)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,3)) + ├── flags: ∅ └── body: (length: 1) └── @ HashNode (location: (1,0)-(1,3)) + ├── flags: newline, static_literal ├── opening_loc: (1,0)-(1,1) = "{" ├── elements: (length: 0) └── closing_loc: (1,2)-(1,3) = "}" diff --git a/test/prism/snapshots/whitequark/hash_hashrocket.txt b/test/prism/snapshots/whitequark/hash_hashrocket.txt index e661a7b0480..fcf3fe3055b 100644 --- a/test/prism/snapshots/whitequark/hash_hashrocket.txt +++ b/test/prism/snapshots/whitequark/hash_hashrocket.txt @@ -1,39 +1,46 @@ @ ProgramNode (location: (1,0)-(3,25)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(3,25)) + ├── flags: ∅ └── body: (length: 2) ├── @ HashNode (location: (1,0)-(1,10)) + │ ├── flags: newline, static_literal │ ├── opening_loc: (1,0)-(1,1) = "{" │ ├── elements: (length: 1) │ │ └── @ AssocNode (location: (1,2)-(1,8)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ IntegerNode (location: (1,2)-(1,3)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── value: │ │ │ @ IntegerNode (location: (1,7)-(1,8)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: (1,4)-(1,6) = "=>" │ └── closing_loc: (1,9)-(1,10) = "}" └── @ HashNode (location: (3,0)-(3,25)) + ├── flags: newline ├── opening_loc: (3,0)-(3,1) = "{" ├── elements: (length: 2) │ ├── @ AssocNode (location: (3,2)-(3,8)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ IntegerNode (location: (3,2)-(3,3)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 1 │ │ ├── value: │ │ │ @ IntegerNode (location: (3,7)-(3,8)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: (3,4)-(3,6) = "=>" │ └── @ AssocNode (location: (3,10)-(3,23)) + │ ├── flags: ∅ │ ├── key: │ │ @ SymbolNode (location: (3,10)-(3,14)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (3,10)-(3,11) = ":" │ │ ├── value_loc: (3,11)-(3,14) = "foo" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/hash_kwsplat.txt b/test/prism/snapshots/whitequark/hash_kwsplat.txt index a5d12174cc4..acccc48b3d6 100644 --- a/test/prism/snapshots/whitequark/hash_kwsplat.txt +++ b/test/prism/snapshots/whitequark/hash_kwsplat.txt @@ -1,25 +1,30 @@ @ ProgramNode (location: (1,0)-(1,17)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,17)) + ├── flags: ∅ └── body: (length: 1) └── @ HashNode (location: (1,0)-(1,17)) + ├── flags: newline ├── opening_loc: (1,0)-(1,1) = "{" ├── elements: (length: 2) │ ├── @ AssocNode (location: (1,2)-(1,8)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (1,2)-(1,6)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,2)-(1,5) = "foo" │ │ │ ├── closing_loc: (1,5)-(1,6) = ":" │ │ │ └── unescaped: "foo" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,7)-(1,8)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: ∅ │ └── @ AssocSplatNode (location: (1,10)-(1,15)) + │ ├── flags: ∅ │ ├── value: │ │ @ CallNode (location: (1,12)-(1,15)) │ │ ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/whitequark/hash_label.txt b/test/prism/snapshots/whitequark/hash_label.txt index fdf7a21ed0c..b321e218592 100644 --- a/test/prism/snapshots/whitequark/hash_label.txt +++ b/test/prism/snapshots/whitequark/hash_label.txt @@ -1,22 +1,26 @@ @ ProgramNode (location: (1,0)-(1,10)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,10)) + ├── flags: ∅ └── body: (length: 1) └── @ HashNode (location: (1,0)-(1,10)) + ├── flags: newline, static_literal ├── opening_loc: (1,0)-(1,1) = "{" ├── elements: (length: 1) │ └── @ AssocNode (location: (1,2)-(1,8)) + │ ├── flags: static_literal │ ├── key: │ │ @ SymbolNode (location: (1,2)-(1,6)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,2)-(1,5) = "foo" │ │ ├── closing_loc: (1,5)-(1,6) = ":" │ │ └── unescaped: "foo" │ ├── value: │ │ @ IntegerNode (location: (1,7)-(1,8)) - │ │ ├── flags: decimal + │ │ ├── flags: static_literal, decimal │ │ └── value: 2 │ └── operator_loc: ∅ └── closing_loc: (1,9)-(1,10) = "}" diff --git a/test/prism/snapshots/whitequark/hash_label_end.txt b/test/prism/snapshots/whitequark/hash_label_end.txt index 88b70d38e2c..9e4accee004 100644 --- a/test/prism/snapshots/whitequark/hash_label_end.txt +++ b/test/prism/snapshots/whitequark/hash_label_end.txt @@ -1,10 +1,12 @@ @ ProgramNode (location: (1,0)-(5,22)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(5,22)) + ├── flags: ∅ └── body: (length: 3) ├── @ CallNode (location: (1,0)-(1,12)) - │ ├── flags: ignore_visibility + │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :f @@ -15,6 +17,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IfNode (location: (1,2)-(1,11)) + │ │ ├── flags: newline │ │ ├── if_keyword_loc: ∅ │ │ ├── predicate: │ │ │ @ CallNode (location: (1,2)-(1,3)) @@ -30,69 +33,78 @@ │ │ ├── then_keyword_loc: (1,4)-(1,5) = "?" │ │ ├── statements: │ │ │ @ StatementsNode (location: (1,6)-(1,9)) + │ │ │ ├── flags: ∅ │ │ │ └── body: (length: 1) │ │ │ └── @ StringNode (location: (1,6)-(1,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: newline │ │ │ ├── opening_loc: (1,6)-(1,7) = "\"" │ │ │ ├── content_loc: (1,7)-(1,8) = "a" │ │ │ ├── closing_loc: (1,8)-(1,9) = "\"" │ │ │ └── unescaped: "a" - │ │ ├── consequent: + │ │ ├── subsequent: │ │ │ @ ElseNode (location: (1,9)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── else_keyword_loc: (1,9)-(1,10) = ":" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (1,10)-(1,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ │ │ │ ├── flags: decimal + │ │ │ │ ├── flags: newline, static_literal, decimal │ │ │ │ └── value: 1 │ │ │ └── end_keyword_loc: ∅ │ │ └── end_keyword_loc: ∅ │ ├── closing_loc: (1,11)-(1,12) = ")" │ └── block: ∅ ├── @ HashNode (location: (3,0)-(3,12)) + │ ├── flags: newline, static_literal │ ├── opening_loc: (3,0)-(3,1) = "{" │ ├── elements: (length: 1) │ │ └── @ AssocNode (location: (3,2)-(3,10)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (3,2)-(3,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (3,2)-(3,3) = "'" │ │ │ ├── value_loc: (3,3)-(3,6) = "foo" │ │ │ ├── closing_loc: (3,6)-(3,8) = "':" │ │ │ └── unescaped: "foo" │ │ ├── value: │ │ │ @ IntegerNode (location: (3,9)-(3,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: ∅ │ └── closing_loc: (3,11)-(3,12) = "}" └── @ HashNode (location: (5,0)-(5,22)) + ├── flags: newline ├── opening_loc: (5,0)-(5,1) = "{" ├── elements: (length: 2) │ ├── @ AssocNode (location: (5,2)-(5,10)) + │ │ ├── flags: static_literal │ │ ├── key: │ │ │ @ SymbolNode (location: (5,2)-(5,8)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: (5,2)-(5,3) = "'" │ │ │ ├── value_loc: (5,3)-(5,6) = "foo" │ │ │ ├── closing_loc: (5,6)-(5,8) = "':" │ │ │ └── unescaped: "foo" │ │ ├── value: │ │ │ @ IntegerNode (location: (5,9)-(5,10)) - │ │ │ ├── flags: decimal + │ │ │ ├── flags: static_literal, decimal │ │ │ └── value: 2 │ │ └── operator_loc: ∅ │ └── @ AssocNode (location: (5,12)-(5,21)) + │ ├── flags: ∅ │ ├── key: │ │ @ SymbolNode (location: (5,12)-(5,18)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: (5,12)-(5,13) = "'" │ │ ├── value_loc: (5,13)-(5,16) = "bar" │ │ ├── closing_loc: (5,16)-(5,18) = "':" │ │ └── unescaped: "bar" │ ├── value: │ │ @ HashNode (location: (5,19)-(5,21)) + │ │ ├── flags: static_literal │ │ ├── opening_loc: (5,19)-(5,20) = "{" │ │ ├── elements: (length: 0) │ │ └── closing_loc: (5,20)-(5,21) = "}" diff --git a/test/prism/snapshots/whitequark/hash_pair_value_omission.txt b/test/prism/snapshots/whitequark/hash_pair_value_omission.txt index 455ba48407a..d87b1ef0f9f 100644 --- a/test/prism/snapshots/whitequark/hash_pair_value_omission.txt +++ b/test/prism/snapshots/whitequark/hash_pair_value_omission.txt @@ -1,39 +1,48 @@ @ ProgramNode (location: (1,0)-(5,7)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(5,7)) + ├── flags: ∅ └── body: (length: 3) ├── @ HashNode (location: (1,0)-(1,6)) + │ ├── flags: newline │ ├── opening_loc: (1,0)-(1,1) = "{" │ ├── elements: (length: 1) │ │ └── @ AssocNode (location: (1,1)-(1,5)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ SymbolNode (location: (1,1)-(1,5)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,1)-(1,4) = "BAR" │ │ │ ├── closing_loc: (1,4)-(1,5) = ":" │ │ │ └── unescaped: "BAR" │ │ ├── value: │ │ │ @ ImplicitNode (location: (1,1)-(1,5)) + │ │ │ ├── flags: ∅ │ │ │ └── value: │ │ │ @ ConstantReadNode (location: (1,1)-(1,5)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :BAR │ │ └── operator_loc: ∅ │ └── closing_loc: (1,5)-(1,6) = "}" ├── @ HashNode (location: (3,0)-(3,8)) + │ ├── flags: newline │ ├── opening_loc: (3,0)-(3,1) = "{" │ ├── elements: (length: 2) │ │ ├── @ AssocNode (location: (3,1)-(3,3)) + │ │ │ ├── flags: ∅ │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (3,1)-(3,3)) - │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (3,1)-(3,2) = "a" │ │ │ │ ├── closing_loc: (3,2)-(3,3) = ":" │ │ │ │ └── unescaped: "a" │ │ │ ├── value: │ │ │ │ @ ImplicitNode (location: (3,1)-(3,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── value: │ │ │ │ @ CallNode (location: (3,1)-(3,3)) │ │ │ │ ├── flags: ignore_visibility @@ -47,15 +56,17 @@ │ │ │ │ └── block: ∅ │ │ │ └── operator_loc: ∅ │ │ └── @ AssocNode (location: (3,5)-(3,7)) + │ │ ├── flags: ∅ │ │ ├── key: │ │ │ @ SymbolNode (location: (3,5)-(3,7)) - │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (3,5)-(3,6) = "b" │ │ │ ├── closing_loc: (3,6)-(3,7) = ":" │ │ │ └── unescaped: "b" │ │ ├── value: │ │ │ @ ImplicitNode (location: (3,5)-(3,7)) + │ │ │ ├── flags: ∅ │ │ │ └── value: │ │ │ @ CallNode (location: (3,5)-(3,7)) │ │ │ ├── flags: ignore_visibility @@ -70,18 +81,21 @@ │ │ └── operator_loc: ∅ │ └── closing_loc: (3,7)-(3,8) = "}" └── @ HashNode (location: (5,0)-(5,7)) + ├── flags: newline ├── opening_loc: (5,0)-(5,1) = "{" ├── elements: (length: 1) │ └── @ AssocNode (location: (5,1)-(5,6)) + │ ├── flags: ∅ │ ├── key: │ │ @ SymbolNode (location: (5,1)-(5,6)) - │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── flags: static_literal, forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (5,1)-(5,5) = "puts" │ │ ├── closing_loc: (5,5)-(5,6) = ":" │ │ └── unescaped: "puts" │ ├── value: │ │ @ ImplicitNode (location: (5,1)-(5,6)) + │ │ ├── flags: ∅ │ │ └── value: │ │ @ CallNode (location: (5,1)-(5,6)) │ │ ├── flags: ignore_visibility diff --git a/test/prism/snapshots/whitequark/heredoc.txt b/test/prism/snapshots/whitequark/heredoc.txt index 86543097ee1..76b3e94a922 100644 --- a/test/prism/snapshots/whitequark/heredoc.txt +++ b/test/prism/snapshots/whitequark/heredoc.txt @@ -1,22 +1,24 @@ @ ProgramNode (location: (1,0)-(11,8)) +├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(11,8)) + ├── flags: ∅ └── body: (length: 3) ├── @ StringNode (location: (1,0)-(1,8)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (1,0)-(1,8) = "<<'HERE'" │ ├── content_loc: (2,0)-(4,0) = "foo\nbar\n" │ ├── closing_loc: (4,0)-(5,0) = "HERE\n" │ └── unescaped: "foo\nbar\n" ├── @ StringNode (location: (6,0)-(6,6)) - │ ├── flags: ∅ + │ ├── flags: newline │ ├── opening_loc: (6,0)-(6,6) = "<(bar) {}") - refute_warning("->(; bar) {}", compare: false) - - refute_warning("def foo; bar = 1; tap { bar }; end") - refute_warning("def foo; bar = 1; tap { baz = bar; baz }; end") - end - - def test_void_statements - assert_warning("foo = 1; foo", "a variable in void") - assert_warning("@foo", "a variable in void") - assert_warning("@@foo", "a variable in void") - assert_warning("$foo", "a variable in void") - assert_warning("$+", "a variable in void") - assert_warning("$1", "a variable in void") - - assert_warning("self", "self in void") - assert_warning("nil", "nil in void") - assert_warning("true", "true in void") - assert_warning("false", "false in void") - - assert_warning("1", "literal in void") - assert_warning("1.0", "literal in void") - assert_warning("1r", "literal in void") - assert_warning("1i", "literal in void") - assert_warning(":foo", "literal in void") - assert_warning("\"foo\"", "literal in void") - assert_warning("\"foo\#{1}\"", "literal in void") - assert_warning("/foo/", "literal in void") - assert_warning("/foo\#{1}/", "literal in void") - - assert_warning("Foo", "constant in void") - assert_warning("::Foo", ":: in void") - assert_warning("Foo::Bar", ":: in void") - - assert_warning("1..2", ".. in void") - assert_warning("1..", ".. in void") - assert_warning("..2", ".. in void") - assert_warning("1...2", "... in void") - assert_warning("1...;", "... in void") - assert_warning("...2", "... in void") - - assert_warning("defined?(foo)", "defined? in void") - - assert_warning("1 + 1", "+ in void") - assert_warning("1 - 1", "- in void") - assert_warning("1 * 1", "* in void") - assert_warning("1 / 1", "/ in void") - assert_warning("1 % 1", "% in void") - assert_warning("1 | 1", "| in void") - assert_warning("1 ^ 1", "^ in void") - assert_warning("1 & 1", "& in void") - assert_warning("1 > 1", "> in void") - assert_warning("1 < 1", "< in void") - - assert_warning("1 ** 1", "** in void") - assert_warning("1 <= 1", "<= in void") - assert_warning("1 >= 1", ">= in void") - assert_warning("1 != 1", "!= in void") - assert_warning("1 == 1", "== in void") - assert_warning("1 <=> 1", "<=> in void") - - assert_warning("+foo", "+@ in void") - assert_warning("-foo", "-@ in void") - - assert_warning("def foo; @bar; @baz; end", "variable in void") - refute_warning("def foo; @bar; end") - refute_warning("@foo", compare: false, scopes: [[]]) - end - - def test_unreachable_statement - assert_warning("begin; rescue; retry; foo; end", "statement not reached") - - assert_warning("return; foo", "statement not reached") - - assert_warning("tap { break; foo }", "statement not reached") - assert_warning("tap { break 1; foo }", "statement not reached") - - assert_warning("tap { next; foo }", "statement not reached") - assert_warning("tap { next 1; foo }", "statement not reached") - - assert_warning("tap { redo; foo }", "statement not reached") - end - - private - - def assert_warning(source, message) - warnings = Prism.parse(source).warnings - - assert_equal 1, warnings.length - assert_include warnings.first.message, message - - if defined?(RubyVM::AbstractSyntaxTree) - assert_include capture_warning { RubyVM::AbstractSyntaxTree.parse(source) }, message - end - end - - def refute_warning(source, compare: true, **options) - assert_empty Prism.parse(source, **options).warnings - - if compare && defined?(RubyVM::AbstractSyntaxTree) - assert_empty capture_warning { RubyVM::AbstractSyntaxTree.parse(source) } - end - end - - def capture_warning - stderr, $stderr, verbose, $VERBOSE = $stderr, StringIO.new, $VERBOSE, true - - begin - yield - $stderr.string - ensure - $stderr, $VERBOSE = stderr, verbose - end - end - end -end