diff --git a/.gitattributes b/.gitattributes index 21fd53cb14..fee51d19c2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,6 +8,9 @@ test/prism/fixtures/unparser/**/*.txt linguist-vendored test/prism/fixtures/whitequark/**/*.txt linguist-vendored test/prism/snapshots/**/*.txt linguist-generated +rbi/generated/**/*.rbi linguist-generated +sig/generated/**/*.rbs linguist-generated + # All .rb files should have LF line ending, even on Windows, regardless of the git config core.autocrlf value. # All .txt should have their line endings as committed in the repository (there are some intentional CR in there), # regardless of the git config core.autocrlf value. diff --git a/.github/workflows/java-wasm-bindings.yml b/.github/workflows/java-wasm-bindings.yml index 3a0a066334..9c16f60848 100644 --- a/.github/workflows/java-wasm-bindings.yml +++ b/.github/workflows/java-wasm-bindings.yml @@ -7,6 +7,8 @@ on: - "include/" - "src/" - "*akefile*" + - "java/" + - "java-wasm/" branches: - main pull_request: @@ -38,14 +40,14 @@ jobs: uses: actions/setup-java@v5 with: distribution: 'temurin' - java-version: '17' + java-version: '21' cache: maven - name: Run the tests run: mvn -B install working-directory: java-wasm - - uses: actions/upload-artifact@v6 + - uses: actions/upload-artifact@v7 with: name: prism.wasm path: java-wasm/src/test/resources/prism.wasm diff --git a/.github/workflows/javascript-bindings.yml b/.github/workflows/javascript-bindings.yml index 6e7d51f282..3753ea2ce9 100644 --- a/.github/workflows/javascript-bindings.yml +++ b/.github/workflows/javascript-bindings.yml @@ -34,7 +34,7 @@ jobs: - name: Build the project run: make wasm WASI_SDK_PATH=$(pwd)/wasi-sdk-25.0-x86_64-linux - - uses: actions/upload-artifact@v6 + - uses: actions/upload-artifact@v7 with: name: prism.wasm path: javascript/src/prism.wasm diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d134bf68b7..9ed312d4d5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -79,7 +79,7 @@ jobs: shell: bash build-ibm: - if: github.repository == 'ruby/prism' && false + if: github.repository == 'ruby/prism' strategy: fail-fast: false matrix: @@ -257,7 +257,7 @@ jobs: bundler-cache: true - run: bundle config --local frozen false - run: bundle exec rake build:dev - - uses: actions/upload-artifact@v6 + - uses: actions/upload-artifact@v7 with: name: gem-package path: pkg @@ -308,7 +308,7 @@ jobs: - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.target.ruby }} - - uses: actions/download-artifact@v7 + - uses: actions/download-artifact@v8 with: name: gem-package path: pkg diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index e14746a155..5a27aecd4c 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -42,5 +42,17 @@ jobs: - name: Update npm run: npm install -g npm@latest - - run: npm publish + - name: Determine npm tag + id: npm-tag + run: | + PACKAGE_VERSION=$(node -p "require('./javascript/package.json').version") + LATEST_VERSION=$(npm view @ruby/prism version 2>/dev/null || echo "0.0.0") + if npx semver "$PACKAGE_VERSION" -r ">$LATEST_VERSION"; then + echo "tag=latest" >> "$GITHUB_OUTPUT" + else + MINOR=$(echo "$PACKAGE_VERSION" | cut -d. -f1,2) + echo "tag=stable-$MINOR" >> "$GITHUB_OUTPUT" + fi + + - run: npm publish --tag ${{ steps.npm-tag.outputs.tag }} working-directory: javascript diff --git a/.github/workflows/sync-ruby.yml b/.github/workflows/sync-ruby.yml index 66a736ed85..72be2a09c5 100644 --- a/.github/workflows/sync-ruby.yml +++ b/.github/workflows/sync-ruby.yml @@ -12,7 +12,7 @@ jobs: - name: Create GitHub App token id: app-token - uses: actions/create-github-app-token@v2 + uses: actions/create-github-app-token@v3 with: app-id: 2060836 private-key: ${{ secrets.RUBY_SYNC_DEFAULT_GEMS_PRIVATE_KEY }} diff --git a/.gitignore b/.gitignore index 6706482b64..4e66dc8b6a 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ out.svg /gemfiles/typecheck/bin/ /include/prism/ast.h /include/prism/diagnostic.h +/include/prism/node_new.h /javascript/node_modules/ /javascript/package-lock.json /javascript/src/deserialize.js @@ -39,9 +40,10 @@ out.svg /javascript/src/visitor.js /javascript/src/prism.wasm /javascript/src/*.d.ts -/java/org/prism/AbstractNodeVisitor.java -/java/org/prism/Loader.java -/java/org/prism/Nodes.java +/java/org/ruby_lang/prism/AbstractNodeVisitor.java +/java/org/ruby_lang/prism/Loader.java +/java/org/ruby_lang/prism/Nodes.java +/java-wasm/src/test/resources/prism.wasm /lib/prism/compiler.rb /lib/prism/dispatcher.rb /lib/prism/dot_visitor.rb @@ -59,12 +61,6 @@ out.svg /src/serialize.c /src/token_type.c /src/**/*.o -/sig/prism.rbs -/sig/prism/dsl.rbs -/sig/prism/mutation_compiler.rbs -/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 @@ -74,3 +70,5 @@ compile_commands.json .vscode/ tags + +wasi-sdk* diff --git a/Doxyfile b/Doxyfile index 8827dea28d..4ea648ed7a 100644 --- a/Doxyfile +++ b/Doxyfile @@ -24,6 +24,7 @@ OUTPUT_DIRECTORY = doc JAVADOC_AUTOBRIEF = YES OPTIMIZE_OUTPUT_FOR_C = YES INPUT = src src/util include include/prism include/prism/util +EXCLUDE = include/prism/debug_allocator.h HTML_OUTPUT = c SORT_MEMBER_DOCS = NO GENERATE_LATEX = NO diff --git a/Gemfile.lock b/Gemfile.lock index 7e23a63cd5..f42c601c6f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,24 +10,25 @@ GEM benchmark-ips (2.14.0) date (3.5.1) date (3.5.1-java) - erb (6.0.1) - erb (6.0.1-java) + erb (6.0.2) + erb (6.0.2-java) ffi (1.17.3) io-console (0.8.2) io-console (0.8.2-java) - irb (1.16.0) + irb (1.17.0) pp (>= 0.6.0) + prism (>= 1.3.0) rdoc (>= 4.0.0) reline (>= 0.4.2) jar-dependencies (0.5.5) mini_portile2 (2.8.9) - nokogiri (1.19.0) + nokogiri (1.19.1) mini_portile2 (~> 2.8.2) racc (~> 1.4) - nokogiri (1.19.0-java) + nokogiri (1.19.1-java) racc (~> 1.4) onigmo (0.1.0) - parser (3.3.10.0) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) @@ -45,7 +46,7 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rdoc (7.0.3) + rdoc (7.2.0) erb psych (>= 4.0.0) tsort @@ -58,7 +59,7 @@ GEM sexp_processor (~> 4.16) sexp_processor (4.17.5) stringio (3.2.0) - test-unit (3.7.6) + test-unit (3.7.7) power_assert tsort (0.2.0) diff --git a/Makefile b/Makefile index 265d478734..9fbc1a27ae 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ SOEXT ?= $(shell ruby -e 'puts RbConfig::CONFIG["SOEXT"]') CPPFLAGS := -Iinclude $(CPPFLAGS) CFLAGS := -g -O2 -std=c99 -Wall -Werror -Wextra -Wpedantic -Wundef -Wconversion -Wno-missing-braces -fPIC -fvisibility=hidden -Wimplicit-fallthrough $(CFLAGS) -JAVA_WASM_CFLAGS := -g -Oz -std=c99 -Wall -Werror -Wextra -Wpedantic -Wundef -Wconversion -Wno-missing-braces -fPIC -fvisibility=hidden -Wimplicit-fallthrough $(JAVA_WASM_CFLAGS) +JAVA_WASM_CFLAGS := -g0 -O2 -Oz -std=c99 -Wall -Werror -Wextra -Wpedantic -Wundef -Wconversion -Wno-missing-braces -fno-sanitize=all -fno-stack-protector -fPIC -fvisibility=hidden -Wimplicit-fallthrough $(JAVA_WASM_CFLAGS) CC ?= cc AR ?= ar ARFLAGS ?= -r$(V0:1=v) @@ -45,7 +45,7 @@ javascript/src/prism.wasm: Makefile $(SOURCES) $(HEADERS) $(ECHO) "building $@" $(Q) $(WASI_SDK_PATH)/bin/clang --sysroot=$(WASI_SDK_PATH)/share/wasi-sysroot/ \ $(DEBUG_FLAGS) \ - -DPRISM_EXPORT_SYMBOLS -DPRISM_EXCLUDE_PRETTYPRINT -DPRISM_EXCLUDE_JSON -DPRISM_EXCLUDE_PACK \ + -DPRISM_EXPORT_SYMBOLS -DPRISM_EXCLUDE_PRETTYPRINT -DPRISM_EXCLUDE_JSON \ -D_WASI_EMULATED_MMAN -lwasi-emulated-mman $(CPPFLAGS) $(CFLAGS) \ -Wl,--export-all -Wl,--gc-sections -Wl,--strip-all -Wl,--lto-O3 -Wl,--no-entry -mexec-model=reactor \ -Oz -g0 -flto -fdata-sections -ffunction-sections \ @@ -53,7 +53,13 @@ javascript/src/prism.wasm: Makefile $(SOURCES) $(HEADERS) java-wasm/src/test/resources/prism.wasm: Makefile $(SOURCES) $(HEADERS) $(ECHO) "building $@" - $(Q) $(WASI_SDK_PATH)/bin/clang $(DEBUG_FLAGS) -DPRISM_EXCLUDE_PRETTYPRINT -DPRISM_EXPORT_SYMBOLS -D_WASI_EMULATED_MMAN -lwasi-emulated-mman $(CPPFLAGS) $(JAVA_WASM_CFLAGS) -Wl,--export-all -Wl,--no-entry -mexec-model=reactor -lc++ -lc++abi -o $@ $(SOURCES) + $(Q) $(MAKEDIRS) $(@D) + $(Q) $(WASI_SDK_PATH)/bin/clang \ + $(DEBUG_FLAGS) \ + -DPRISM_EXCLUDE_PRETTYPRINT -DPRISM_EXPORT_SYMBOLS -D_WASI_EMULATED_MMAN \ + -lwasi-emulated-mman $(CPPFLAGS) $(JAVA_WASM_CFLAGS) \ + -Wl,--export-all -Wl,--no-entry -mexec-model=reactor -lc++ -lc++abi \ + -o $@ $(SOURCES) build/shared/%.o: src/%.c Makefile $(HEADERS) $(ECHO) "compiling $@" diff --git a/Rakefile b/Rakefile index b06877107e..80b00bd913 100644 --- a/Rakefile +++ b/Rakefile @@ -45,8 +45,7 @@ elsif RUBY_ENGINE == "jruby" ext.name = "prism" ext.ext_dir = "java" ext.lib_dir = "tmp" - ext.source_version = "1.8" - ext.target_version = "1.8" + ext.release = "21" ext.gem_spec = Gem::Specification.load("prism.gemspec") end end @@ -55,6 +54,7 @@ end CLOBBER.concat(Prism::Template::TEMPLATES) CLOBBER.concat(["build"]) CLOBBER << "lib/prism/prism.#{RbConfig::CONFIG["DLEXT"]}" +CLOBBER << "java-wasm/src/main/resources/prism.wasm" Prism::Template::TEMPLATES.each do |filepath| desc "Generate #{filepath}" diff --git a/Steepfile b/Steepfile index 433e53cd29..e6e1a8efb5 100644 --- a/Steepfile +++ b/Steepfile @@ -1,21 +1,18 @@ # frozen_string_literal: true target :lib do + check "lib" signature "sig" - library "cgi" # in lib/prism/dot_visitor.rb (Prism::DotVisitor) - - check "lib" + library "cgi" + library "pp" - # TODO: Type-checking these files is still WIP - ignore "lib/prism/desugar_compiler.rb" - ignore "lib/prism/lex_compat.rb" - ignore "lib/prism/serialize.rb" - ignore "lib/prism/ffi.rb" + # Ignored because it requires other libraries. ignore "lib/prism/translation" - ignore "lib/prism/polyfill/append_as_bytes.rb" - ignore "lib/prism/polyfill/byteindex.rb" - ignore "lib/prism/polyfill/scan_byte.rb" - ignore "lib/prism/polyfill/unpack1.rb" + # Ignored because they are only for older Rubies. + ignore "lib/prism/polyfill" + + # Ignored because we do not want to overlap with the C extension. + ignore "lib/prism/ffi.rb" end diff --git a/bin/mcp b/bin/mcp new file mode 100755 index 0000000000..1833d2f70b --- /dev/null +++ b/bin/mcp @@ -0,0 +1,188 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# This script is a server that can be run on your local machine, typically given +# to an LLM to reduce token usage and standardize interactions. It listens for +# JSON-RPC requests on stdin, processes them using the defined tools, and writes +# responses to stdout. +# +# To test out the server locally, it is easiest to pipe requests directly into +# stdin and then format JSON responses with a tool like `jq` for readability. +# Here are some example requests you can make to the server: +# +# echo '{"jsonrpc":"2.0","id":"1","method":"ping"}' | bin/mcp | jq +# echo '{"jsonrpc":"2.0","id":"2","method":"tools/list"}' | bin/mcp | jq +# echo '{"jsonrpc":"2.0","id":"1","method":"tools/call","params":{"name":"rake","arguments":{"target":"compile"}}}' | bin/mcp | jq +# echo '{"jsonrpc":"2.0","id":"1","method":"tools/call","params":{"name":"c_function","arguments":{"filepath":"src/prism.c","function_name":"pm_parser_init"}}}' | bin/mcp | jq +# echo '{"jsonrpc":"2.0","id":"1","method":"tools/call","params":{"name":"ruby_method","arguments":{"filepath":"lib/prism.rb","method_name":"load"}}}' | bin/mcp | jq +# + +def silence_output + original_stdout = $stdout.dup + original_stderr = $stderr.dup + + File.open(File::NULL, "w") do |null| + $stdout.reopen(null) + $stderr.reopen(null) + yield + end +ensure + $stdout.reopen(original_stdout) + $stderr.reopen(original_stderr) +end + +require "bundler/inline" +gemfile do + source "https://rubygems.org" + gem "mcp" + gem "open3" + gem "prism", path: File.expand_path("..", __dir__) + + silence_output do + gem "ffi-clang" + require "ffi/clang" + end +end + +class RakeTool < MCP::Tool + tool_name "rake" + description "Run rake on a specific target." + + input_schema( + properties: { + target: { type: "string", enum: ["clean", "compile", "test"], description: "The rake target to build." } + }, + required: ["target"] + ) + output_schema( + properties: { + success: { type: "boolean" }, + stderr: { type: "string" } + }, + required: ["success"] + ) + + def self.call(server_context:, target:) + _, stderr, status = + Dir.chdir(File.expand_path("..", __dir__)) do + Open3.capture3("bundle", "exec", "rake", target) + end + + result = + if status.success? + { success: true } + else + { success: false, stderr: stderr.strip } + end + + output_schema.validate_result(result) + MCP::Tool::Response.new([{ type: "text", text: result.to_json }], structured_content: result) + end +end + +class CFunctionTool < MCP::Tool + tool_name "c_function" + description "Extracts a C function from a source file." + + input_schema( + properties: { + filepath: { type: "string", description: "Path to the C source file." }, + function_name: { type: "string", description: "The name of the function to extract." } + }, + required: ["filepath", "function_name"] + ) + output_schema( + properties: { + body: { type: "string" } + }, + required: ["body"] + ) + + class << self + def call(server_context:, filepath:, function_name:) + if !File.readable?(filepath) + MCP::Tool::Response.new([MCP::Content::Text.new("Invalid filepath").to_h], error: true) + elsif !(body = find(filepath, function_name)) + MCP::Tool::Response.new([MCP::Content::Text.new("Function not found").to_h], error: true) + else + result = { body: body } + output_schema.validate_result(result) + + MCP::Tool::Response.new([{ type: "text", text: result.to_json }], structured_content: result) + end + end + + private + + def extract(cursor) + location = cursor.definition.location + return unless (filepath = location.file) + + extent = cursor.extent + start_offset = extent.start.offset + File.open(filepath, "rb") do |file| + file.pread(extent.end.offset - start_offset, start_offset) + end + end + + def find(filepath, function_name) + translation_unit = FFI::Clang::Index.new.parse_translation_unit(filepath) + translation_unit.cursor.find { |cursor, _| break extract(cursor) if cursor.declaration? && cursor.spelling == function_name } + end + end +end + +class RubyMethodTool < MCP::Tool + tool_name "ruby_method" + description "Extracts a Ruby method from a source file." + + input_schema( + properties: { + filepath: { type: "string", description: "Path to the Ruby source file." }, + method_name: { type: "string", description: "The name of the method to extract." } + }, + required: ["filepath", "method_name"] + ) + output_schema( + properties: { + body: { type: "string" } + }, + required: ["body"] + ) + + class << self + def call(server_context:, filepath:, method_name:) + if !File.readable?(filepath) + MCP::Tool::Response.new([MCP::Content::Text.new("Invalid filepath").to_h], error: true) + elsif !(result = Prism.parse_file(filepath)).success? + MCP::Tool::Response.new([MCP::Content::Text.new("Failed to parse file").to_h], error: true) + elsif !(body = find(result.value, method_name)) + MCP::Tool::Response.new([MCP::Content::Text.new("Method not found").to_h], error: true) + else + result = { body: body } + output_schema.validate_result(result) + + MCP::Tool::Response.new([{ type: "text", text: result.to_json }], structured_content: result) + end + end + + private + + def find(node, method_name) + name = method_name.to_sym + node.breadth_first_search do |child| + break child.slice if child.is_a?(Prism::DefNode) && child.name == name + end + end + end +end + +tools = [ + RakeTool, + CFunctionTool, + RubyMethodTool +] + +server = MCP::Server.new(name: "Prism", tools: tools) +transport = MCP::Server::Transports::StdioTransport.new(server) +transport.open diff --git a/bin/prism b/bin/prism index dbd0ddb174..43bdea1f36 100755 --- a/bin/prism +++ b/bin/prism @@ -8,7 +8,7 @@ module Prism class CLI def run(argv) case argv.shift - when "benchmark" then benchmark(argv) + when "bench" then bench(argv) when "bundle" then bundle(argv) when "console" then console when "dot" then dot(argv) @@ -25,7 +25,7 @@ module Prism else puts <<~TXT Usage: - bin/prism benchmark [source_file] + bin/prism bench [file ...] bin/prism bundle [...] bin/prism console bin/prism dot [source] @@ -49,46 +49,34 @@ module Prism # Commands ############################################################################ - # bin/prism benchmark [source_file] - def benchmark(argv) + # bin/prism bench [file ...] + # Measures raw parse throughput using Prism.profile (no Ruby AST creation). + def bench(argv) require "benchmark/ips" - require "parser/current" - require "ripper" - require "ruby_parser" - - filepath = argv.fetch(0) { File.expand_path("../lib/prism/node.rb", __dir__) } - source = File.read(filepath) - - Benchmark.ips do |x| - x.report("Prism") do - Prism.parse(source, filepath: filepath) - end - - x.report("Ripper::SexpBuilder") do - Ripper.sexp_raw(source, filepath) - end - x.report("Prism::Translation::Ripper::SexpBuilder") do - Prism::Translation::Ripper.sexp_raw(source, filepath) + files = + if argv.any? + argv.map { |path| [path, File.read(path)] } + else + Dir[File.join(__dir__, "../test/prism/fixtures/**/*.txt")].sort.map { |path| [path, File.read(path)] } + + Dir[File.join(__dir__, "../lib/**/*.rb")].sort.map { |path| [path, File.read(path)] } end - x.report("Parser::CurrentRuby") do - Parser::CurrentRuby.parse(source, filepath) - end + total_bytes = files.sum { |_, source| source.bytesize } + puts "Benchmarking #{files.size} files (#{total_bytes} bytes total)" + puts - x.report("Prism::Translation::Parser") do - Prism::Translation::Parser.parse(source, filepath) - end + Benchmark.ips do |x| + x.time = 10 + x.warmup = 3 - x.report("RubyParser") do - RubyParser.new.parse(source, filepath) + x.report("parse (all files)") do + files.each { |_, source| Prism.profile(source) } end - x.report("Prism::Translation::RubyParser") do - Prism::Translation::RubyParser.new.parse(source, filepath) + x.report("parse (fixtures only)") do + files.each { |path, source| Prism.profile(source) if path.end_with?(".txt") } end - - x.compare! end end @@ -166,7 +154,6 @@ module Prism source, filepath = read_source(argv) result = Prism.parse(source) - if result.errors.any? puts result.errors_format else @@ -270,17 +257,17 @@ module Prism # bin/prism parser [source] def parser(argv) - require "parser/ruby34" + require "parser/current" source, filepath = read_source(argv) buffer = Parser::Source::Buffer.new(filepath, 1) buffer.source = source puts "Parser:" - parser_parse(Parser::Ruby34.new, buffer) + parser_parse(Parser::CurrentRuby.new, buffer) puts "Prism:" - parser_parse(Prism::Translation::Parser34.new, buffer) + parser_parse(Prism::Translation::ParserCurrent.new, buffer) end # bin/prism ripper [source] diff --git a/config.yml b/config.yml index 4e1560481e..1ea1bcf7f1 100644 --- a/config.yml +++ b/config.yml @@ -17,6 +17,8 @@ errors: - ARGUMENT_FORWARDING_UNBOUND - ARGUMENT_NO_FORWARDING_AMPERSAND - ARGUMENT_NO_FORWARDING_ELLIPSES + - ARGUMENT_NO_FORWARDING_ELLIPSES_LAMBDA + - ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK - ARGUMENT_NO_FORWARDING_STAR - ARGUMENT_NO_FORWARDING_STAR_STAR - ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT @@ -62,6 +64,7 @@ errors: - DEF_ENDLESS - DEF_ENDLESS_PARAMETERS - DEF_ENDLESS_SETTER + - DEF_ENDLESS_DO_BLOCK - DEF_NAME - DEF_PARAMS_TERM - DEF_PARAMS_TERM_PAREN @@ -245,7 +248,9 @@ errors: - PATTERN_TERM_PAREN - PIPEPIPEEQ_MULTI_ASSIGN - REGEXP_ENCODING_OPTION_MISMATCH + - REGEXP_ESCAPED_NON_ASCII_IN_UTF8 - REGEXP_INCOMPAT_CHAR_ENCODING + - REGEXP_INVALID_CHAR_PROPERTY - REGEXP_INVALID_UNICODE_RANGE - REGEXP_NON_ESCAPED_MBC - REGEXP_PARSE_ERROR @@ -491,6 +496,8 @@ tokens: comment: "def" - name: KEYWORD_DEFINED comment: "defined?" + - name: KEYWORD_DO_BLOCK + comment: "do keyword for a block attached to a command" - name: KEYWORD_DO_LOOP comment: "do keyword for a predicate in a while, until, or for loop" - name: KEYWORD_END_UPCASE @@ -817,7 +824,7 @@ nodes: - name: keyword_loc type: location comment: | - The location of the `alias` keyword. + The Location of the `alias` keyword. alias $foo $bar ^^^^^ @@ -865,7 +872,7 @@ nodes: - name: keyword_loc type: location comment: | - Represents the location of the `alias` keyword. + Represents the Location of the `alias` keyword. alias foo bar ^^^^^ @@ -895,7 +902,7 @@ nodes: - name: operator_loc type: location comment: | - Represents the alternation operator location. + Represents the alternation operator Location. foo => bar | baz ^ @@ -931,7 +938,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `and` keyword or the `&&` operator. + The Location of the `and` keyword or the `&&` operator. left and right ^^^ @@ -966,7 +973,7 @@ nodes: - name: opening_loc type: location? comment: | - Represents the optional source location for the opening token. + Represents the optional source Location for the opening token. [1,2,3] # "[" %w[foo bar baz] # "%w[" @@ -975,7 +982,7 @@ nodes: - name: closing_loc type: location? comment: | - Represents the optional source location for the closing token. + Represents the optional source Location for the closing token. [1,2,3] # "]" %w[foo bar baz] # "]" @@ -1031,14 +1038,14 @@ nodes: - name: opening_loc type: location? comment: | - Represents the opening location of the array pattern. + Represents the opening Location of the array pattern. foo in [1, 2] ^ - name: closing_loc type: location? comment: | - Represents the closing location of the array pattern. + Represents the closing Location of the array pattern. foo in [1, 2] ^ @@ -1046,19 +1053,19 @@ nodes: Represents an array pattern in pattern matching. foo in 1, 2 - ^^^^^^^^^^^ + ^^^^ foo in [1, 2] - ^^^^^^^^^^^^^ + ^^^^^^ foo in *bar - ^^^^^^^^^^^ + ^^^^ foo in Bar[] - ^^^^^^^^^^^^ + ^^^^^ foo in Bar[1, 2, 3] - ^^^^^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^ - name: AssocNode fields: - name: key @@ -1089,7 +1096,7 @@ nodes: - name: operator_loc type: location? comment: | - The location of the `=>` operator, if present. + The Location of the `=>` operator, if present. { foo => bar } ^^ @@ -1111,7 +1118,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `**` operator. + The Location of the `**` operator. { **x } ^^ @@ -1140,7 +1147,7 @@ nodes: - name: begin_keyword_loc type: location? comment: | - Represents the location of the `begin` keyword. + Represents the Location of the `begin` keyword. begin x end ^^^^^ @@ -1167,7 +1174,7 @@ nodes: Represents the else clause within the begin block. begin x; rescue y; else z; end - ^^^^^^ + ^^^^^^^^^^^ - name: ensure_clause type: node? kind: EnsureNode @@ -1179,7 +1186,7 @@ nodes: - name: end_keyword_loc type: location? comment: | - Represents the location of the `end` keyword. + Represents the Location of the `end` keyword. begin x end ^^^ @@ -1200,11 +1207,11 @@ nodes: The expression that is being passed as a block argument. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). foo(&args) - ^^^^^ + ^^^^ - name: operator_loc type: location comment: | - Represents the location of the `&` operator. + Represents the Location of the `&` operator. foo(&args) ^ @@ -1212,7 +1219,7 @@ nodes: Represents a block argument using `&`. bar(&args) - ^^^^^^^^^^ + ^^^^^ - name: BlockLocalVariableNode flags: ParameterFlags fields: @@ -1265,14 +1272,14 @@ nodes: - name: opening_loc type: location comment: | - Represents the location of the opening `{` or `do`. + Represents the Location of the opening `{` or `do`. [1, 2, 3].each { |i| puts x } ^ - name: closing_loc type: location comment: | - Represents the location of the closing `}` or `end`. + Represents the Location of the closing `}` or `end`. [1, 2, 3].each { |i| puts x } ^ @@ -1295,14 +1302,14 @@ nodes: - name: name_loc type: location? comment: | - Represents the location of the block parameter name. + Represents the Location of the block parameter name. def a(&b) ^ - name: operator_loc type: location comment: | - Represents the location of the `&` operator. + Represents the Location of the `&` operator. def a(&b) ^ @@ -1342,7 +1349,7 @@ nodes: - name: opening_loc type: location? comment: | - Represents the opening location of the block parameters. + Represents the opening Location of the block parameters. -> (a, b = 1; local) { } ^ @@ -1353,7 +1360,7 @@ nodes: - name: closing_loc type: location? comment: | - Represents the closing location of the block parameters. + Represents the closing Location of the block parameters. -> (a, b = 1; local) { } ^ @@ -1383,7 +1390,7 @@ nodes: - name: keyword_loc type: location comment: | - The location of the `break` keyword. + The Location of the `break` keyword. break foo ^^^^^ @@ -1406,14 +1413,14 @@ nodes: - name: call_operator_loc type: location? comment: | - Represents the location of the call operator. + Represents the Location of the call operator. foo.bar &&= value ^ - name: message_loc type: location? comment: | - Represents the location of the message. + Represents the Location of the message. foo.bar &&= value ^^^ @@ -1434,7 +1441,7 @@ nodes: - name: operator_loc type: location comment: | - Represents the location of the operator. + Represents the Location of the operator. foo.bar &&= value ^^^ @@ -1471,7 +1478,7 @@ nodes: - name: call_operator_loc type: location? comment: | - Represents the location of the call operator. + Represents the Location of the call operator. foo.bar ^ @@ -1488,14 +1495,15 @@ nodes: - name: message_loc type: location? comment: | - Represents the location of the message. + Represents the Location of the message. foo.bar ^^^ - name: opening_loc type: location? comment: | - Represents the location of the left parenthesis. + Represents the Location of the left parenthesis. + foo(bar) ^ - name: arguments @@ -1509,14 +1517,14 @@ nodes: - name: closing_loc type: location? comment: | - Represents the location of the right parenthesis. + Represents the Location of the right parenthesis. foo(bar) ^ - name: equal_loc type: location? comment: | - Represents the location of the equal sign, in the case that this is an attribute write. + Represents the Location of the equal sign, in the case that this is an attribute write. foo.bar = value ^ @@ -1567,14 +1575,14 @@ nodes: - name: call_operator_loc type: location? comment: | - Represents the location of the call operator. + Represents the Location of the call operator. foo.bar += value ^ - name: message_loc type: location? comment: | - Represents the location of the message. + Represents the Location of the message. foo.bar += value ^^^ @@ -1602,7 +1610,7 @@ nodes: - name: binary_operator_loc type: location comment: | - Represents the location of the binary operator. + Represents the Location of the binary operator. foo.bar += value ^^ @@ -1633,14 +1641,14 @@ nodes: - name: call_operator_loc type: location? comment: | - Represents the location of the call operator. + Represents the Location of the call operator. foo.bar ||= value ^ - name: message_loc type: location? comment: | - Represents the location of the message. + Represents the Location of the message. foo.bar ||= value ^^^ @@ -1661,7 +1669,7 @@ nodes: - name: operator_loc type: location comment: | - Represents the location of the operator. + Represents the Location of the operator. foo.bar ||= value ^^^ @@ -1692,7 +1700,7 @@ nodes: - name: call_operator_loc type: location comment: | - Represents the location of the call operator. + Represents the Location of the call operator. foo.bar = 1 ^ @@ -1706,7 +1714,7 @@ nodes: - name: message_loc type: location comment: | - Represents the location of the message. + Represents the Location of the message. foo.bar = 1 ^^^ @@ -1744,7 +1752,7 @@ nodes: - name: operator_loc type: location comment: | - Represents the location of the `=>` operator. + Represents the Location of the `=>` operator. foo => bar ^^ @@ -1752,7 +1760,7 @@ nodes: Represents assigning to a local variable in pattern matching. foo => [bar => baz] - ^^^^^^^^^^^^ + ^^^^^^^^^^ - name: CaseMatchNode fields: - name: predicate @@ -1762,7 +1770,7 @@ nodes: Represents the predicate of the case match. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). case true; in false; end - ^^^^ + ^^^^ - name: conditions type: node[] kind: InNode @@ -1778,18 +1786,18 @@ nodes: Represents the else clause of the case match. case true; in false; else; end - ^^^^ + ^^^^^^^^^ - name: case_keyword_loc type: location comment: | - Represents the location of the `case` keyword. + Represents the Location of the `case` keyword. case true; in false; end ^^^^ - name: end_keyword_loc type: location comment: | - Represents the location of the `end` keyword. + Represents the Location of the `end` keyword. case true; in false; end ^^^ @@ -1825,18 +1833,18 @@ nodes: Represents the else clause of the case statement. case true; when false; else; end - ^^^^ + ^^^^^^^^^ - name: case_keyword_loc type: location comment: | - Represents the location of the `case` keyword. + Represents the Location of the `case` keyword. case true; when false; end ^^^^ - name: end_keyword_loc type: location comment: | - Represents the location of the `end` keyword. + Represents the Location of the `end` keyword. case true; when false; end ^^^ @@ -1854,7 +1862,7 @@ nodes: - name: class_keyword_loc type: location comment: | - Represents the location of the `class` keyword. + Represents the Location of the `class` keyword. class Foo end ^^^^^ @@ -1867,7 +1875,7 @@ nodes: - name: inheritance_operator_loc type: location? comment: | - Represents the location of the `<` operator. + Represents the Location of the `<` operator. class Foo < Bar ^ @@ -1887,13 +1895,12 @@ nodes: comment: | Represents the body of the class. - class Foo - foo - ^^^ + class Foo; bar; end + ^^^ - name: end_keyword_loc type: location comment: | - Represents the location of the `end` keyword. + Represents the Location of the `end` keyword. class Foo end ^^^ @@ -1920,14 +1927,14 @@ nodes: - name: name_loc type: location comment: | - Represents the location of the variable name. + Represents the Location of the variable name. @@target &&= value ^^^^^^^^ - name: operator_loc type: location comment: | - Represents the location of the `&&=` operator. + Represents the Location of the `&&=` operator. @@target &&= value ^^^ @@ -2015,7 +2022,7 @@ nodes: - name: name_loc type: location comment: | - The location of the variable name. + The Location of the variable name. @@foo = :bar ^^^^^ @@ -2033,7 +2040,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `=` operator. + The Location of the `=` operator. @@foo = :bar ^ @@ -2129,7 +2136,7 @@ nodes: - name: delimiter_loc type: location comment: | - The location of the `::` delimiter. + The Location of the `::` delimiter. ::Foo ^^ @@ -2139,7 +2146,7 @@ nodes: - name: name_loc type: location comment: | - The location of the name of the constant. + The Location of the name of the constant. ::Foo ^^^ @@ -2215,7 +2222,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `=` operator. + The Location of the `=` operator. ::ABC = 123 ^ @@ -2275,7 +2282,7 @@ nodes: - name: name_loc type: location comment: | - The location of the constant name. + The Location of the constant name. FOO = 1 ^^^ @@ -2293,7 +2300,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `=` operator. + The Location of the `=` operator. FOO = :bar ^ @@ -2474,7 +2481,7 @@ nodes: - name: opening_loc type: location? comment: | - The location of the opening brace. + The Location of the opening brace. foo in [*bar, baz, *qux] ^ @@ -2484,7 +2491,7 @@ nodes: - name: closing_loc type: location? comment: | - The location of the closing brace. + The Location of the closing brace. foo in [*bar, baz, *qux] ^ @@ -2574,28 +2581,28 @@ nodes: - name: for_keyword_loc type: location comment: | - The location of the `for` keyword. + The Location of the `for` keyword. for i in a end ^^^ - name: in_keyword_loc type: location comment: | - The location of the `in` keyword. + 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. + 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. + The Location of the `end` keyword. for i in a end ^^^ @@ -2723,7 +2730,7 @@ nodes: - name: name_loc type: location comment: | - The location of the global variable's name. + The Location of the global variable's name. $foo = :bar ^^^^ @@ -2741,7 +2748,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `=` operator. + The Location of the `=` operator. $foo = :bar ^ @@ -2755,7 +2762,7 @@ nodes: - name: opening_loc type: location comment: | - The location of the opening brace. + The Location of the opening brace. { a => b } ^ @@ -2775,7 +2782,7 @@ nodes: - name: closing_loc type: location comment: | - The location of the closing brace. + The Location of the closing brace. { a => b } ^ @@ -2826,7 +2833,7 @@ nodes: - name: opening_loc type: location? comment: | - The location of the opening brace. + The Location of the opening brace. foo => { a: 1 } ^ @@ -2836,7 +2843,7 @@ nodes: - name: closing_loc type: location? comment: | - The location of the closing brace. + The Location of the closing brace. foo => { a: 1 } ^ @@ -2862,7 +2869,7 @@ nodes: - name: if_keyword_loc type: location? comment: | - The location of the `if` keyword if present. + The Location of the `if` keyword if present. bar if foo ^^ @@ -2887,7 +2894,7 @@ nodes: - name: then_keyword_loc type: location? comment: | - The location of the `then` keyword (if present) or the `?` in a ternary expression, `nil` otherwise. + The Location of the `then` keyword (if present) or the `?` in a ternary expression, `nil` otherwise. if foo then bar end ^^^^ @@ -2928,7 +2935,7 @@ nodes: - name: end_keyword_loc type: location? comment: | - The location of the `end` keyword if present, `nil` otherwise. + The Location of the `end` keyword if present, `nil` otherwise. if foo bar @@ -3213,7 +3220,7 @@ nodes: - name: name_loc type: location comment: | - The location of the variable name. + The Location of the variable name. @_x = 1 ^^^ @@ -3231,7 +3238,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `=` operator. + The Location of the `=` operator. @x = y ^ @@ -3538,7 +3545,7 @@ nodes: - name: name_loc type: location comment: | - The location of the variable name. + The Location of the variable name. foo = :bar ^^^ @@ -3560,7 +3567,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `=` operator. + The Location of the `=` operator. x = :y ^ @@ -3660,7 +3667,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the operator. + The Location of the operator. foo => bar ^^ @@ -3781,14 +3788,14 @@ nodes: - name: lparen_loc type: location? comment: | - The location of the opening parenthesis. + The Location of the opening parenthesis. a, (b, c) = 1, 2, 3 ^ - name: rparen_loc type: location? comment: | - The location of the closing parenthesis. + The Location of the closing parenthesis. a, (b, c) = 1, 2, 3 ^ @@ -3870,21 +3877,21 @@ nodes: - name: lparen_loc type: location? comment: | - The location of the opening parenthesis. + The Location of the opening parenthesis. (a, b, c) = 1, 2, 3 ^ - name: rparen_loc type: location? comment: | - The location of the closing parenthesis. + The Location of the closing parenthesis. (a, b, c) = 1, 2, 3 ^ - name: operator_loc type: location comment: | - The location of the operator. + The Location of the operator. a, b, c = 1, 2, 3 ^ @@ -3919,6 +3926,18 @@ nodes: nil ^^^ + - name: NoBlockParameterNode + fields: + - name: operator_loc + type: location + - name: keyword_loc + type: location + comment: | + Represents the use of `&nil` inside method arguments. + + def a(&nil) + ^^^^ + end - name: NoKeywordsParameterNode fields: - name: operator_loc @@ -4018,7 +4037,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `or` keyword or the `||` operator. + The Location of the `or` keyword or the `||` operator. left or right ^^ @@ -4052,6 +4071,9 @@ nodes: - on error: NoKeywordsParameterNode # On parsing error of `f(..., ...)`, the first forwarding parameter is moved here: - on error: ForwardingParameterNode + # On parsing error of `f(&nil, &foo)`/`f(&foo, &nil)`, the first forwarding parameter is moved here: + - on error: BlockParameterNode + - on error: NoBlockParameterNode - name: keywords type: node[] kind: @@ -4065,7 +4087,9 @@ nodes: - NoKeywordsParameterNode - name: block type: node? - kind: BlockParameterNode + kind: + - BlockParameterNode + - NoBlockParameterNode comment: | Represents the list of parameters on a method, block, or lambda definition. @@ -4101,21 +4125,21 @@ nodes: - name: operator_loc type: location comment: | - The location of the `^` operator + The Location of the `^` operator foo in ^(bar) ^ - name: lparen_loc type: location comment: | - The location of the opening parenthesis. + The Location of the opening parenthesis. foo in ^(bar) ^ - name: rparen_loc type: location comment: | - The location of the closing parenthesis. + The Location of the closing parenthesis. foo in ^(bar) ^ @@ -4145,7 +4169,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `^` operator + The Location of the `^` operator foo in ^bar ^ @@ -4223,7 +4247,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `..` or `...` operator. + The Location of the `..` or `...` operator. comment: | Represents the use of the `..` or `...` operators. @@ -4449,7 +4473,7 @@ nodes: fields: - 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. + comment: Represents the file path being parsed. This corresponds directly to the `filepath` option given to the various `Prism.parse*` APIs. comment: | Represents the use of the `__FILE__` keyword. @@ -4576,7 +4600,7 @@ nodes: - name: keyword_loc type: location comment: | - The location of the `unless` keyword. + The Location of the `unless` keyword. unless cond then bar end ^^^^^^ @@ -4597,7 +4621,7 @@ nodes: - name: then_keyword_loc type: location? comment: | - The location of the `then` keyword, if present. + The Location of the `then` keyword, if present. unless cond then bar end ^^^^ @@ -4617,11 +4641,11 @@ nodes: The else clause of the unless expression, if present. unless cond then bar else baz end - ^^^^^^^^ + ^^^^^^^^^^^^ - name: end_keyword_loc type: location? comment: | - The location of the `end` keyword, if present. + The Location of the `end` keyword, if present. unless cond then bar end ^^^ diff --git a/cpp/test.cpp b/cpp/test.cpp index af993c9fca..3e41b270e9 100644 --- a/cpp/test.cpp +++ b/cpp/test.cpp @@ -5,8 +5,9 @@ extern "C" { #include int main() { + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, reinterpret_cast("1 + 2"), 5, NULL); + pm_parser_init(&arena, &parser, reinterpret_cast("1 + 2"), 5, NULL); pm_node_t *root = pm_parse(&parser); pm_buffer_t buffer = { 0 }; @@ -17,8 +18,8 @@ int main() { std::cout << buffer.value << std::endl; pm_buffer_free(&buffer); - pm_node_destroy(&parser, root); pm_parser_free(&parser); + pm_arena_free(&arena); return 0; } diff --git a/docs/build_system.md b/docs/build_system.md index 3595c69741..096edb8ad0 100644 --- a/docs/build_system.md +++ b/docs/build_system.md @@ -113,7 +113,6 @@ MAKEFLAGS="-j10" bundle exec rake compile * `PRISM_ENCODING_EXCLUDE_FULL` - Will cause the library to exclude the full encoding API, and only include the minimal number of encodings to support parsing Ruby code without encoding comments. By default this is off. * `PRISM_EXPORT_SYMBOLS` - Will cause the shared library to export symbols. By default this is off. * `PRISM_EXCLUDE_JSON` - Will cause the library to exclude the JSON API. By default this is off. -* `PRISM_EXCLUDE_PACK` - Will cause the library to exclude the pack API. By default this is off. * `PRISM_EXCLUDE_PRETTYPRINT` - Will cause the library to exclude the prettyprint API. By default this is off. * `PRISM_EXCLUDE_SERIALIZATION` - Will cause the library to exclude the serialization API. By default this is off. * `PRISM_XALLOCATOR` - Will cause the library to use the custom memory allocator. By default this is off. diff --git a/docs/configuration.md b/docs/configuration.md index 04887d6d9c..30001b7db7 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -5,11 +5,12 @@ A lot of code in prism's repository is templated from a single configuration fil * `ext/prism/api_node.c` - for defining how to build Ruby objects for the nodes out of C structs * `include/prism/ast.h` - for defining the C structs that represent the nodes * `include/prism/diagnostic.h` - for defining the diagnostics +* `include/prism/node_new.h` - for defining the functions that create the nodes in C * `javascript/src/deserialize.js` - for defining how to deserialize the nodes in JavaScript * `javascript/src/nodes.js` - for defining the nodes in JavaScript -* `java/org/prism/AbstractNodeVisitor.java` - for defining the visitor interface for the nodes in Java -* `java/org/prism/Loader.java` - for defining how to deserialize the nodes in Java -* `java/org/prism/Nodes.java` - for defining the nodes in Java +* `java/org/ruby_lang/prism/AbstractNodeVisitor.java` - for defining the visitor interface for the nodes in Java +* `java/org/ruby_lang/prism/Loader.java` - for defining how to deserialize the nodes in Java +* `java/org/ruby_lang/prism/Nodes.java` - for defining the nodes in Java * `lib/prism/compiler.rb` - for defining the compiler for the nodes in Ruby * `lib/prism/dispatcher.rb` - for defining the dispatch visitors for the nodes in Ruby * `lib/prism/dot_visitor.rb` - for defining the dot visitor for the nodes in Ruby diff --git a/docs/releasing.md b/docs/releasing.md index a7d3cf5eb3..6d0f892926 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -23,9 +23,9 @@ ruby -pi -e 'gsub(/PRISM_VERSION_PATCH \d+/, %Q{PRISM_VERSION_PATCH #{ENV["PRISM ruby -pi -e 'gsub(/PRISM_VERSION ".+?"/, %Q{PRISM_VERSION "#{ENV["PRISM_VERSION"]}"})' include/prism/version.h ruby -pi -e 'gsub(/"version": ".+?"/, %Q{"version": "#{ENV["PRISM_VERSION"]}"})' javascript/package.json ruby -pi -e 'gsub(/lossy\(\), ".+?"/, %Q{lossy(), "#{ENV["PRISM_VERSION"]}"})' rust/ruby-prism-sys/tests/utils_tests.rs -ruby -pi -e 'gsub(/\d+, "prism major/, %Q{#{ENV["PRISM_MAJOR"]}, "prism major})' templates/java/org/prism/Loader.java.erb -ruby -pi -e 'gsub(/\d+, "prism minor/, %Q{#{ENV["PRISM_MINOR"]}, "prism minor})' templates/java/org/prism/Loader.java.erb -ruby -pi -e 'gsub(/\d+, "prism patch/, %Q{#{ENV["PRISM_PATCH"]}, "prism patch})' templates/java/org/prism/Loader.java.erb +ruby -pi -e 'gsub(/\d+, "prism major/, %Q{#{ENV["PRISM_MAJOR"]}, "prism major})' templates/java/org/ruby_lang/prism/Loader.java.erb +ruby -pi -e 'gsub(/\d+, "prism minor/, %Q{#{ENV["PRISM_MINOR"]}, "prism minor})' templates/java/org/ruby_lang/prism/Loader.java.erb +ruby -pi -e 'gsub(/\d+, "prism patch/, %Q{#{ENV["PRISM_PATCH"]}, "prism patch})' templates/java/org/ruby_lang/prism/Loader.java.erb ruby -pi -e 'gsub(/MAJOR_VERSION = \d+/, %Q{MAJOR_VERSION = #{ENV["PRISM_MAJOR"]}})' templates/javascript/src/deserialize.js.erb ruby -pi -e 'gsub(/MINOR_VERSION = \d+/, %Q{MINOR_VERSION = #{ENV["PRISM_MINOR"]}})' templates/javascript/src/deserialize.js.erb ruby -pi -e 'gsub(/PATCH_VERSION = \d+/, %Q{PATCH_VERSION = #{ENV["PRISM_PATCH"]}})' templates/javascript/src/deserialize.js.erb diff --git a/docs/serialization.md b/docs/serialization.md index ec395f8847..a7ba533566 100644 --- a/docs/serialization.md +++ b/docs/serialization.md @@ -106,6 +106,7 @@ The header is structured like the following table: | error* | errors | | varuint | number of warnings | | warning* | warnings | +| `1` | `1` if the source is continuable (incomplete but could become valid with more input), `0` otherwise | | `4` | content pool offset | | varuint | content pool size | @@ -126,7 +127,7 @@ Every field on the node is then appended to the serialized string. The fields ca * `node` - A field that is a node. This is structured just as like parent node. * `node?` - A field that is a node that is optionally present. If the node is not present, then a single `0` byte will be written in its place. If it is present, then it will be structured just as like parent node. * `node[]` - A field that is an array of nodes. This is structured as a variable-length integer length, followed by the child nodes themselves. -* `string` - A field that is a string. For example, this is used as the name of the method in a call node, since it cannot directly reference the source string (as in `@-` or `foo=`). This is structured as a variable-length integer byte length, followed by the string itself (_without_ a trailing null byte). +* `string` - A field that is a string. For example, this is used as the name of the method in a call node, since it cannot directly reference the source string (as in `@-` or `foo=`). This is structured as a variable-length integer byte length, followed by the string bytes (_without_ a trailing null byte). * `constant` - A variable-length integer that represents an index in the constant pool. * `constant?` - An optional variable-length integer that represents an index in the constant pool. If it's not present, then a single `0` byte will be written in its place. * `integer` - A field that represents an arbitrary-sized integer. The structure is listed above. @@ -135,23 +136,14 @@ Every field on the node is then appended to the serialized string. The fields ca * `uint8` - A field that is an 8-bit unsigned integer. This is structured as a single byte. * `uint32` - A field that is a 32-bit unsigned integer. This is structured as a variable-length integer. -After the syntax tree, the content pool is serialized. This is a list of constants that were referenced from within the tree. The content pool begins at the offset specified in the header. Constants can be either "owned" (in which case their contents are embedded in the serialization) or "shared" (in which case their contents represent a slice of the source string). The most significant bit of the constant indicates whether it is owned or shared. - -In the case that it is owned, the constant is structured as follows: +After the syntax tree, the content pool is serialized. This is a list of constants that were referenced from within the tree. The content pool begins at the offset specified in the header. Every constant is embedded in the serialization. Each constant is structured as follows: | # bytes | field | | --- | --- | | `4` | the byte offset in the serialization for the contents of the constant | | `4` | the byte length in the serialization | -Note that you will need to mask off the most significant bit for the byte offset in the serialization. In the case that it is shared, the constant is structured as follows: - -| # bytes | field | -| --- | --- | -| `4` | the byte offset in the source string for the contents of the constant | -| `4` | the byte length in the source string | - -After the constant pool, the contents of the owned constants are serialized. This is just a sequence of bytes that represent the contents of the constants. At the end of the serialization, the buffer is null terminated. +After the constant pool, the contents of the constants are serialized. This is just a sequence of bytes that represent the contents of the constants. At the end of the serialization, the buffer is null terminated. ## APIs diff --git a/docs/testing.md b/docs/testing.md index a42ee2e270..ade07bfbb5 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -14,42 +14,59 @@ These test specific prism implementation details like comments, errors, and regu Snapshot tests ensure that parsed output is equivalent to previous parsed output. There are many categorized examples of valid syntax within the `test/prism/fixtures/` directory. When the test suite runs, it will parse all of this syntax, and compare it against corresponding files in the `test/prism/snapshots/` directory. For example, `test/prism/fixtures/strings.txt` has a corresponding `test/prism/snapshots/strings.txt`. -If the parsed files do not match, it will raise an error. If there is not a corresponding file in the `test/prism/snapshots/` directory, one will be created so that it exists for the next test run. +If the parsed files do not match, it will raise an error. If there is not a corresponding file in the `test/prism/snapshots/` directory, one will be created so that it exists for the next test run. If the snapshot already exists but differs you can run with `UPDATE_SNAPSHOTS=1` to regenerate them. -### Testing against repositories +When working on a specific example, you can limit tests to a single fixture via `FOCUS=strings.txt`. -To test the parser against a repository, you can run `FILEPATHS='/path/to/repository/**/*.rb' rake lex`. This will run the parser against every file matched by the glob pattern and check its generated tokens against those generated by ripper. +#### Versioning -## Local testing - -As you are working, you will likely want to test your code locally. `test.rb` is ignored by git, so it can be used for local testing. There are also two executables which may help you: - -1. **bin/lex** takes a filepath and compares prism's lexed output to Ripper's lexed output. It prints any lexed output that doesn't match. It does some minor transformations to the lexed output in order to compare them, like split prism's heredoc tokens to mirror Ripper's. - -``` -$ bin/lex test.rb -``` +Prism is capable of parsing code with different version specifiers. The test suite reflects this: +* Test files under `test/prism/snapshots/*.txt` are validated against all supported versions. +* Test files under `test/prism/snapshots/[MAJOR].[MINOR]/*.txt` are validated against all versions starting from the given version. +* Test files under `test/prism/snapshots/[MAJOR].[MINOR]-[MAJOR].[MINOR]/*.txt` are validated against the given version range. -If you would like to see the full lexed comparison, and not only the output that doesn't match, you can run with `VERBOSE=1`: - -``` -$ VERBOSE=1 bin/lex test.rb -``` +Should you add logic specific to a new ruby version, validate the new behavior but also that old behavior remains the same. -`bin/lex` can also be used with `-e` and then source code, like this: +### Error tests -``` -$ bin/lex -e "1 + 2" -``` +Error tests are similar to snapshot tests and expectations are located under `test/prism/errors/`. +They contain invalid syntax and rendered errors, similar to how `ruby -c` would show them. +Error tests are versioned in the same way that snapshot tests are and also support `FOCUS`/`UPDATE_SNAPSHOTS`. -2. **bin/parse** takes a filepath and outputs prism's parsed node structure generated from reading the file. +## Local testing +As you are working, you will likely want to test your code locally. `test.rb` is ignored by git, so it can be used for local testing. **bin/prism** contains a multitude of options to aid you, depending on which area +of prism you are working on. `bin/prism --help` prints a list of all available commands. + +Commands that take a `[source]` can be called in three different ways: +1. `bin/prism parse` will use `test.rb` as input. +1. `bin/prism parse foo.rb` will read from the given path. +1. `bin/prism parse -e "1 + 2"` will use the given source code. + +`bin/prism parse` is aliased as `bin/parse` for for convenience. + +### Validating your changes against real code + +If you create a change which is not expected to have a large impact on real code, you can use +`bin/compare` to validate that assumption. It compiles two versions of prism (for example +your feature branch and main), comparing ast, errors and warnings. Once done, a report is +printed showcasing in what way files changed, if any (syntax valid -> syntax invalid, changed AST, etc.) + +```sh +$ bin/compare main feature-branch ~/all-of-rubygems` +... +0/3157385 +1000/3157385 +... +3157000/3157385 +Oops: +intermine-1.05.00/lib/intermine/lists.rb changed from valid(true) to valid(false) +whistle-0.1.1/lib/resource.rb changed from valid(true) to valid(false) +Took 2661.5390081949999512 seconds ``` -$ bin/parse test.rb -``` - -`bin/parse` can also be used with `-e` and then source code, like this: -``` -$ bin/parse -e "1 + 2" -``` +It is up to you to aquire code samples. Here are some resources you can use for this purpose: +* https://github.com/jeromedalbert/real-world-ruby-apps +* https://github.com/eliotsykes/real-world-rails +* https://github.com/rubygems/rubygems-mirror + Requires some work to unpack the downloaded gems. You should also run with `RUBYGEMS_MIRROR_ONLY_LATEST=TRUE`. diff --git a/ext/prism/api_pack.c b/ext/prism/api_pack.c deleted file mode 100644 index 98509ae65c..0000000000 --- a/ext/prism/api_pack.c +++ /dev/null @@ -1,276 +0,0 @@ -#include "prism/extension.h" - -#ifdef PRISM_EXCLUDE_PACK - -void -Init_prism_pack(void) {} - -#else - -static VALUE rb_cPrism; -static VALUE rb_cPrismPack; -static VALUE rb_cPrismPackDirective; -static VALUE rb_cPrismPackFormat; - -static VALUE v3_2_0_symbol; -static VALUE pack_symbol; -static VALUE unpack_symbol; - -#if SIZEOF_UINT64_T == SIZEOF_LONG_LONG -# define UINT64T2NUM(x) ULL2NUM(x) -# define NUM2UINT64T(x) (uint64_t)NUM2ULL(x) -#elif SIZEOF_UINT64_T == SIZEOF_LONG -# define UINT64T2NUM(x) ULONG2NUM(x) -# define NUM2UINT64T(x) (uint64_t)NUM2ULONG(x) -#else -// error No uint64_t conversion -#endif - -static VALUE -pack_type_to_symbol(pm_pack_type type) { - switch (type) { - case PM_PACK_SPACE: - return ID2SYM(rb_intern("SPACE")); - case PM_PACK_COMMENT: - return ID2SYM(rb_intern("COMMENT")); - case PM_PACK_INTEGER: - return ID2SYM(rb_intern("INTEGER")); - case PM_PACK_UTF8: - return ID2SYM(rb_intern("UTF8")); - case PM_PACK_BER: - return ID2SYM(rb_intern("BER")); - case PM_PACK_FLOAT: - return ID2SYM(rb_intern("FLOAT")); - case PM_PACK_STRING_SPACE_PADDED: - return ID2SYM(rb_intern("STRING_SPACE_PADDED")); - case PM_PACK_STRING_NULL_PADDED: - return ID2SYM(rb_intern("STRING_NULL_PADDED")); - case PM_PACK_STRING_NULL_TERMINATED: - return ID2SYM(rb_intern("STRING_NULL_TERMINATED")); - case PM_PACK_STRING_MSB: - return ID2SYM(rb_intern("STRING_MSB")); - case PM_PACK_STRING_LSB: - return ID2SYM(rb_intern("STRING_LSB")); - case PM_PACK_STRING_HEX_HIGH: - return ID2SYM(rb_intern("STRING_HEX_HIGH")); - case PM_PACK_STRING_HEX_LOW: - return ID2SYM(rb_intern("STRING_HEX_LOW")); - case PM_PACK_STRING_UU: - return ID2SYM(rb_intern("STRING_UU")); - case PM_PACK_STRING_MIME: - return ID2SYM(rb_intern("STRING_MIME")); - case PM_PACK_STRING_BASE64: - return ID2SYM(rb_intern("STRING_BASE64")); - case PM_PACK_STRING_FIXED: - return ID2SYM(rb_intern("STRING_FIXED")); - case PM_PACK_STRING_POINTER: - return ID2SYM(rb_intern("STRING_POINTER")); - case PM_PACK_MOVE: - return ID2SYM(rb_intern("MOVE")); - case PM_PACK_BACK: - return ID2SYM(rb_intern("BACK")); - case PM_PACK_NULL: - return ID2SYM(rb_intern("NULL")); - default: - return Qnil; - } -} - -static VALUE -pack_signed_to_symbol(pm_pack_signed signed_type) { - switch (signed_type) { - case PM_PACK_UNSIGNED: - return ID2SYM(rb_intern("UNSIGNED")); - case PM_PACK_SIGNED: - return ID2SYM(rb_intern("SIGNED")); - case PM_PACK_SIGNED_NA: - return ID2SYM(rb_intern("SIGNED_NA")); - default: - return Qnil; - } -} - -static VALUE -pack_endian_to_symbol(pm_pack_endian endian) { - switch (endian) { - case PM_PACK_AGNOSTIC_ENDIAN: - return ID2SYM(rb_intern("AGNOSTIC_ENDIAN")); - case PM_PACK_LITTLE_ENDIAN: - return ID2SYM(rb_intern("LITTLE_ENDIAN")); - case PM_PACK_BIG_ENDIAN: - return ID2SYM(rb_intern("BIG_ENDIAN")); - case PM_PACK_NATIVE_ENDIAN: - return ID2SYM(rb_intern("NATIVE_ENDIAN")); - case PM_PACK_ENDIAN_NA: - return ID2SYM(rb_intern("ENDIAN_NA")); - default: - return Qnil; - } -} - -static VALUE -pack_size_to_symbol(pm_pack_size size) { - switch (size) { - case PM_PACK_SIZE_SHORT: - return ID2SYM(rb_intern("SIZE_SHORT")); - case PM_PACK_SIZE_INT: - return ID2SYM(rb_intern("SIZE_INT")); - case PM_PACK_SIZE_LONG: - return ID2SYM(rb_intern("SIZE_LONG")); - case PM_PACK_SIZE_LONG_LONG: - return ID2SYM(rb_intern("SIZE_LONG_LONG")); - case PM_PACK_SIZE_8: - return ID2SYM(rb_intern("SIZE_8")); - case PM_PACK_SIZE_16: - return ID2SYM(rb_intern("SIZE_16")); - case PM_PACK_SIZE_32: - return ID2SYM(rb_intern("SIZE_32")); - case PM_PACK_SIZE_64: - return ID2SYM(rb_intern("SIZE_64")); - case PM_PACK_SIZE_P: - return ID2SYM(rb_intern("SIZE_P")); - case PM_PACK_SIZE_NA: - return ID2SYM(rb_intern("SIZE_NA")); - default: - return Qnil; - } -} - -static VALUE -pack_length_type_to_symbol(pm_pack_length_type length_type) { - switch (length_type) { - case PM_PACK_LENGTH_FIXED: - return ID2SYM(rb_intern("LENGTH_FIXED")); - case PM_PACK_LENGTH_MAX: - return ID2SYM(rb_intern("LENGTH_MAX")); - case PM_PACK_LENGTH_RELATIVE: - return ID2SYM(rb_intern("LENGTH_RELATIVE")); - case PM_PACK_LENGTH_NA: - return ID2SYM(rb_intern("LENGTH_NA")); - default: - return Qnil; - } -} - -static VALUE -pack_encoding_to_ruby(pm_pack_encoding encoding) { - int index; - switch (encoding) { - case PM_PACK_ENCODING_ASCII_8BIT: - index = rb_ascii8bit_encindex(); - break; - case PM_PACK_ENCODING_US_ASCII: - index = rb_usascii_encindex(); - break; - case PM_PACK_ENCODING_UTF_8: - index = rb_utf8_encindex(); - break; - default: - return Qnil; - } - return rb_enc_from_encoding(rb_enc_from_index(index)); -} - -/** - * call-seq: - * Pack::parse(version, variant, source) -> Format - * - * Parse the given source and return a format object. - */ -static VALUE -pack_parse(VALUE self, VALUE version_symbol, VALUE variant_symbol, VALUE format_string) { - if (version_symbol != v3_2_0_symbol) { - rb_raise(rb_eArgError, "invalid version"); - } - - pm_pack_variant variant; - if (variant_symbol == pack_symbol) { - variant = PM_PACK_VARIANT_PACK; - } else if (variant_symbol == unpack_symbol) { - variant = PM_PACK_VARIANT_UNPACK; - } else { - rb_raise(rb_eArgError, "invalid variant"); - } - - StringValue(format_string); - - const char *format = RSTRING_PTR(format_string); - const char *format_end = format + RSTRING_LEN(format_string); - pm_pack_encoding encoding = PM_PACK_ENCODING_START; - - VALUE directives_array = rb_ary_new(); - - while (format < format_end) { - pm_pack_type type; - pm_pack_signed signed_type; - pm_pack_endian endian; - pm_pack_size size; - pm_pack_length_type length_type; - uint64_t length; - - const char *directive_start = format; - - pm_pack_result parse_result = pm_pack_parse(variant, &format, format_end, &type, &signed_type, &endian, - &size, &length_type, &length, &encoding); - - const char *directive_end = format; - - switch (parse_result) { - case PM_PACK_OK: - break; - case PM_PACK_ERROR_UNSUPPORTED_DIRECTIVE: - rb_raise(rb_eArgError, "unsupported directive"); - case PM_PACK_ERROR_UNKNOWN_DIRECTIVE: - rb_raise(rb_eArgError, "unsupported directive"); - case PM_PACK_ERROR_LENGTH_TOO_BIG: - rb_raise(rb_eRangeError, "pack length too big"); - case PM_PACK_ERROR_BANG_NOT_ALLOWED: - rb_raise(rb_eRangeError, "bang not allowed"); - case PM_PACK_ERROR_DOUBLE_ENDIAN: - rb_raise(rb_eRangeError, "double endian"); - default: - rb_bug("parse result"); - } - - if (type == PM_PACK_END) { - break; - } - - VALUE directive_args[9] = { - version_symbol, - variant_symbol, - rb_usascii_str_new(directive_start, directive_end - directive_start), - pack_type_to_symbol(type), - pack_signed_to_symbol(signed_type), - pack_endian_to_symbol(endian), - pack_size_to_symbol(size), - pack_length_type_to_symbol(length_type), - UINT64T2NUM(length) - }; - - rb_ary_push(directives_array, rb_class_new_instance(9, directive_args, rb_cPrismPackDirective)); - } - - VALUE format_args[2]; - format_args[0] = directives_array; - format_args[1] = pack_encoding_to_ruby(encoding); - return rb_class_new_instance(2, format_args, rb_cPrismPackFormat); -} - -/** - * The function that gets called when Ruby initializes the prism extension. - */ -void -Init_prism_pack(void) { - rb_cPrism = rb_define_module("Prism"); - rb_cPrismPack = rb_define_module_under(rb_cPrism, "Pack"); - rb_cPrismPackDirective = rb_define_class_under(rb_cPrismPack, "Directive", rb_cObject); - rb_cPrismPackFormat = rb_define_class_under(rb_cPrismPack, "Format", rb_cObject); - rb_define_singleton_method(rb_cPrismPack, "parse", pack_parse, 3); - - v3_2_0_symbol = ID2SYM(rb_intern("v3_2_0")); - pack_symbol = ID2SYM(rb_intern("pack")); - unpack_symbol = ID2SYM(rb_intern("unpack")); -} - -#endif diff --git a/ext/prism/extconf.rb b/ext/prism/extconf.rb index ae1691c979..ea7cfe963e 100644 --- a/ext/prism/extconf.rb +++ b/ext/prism/extconf.rb @@ -122,6 +122,8 @@ def add_libprism_source(path) add_libprism_source("$(srcdir)/../../src") + add_libprism_source("$(srcdir)/../../src/util") +$headers += Dir["#{$srcdir}/../../include/**/*.h"] + # Finally, we'll create the `Makefile` that is going to be used to configure and # build the C extension. create_makefile("prism/prism") diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 363144970c..147434c975 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -205,18 +205,14 @@ build_options_i(VALUE key, VALUE value, VALUE argument) { rb_exc_raise(rb_exc_new_cstr(rb_cPrismCurrentVersionError, ruby_version)); } } else if (RSTRING_LEN(value) == 7 && strncmp(version, "nearest", 7) == 0) { - const char *nearest_version; - - if (ruby_version[0] < '3' || (ruby_version[0] == '3' && ruby_version[2] < '3')) { - nearest_version = "3.3"; - } else if (ruby_version[0] > '4' || (ruby_version[0] == '4' && ruby_version[2] > '1')) { - nearest_version = "4.1"; - } else { - nearest_version = ruby_version; - } - - if (!pm_options_version_set(options, nearest_version, 3)) { - rb_raise(rb_eArgError, "invalid nearest version: %s", nearest_version); + if (!pm_options_version_set(options, ruby_version, 3)) { + // Prism doesn't know this specific version. Is it lower? + if (ruby_version[0] < '3' || (ruby_version[0] == '3' && ruby_version[2] < '3')) { + options->version == PM_OPTIONS_VERSION_CRUBY_3_3; + } else { + // Must be higher. + options->version == PM_OPTIONS_VERSION_LATEST; + } } } else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) { rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value); @@ -378,26 +374,28 @@ dump_input(pm_string_t *input, const pm_options_t *options) { rb_raise(rb_eNoMemError, "failed to allocate memory"); } + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); pm_node_t *node = pm_parse(&parser); pm_serialize(&parser, node, &buffer); VALUE result = rb_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer)); - pm_node_destroy(&parser, node); pm_buffer_free(&buffer); pm_parser_free(&parser); + pm_arena_free(&arena); return result; } /** + * :markup: markdown * call-seq: - * Prism::dump(source, **options) -> String + * dump(source, **options) -> String * * Dump the AST corresponding to the given string to a string. For supported - * options, see Prism::parse. + * options, see Prism.parse. */ static VALUE dump(int argc, VALUE *argv, VALUE self) { @@ -416,7 +414,7 @@ dump(int argc, VALUE *argv, VALUE self) { if (options.freeze) rb_obj_freeze(value); #ifdef PRISM_BUILD_DEBUG - xfree(dup); + xfree_sized(dup, length); #endif pm_string_free(&input); @@ -426,11 +424,12 @@ dump(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: - * Prism::dump_file(filepath, **options) -> String + * dump_file(filepath, **options) -> String * * Dump the AST corresponding to the given file to a string. For supported - * options, see Prism::parse. + * options, see Prism.parse. */ static VALUE dump_file(int argc, VALUE *argv, VALUE self) { @@ -642,10 +641,11 @@ parse_result_create(VALUE class, const pm_parser_t *parser, VALUE value, rb_enco parser_data_loc(parser, source, freeze), parser_errors(parser, encoding, source, freeze), parser_warnings(parser, encoding, source, freeze), + parser->continuable ? Qtrue : Qfalse, source }; - return rb_class_new_instance_freeze(7, result_argv, class, freeze); + return rb_class_new_instance_freeze(8, result_argv, class, freeze); } /******************************************************************************/ @@ -738,12 +738,13 @@ parse_lex_encoding_changed_callback(pm_parser_t *parser) { */ static VALUE parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nodes) { + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); 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_capa(parser.newline_list.size); + VALUE offsets = rb_ary_new_capa(parser.line_offsets.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 = { @@ -769,8 +770,8 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod rb_encoding *encoding = rb_enc_find(parser.encoding->name); rb_enc_associate(source_string, encoding); - for (size_t index = 0; index < parser.newline_list.size; index++) { - rb_ary_push(offsets, ULONG2NUM(parser.newline_list.offsets[index])); + for (size_t index = 0; index < parser.line_offsets.size; index++) { + rb_ary_push(offsets, ULONG2NUM(parser.line_offsets.offsets[index])); } if (options->freeze) { @@ -791,18 +792,19 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod result = parse_result_create(rb_cPrismLexResult, &parser, parse_lex_data.tokens, parse_lex_data.encoding, source, options->freeze); } - pm_node_destroy(&parser, node); pm_parser_free(&parser); + pm_arena_free(&arena); return result; } /** + * :markup: markdown * call-seq: - * Prism::lex(source, **options) -> LexResult + * lex(source, **options) -> LexResult * * Return a LexResult instance that contains an array of Token instances - * corresponding to the given string. For supported options, see Prism::parse. + * corresponding to the given string. For supported options, see Prism.parse. */ static VALUE lex(int argc, VALUE *argv, VALUE self) { @@ -818,11 +820,12 @@ lex(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: - * Prism::lex_file(filepath, **options) -> LexResult + * lex_file(filepath, **options) -> LexResult * * Return a LexResult instance that contains an array of Token instances - * corresponding to the given file. For supported options, see Prism::parse. + * corresponding to the given file. For supported options, see Prism.parse. */ static VALUE lex_file(int argc, VALUE *argv, VALUE self) { @@ -848,8 +851,9 @@ lex_file(int argc, VALUE *argv, VALUE self) { */ static VALUE parse_input(pm_string_t *input, const pm_options_t *options) { + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); pm_node_t *node = pm_parse(&parser); rb_encoding *encoding = rb_enc_find(parser.encoding->name); @@ -862,15 +866,16 @@ parse_input(pm_string_t *input, const pm_options_t *options) { rb_obj_freeze(source); } - pm_node_destroy(&parser, node); pm_parser_free(&parser); + pm_arena_free(&arena); return result; } /** + * :markup: markdown * call-seq: - * Prism::parse(source, **options) -> ParseResult + * parse(source, **options) -> ParseResult * * Parse the given string and return a ParseResult instance. The options that * are supported are: @@ -928,7 +933,7 @@ parse(int argc, VALUE *argv, VALUE self) { VALUE value = parse_input(&input, &options); #ifdef PRISM_BUILD_DEBUG - xfree(dup); + xfree_sized(dup, length); #endif pm_string_free(&input); @@ -937,11 +942,12 @@ parse(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: - * Prism::parse_file(filepath, **options) -> ParseResult + * parse_file(filepath, **options) -> ParseResult * * Parse the given file and return a ParseResult instance. For supported - * options, see Prism::parse. + * options, see Prism.parse. */ static VALUE parse_file(int argc, VALUE *argv, VALUE self) { @@ -963,21 +969,23 @@ parse_file(int argc, VALUE *argv, VALUE self) { */ static void profile_input(pm_string_t *input, const pm_options_t *options) { + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); - pm_node_t *node = pm_parse(&parser); - pm_node_destroy(&parser, node); + pm_parse(&parser); pm_parser_free(&parser); + pm_arena_free(&arena); } /** + * :markup: markdown * call-seq: - * Prism::profile(source, **options) -> nil + * 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. + * options, see Prism.parse. */ static VALUE profile(int argc, VALUE *argv, VALUE self) { @@ -993,12 +1001,13 @@ profile(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: - * Prism::profile_file(filepath, **options) -> nil + * 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. + * options, see Prism.parse. */ static VALUE profile_file(int argc, VALUE *argv, VALUE self) { @@ -1045,11 +1054,12 @@ parse_stream_fgets(char *string, int size, void *stream) { } /** + * :markup: markdown * call-seq: - * Prism::parse_stream(stream, **options) -> ParseResult + * parse_stream(stream, **options) -> ParseResult * * Parse the given object that responds to `gets` and return a ParseResult - * instance. The options that are supported are the same as Prism::parse. + * instance. The options that are supported are the same as Prism.parse. */ static VALUE parse_stream(int argc, VALUE *argv, VALUE self) { @@ -1060,19 +1070,20 @@ parse_stream(int argc, VALUE *argv, VALUE self) { pm_options_t options = { 0 }; extract_options(&options, Qnil, keywords); + pm_arena_t arena = { 0 }; pm_parser_t parser; pm_buffer_t buffer; - pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, &options); + pm_node_t *node = pm_parse_stream(&arena, &parser, &buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, &options); rb_encoding *encoding = rb_enc_find(parser.encoding->name); VALUE source = pm_source_new(&parser, encoding, options.freeze); VALUE value = pm_ast_new(&parser, node, encoding, source, options.freeze); VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source, options.freeze); - pm_node_destroy(&parser, node); pm_buffer_free(&buffer); pm_parser_free(&parser); + pm_arena_free(&arena); return result; } @@ -1082,27 +1093,29 @@ parse_stream(int argc, VALUE *argv, VALUE self) { */ static VALUE parse_input_comments(pm_string_t *input, const pm_options_t *options) { + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); - pm_node_t *node = pm_parse(&parser); + pm_parse(&parser); rb_encoding *encoding = rb_enc_find(parser.encoding->name); VALUE source = pm_source_new(&parser, encoding, options->freeze); VALUE comments = parser_comments(&parser, source, options->freeze); - pm_node_destroy(&parser, node); pm_parser_free(&parser); + pm_arena_free(&arena); return comments; } /** + * :markup: markdown * call-seq: - * Prism::parse_comments(source, **options) -> Array + * parse_comments(source, **options) -> Array * * Parse the given string and return an array of Comment objects. For supported - * options, see Prism::parse. + * options, see Prism.parse. */ static VALUE parse_comments(int argc, VALUE *argv, VALUE self) { @@ -1118,11 +1131,12 @@ parse_comments(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: - * Prism::parse_file_comments(filepath, **options) -> Array + * parse_file_comments(filepath, **options) -> Array * * Parse the given file and return an array of Comment objects. For supported - * options, see Prism::parse. + * options, see Prism.parse. */ static VALUE parse_file_comments(int argc, VALUE *argv, VALUE self) { @@ -1140,18 +1154,19 @@ parse_file_comments(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: - * Prism::parse_lex(source, **options) -> ParseLexResult + * parse_lex(source, **options) -> ParseLexResult * * 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. * * This API is only meant to be used in the case where you need both the AST and - * the tokens. If you only need one or the other, use either Prism::parse or - * Prism::lex. + * the tokens. If you only need one or the other, use either Prism.parse or + * Prism.lex. * - * For supported options, see Prism::parse. + * For supported options, see Prism.parse. */ static VALUE parse_lex(int argc, VALUE *argv, VALUE self) { @@ -1167,18 +1182,19 @@ parse_lex(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: - * Prism::parse_lex_file(filepath, **options) -> ParseLexResult + * parse_lex_file(filepath, **options) -> ParseLexResult * * 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. * * This API is only meant to be used in the case where you need both the AST and - * the tokens. If you only need one or the other, use either Prism::parse_file - * or Prism::lex_file. + * the tokens. If you only need one or the other, use either Prism.parse_file + * or Prism.lex_file. * - * For supported options, see Prism::parse. + * For supported options, see Prism.parse. */ static VALUE parse_lex_file(int argc, VALUE *argv, VALUE self) { @@ -1200,24 +1216,26 @@ parse_lex_file(int argc, VALUE *argv, VALUE self) { */ static VALUE parse_input_success_p(pm_string_t *input, const pm_options_t *options) { + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); - pm_node_t *node = pm_parse(&parser); - pm_node_destroy(&parser, node); + pm_parse(&parser); VALUE result = parser.error_list.size == 0 ? Qtrue : Qfalse; pm_parser_free(&parser); + pm_arena_free(&arena); return result; } /** + * :markup: markdown * call-seq: - * Prism::parse_success?(source, **options) -> bool + * parse_success?(source, **options) -> bool * * Parse the given string and return true if it parses without errors. For - * supported options, see Prism::parse. + * supported options, see Prism.parse. */ static VALUE parse_success_p(int argc, VALUE *argv, VALUE self) { @@ -1233,11 +1251,12 @@ parse_success_p(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: - * Prism::parse_failure?(source, **options) -> bool + * parse_failure?(source, **options) -> bool * * Parse the given string and return true if it parses with errors. For - * supported options, see Prism::parse. + * supported options, see Prism.parse. */ static VALUE parse_failure_p(int argc, VALUE *argv, VALUE self) { @@ -1245,11 +1264,12 @@ parse_failure_p(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: - * Prism::parse_file_success?(filepath, **options) -> bool + * parse_file_success?(filepath, **options) -> bool * * Parse the given file and return true if it parses without errors. For - * supported options, see Prism::parse. + * supported options, see Prism.parse. */ static VALUE parse_file_success_p(int argc, VALUE *argv, VALUE self) { @@ -1267,11 +1287,12 @@ parse_file_success_p(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: - * Prism::parse_file_failure?(filepath, **options) -> bool + * parse_file_failure?(filepath, **options) -> bool * * Parse the given file and return true if it parses with errors. For - * supported options, see Prism::parse. + * supported options, see Prism.parse. */ static VALUE parse_file_failure_p(int argc, VALUE *argv, VALUE self) { @@ -1301,8 +1322,9 @@ string_query(pm_string_query_t result) { } /** + * :markup: markdown * call-seq: - * Prism::StringQuery::local?(string) -> bool + * local?(string) -> bool * * 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 @@ -1315,8 +1337,9 @@ string_query_local_p(VALUE self, VALUE string) { } /** + * :markup: markdown * call-seq: - * Prism::StringQuery::constant?(string) -> bool + * constant?(string) -> bool * * 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 @@ -1329,8 +1352,9 @@ string_query_constant_p(VALUE self, VALUE string) { } /** + * :markup: markdown * call-seq: - * Prism::StringQuery::method_name?(string) -> bool + * method_name?(string) -> bool * * Returns true if the string constitutes a valid method name. */ @@ -1438,5 +1462,4 @@ Init_prism(void) { // Next, initialize the other APIs. Init_prism_api_node(); - Init_prism_pack(); } diff --git a/ext/prism/extension.h b/ext/prism/extension.h index a2aaa6388f..d0cbc2ff53 100644 --- a/ext/prism/extension.h +++ b/ext/prism/extension.h @@ -14,7 +14,6 @@ VALUE pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding * VALUE pm_integer_new(const pm_integer_t *integer); void Init_prism_api_node(void); -void Init_prism_pack(void); RUBY_FUNC_EXPORTED void Init_prism(void); #endif diff --git a/fuzz/regexp.c b/fuzz/regexp.c index 3837d74d57..f1a02dedc2 100644 --- a/fuzz/regexp.c +++ b/fuzz/regexp.c @@ -12,10 +12,12 @@ regexp_error_callback(const uint8_t *start, const uint8_t *end, const char *mess void harness(const uint8_t *input, size_t size) { + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, input, size, NULL); + pm_parser_init(&arena, &parser, input, size, NULL); pm_regexp_parse(&parser, input, size, false, regexp_name_callback, NULL, regexp_error_callback, NULL); pm_parser_free(&parser); + pm_arena_free(&arena); } diff --git a/gemfiles/2.7/Gemfile b/gemfiles/2.7/Gemfile index 8d1fbb82cd..a3ac724e5e 100644 --- a/gemfiles/2.7/Gemfile +++ b/gemfiles/2.7/Gemfile @@ -10,6 +10,5 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/2.7/Gemfile.lock b/gemfiles/2.7/Gemfile.lock index f75112d346..7eab6a5528 100644 --- a/gemfiles/2.7/Gemfile.lock +++ b/gemfiles/2.7/Gemfile.lock @@ -8,7 +8,7 @@ GEM specs: ast (2.4.3) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) @@ -16,7 +16,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.1.3) ruby_parser (3.21.1) racc (~> 1.5) sexp_processor (~> 4.16) @@ -33,7 +32,6 @@ DEPENDENCIES prism! rake rake-compiler - rbs ruby_parser test-unit diff --git a/gemfiles/3.0/Gemfile b/gemfiles/3.0/Gemfile index c52f90eaf8..c5600d20f0 100644 --- a/gemfiles/3.0/Gemfile +++ b/gemfiles/3.0/Gemfile @@ -10,7 +10,5 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" -gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/3.0/Gemfile.lock b/gemfiles/3.0/Gemfile.lock index 9174ab2a9e..d295f1f173 100644 --- a/gemfiles/3.0/Gemfile.lock +++ b/gemfiles/3.0/Gemfile.lock @@ -7,13 +7,8 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - logger (1.7.0) - mini_portile2 (2.8.9) - nokogiri (1.17.2) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) @@ -21,10 +16,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.6.1) - logger - ruby_memcheck (3.0.1) - nokogiri ruby_parser (3.21.1) racc (~> 1.5) sexp_processor (~> 4.16) @@ -41,8 +32,6 @@ DEPENDENCIES prism! rake rake-compiler - rbs - ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/3.1/Gemfile b/gemfiles/3.1/Gemfile index b17401ffc3..6f7e7b6a28 100644 --- a/gemfiles/3.1/Gemfile +++ b/gemfiles/3.1/Gemfile @@ -10,7 +10,5 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" -gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/3.1/Gemfile.lock b/gemfiles/3.1/Gemfile.lock index 8247f879fd..3b242f5c3c 100644 --- a/gemfiles/3.1/Gemfile.lock +++ b/gemfiles/3.1/Gemfile.lock @@ -7,13 +7,8 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - logger (1.7.0) - mini_portile2 (2.8.9) - nokogiri (1.18.10) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) @@ -21,10 +16,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.10.2) - logger - ruby_memcheck (3.0.1) - nokogiri ruby_parser (3.21.1) racc (~> 1.5) sexp_processor (~> 4.16) @@ -41,8 +32,6 @@ DEPENDENCIES prism! rake rake-compiler - rbs - ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/3.2/Gemfile b/gemfiles/3.2/Gemfile index 009b09ec1a..7d82c2b76a 100644 --- a/gemfiles/3.2/Gemfile +++ b/gemfiles/3.2/Gemfile @@ -10,7 +10,5 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" -gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/3.2/Gemfile.lock b/gemfiles/3.2/Gemfile.lock index c9c75907d6..661e0434d9 100644 --- a/gemfiles/3.2/Gemfile.lock +++ b/gemfiles/3.2/Gemfile.lock @@ -7,13 +7,8 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - logger (1.7.0) - mini_portile2 (2.8.9) - nokogiri (1.19.0) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) @@ -21,10 +16,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.10.2) - logger - ruby_memcheck (3.0.1) - nokogiri ruby_parser (3.22.0) racc (~> 1.5) sexp_processor (~> 4.16) @@ -41,8 +32,6 @@ DEPENDENCIES prism! rake rake-compiler - rbs - ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/3.3/Gemfile b/gemfiles/3.3/Gemfile index 73006ce144..f78c4cc9a2 100644 --- a/gemfiles/3.3/Gemfile +++ b/gemfiles/3.3/Gemfile @@ -10,7 +10,5 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" -gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/3.3/Gemfile.lock b/gemfiles/3.3/Gemfile.lock index d452f1bc2f..55d0a9103d 100644 --- a/gemfiles/3.3/Gemfile.lock +++ b/gemfiles/3.3/Gemfile.lock @@ -7,13 +7,8 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - logger (1.7.0) - mini_portile2 (2.8.9) - nokogiri (1.19.0) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) @@ -21,10 +16,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.10.2) - logger - ruby_memcheck (3.0.1) - nokogiri ruby_parser (3.22.0) racc (~> 1.5) sexp_processor (~> 4.16) @@ -41,8 +32,6 @@ DEPENDENCIES prism! rake rake-compiler - rbs - ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/3.4/Gemfile b/gemfiles/3.4/Gemfile index 2e86887f58..c1b19d7d53 100644 --- a/gemfiles/3.4/Gemfile +++ b/gemfiles/3.4/Gemfile @@ -10,7 +10,5 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" -gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/3.4/Gemfile.lock b/gemfiles/3.4/Gemfile.lock index a1195453db..6857ef7c0b 100644 --- a/gemfiles/3.4/Gemfile.lock +++ b/gemfiles/3.4/Gemfile.lock @@ -7,13 +7,8 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - logger (1.7.0) - mini_portile2 (2.8.9) - nokogiri (1.19.0) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) @@ -21,10 +16,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.10.2) - logger - ruby_memcheck (3.0.1) - nokogiri ruby_parser (3.22.0) racc (~> 1.5) sexp_processor (~> 4.16) @@ -41,8 +32,6 @@ DEPENDENCIES prism! rake rake-compiler - rbs - ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/4.0/Gemfile b/gemfiles/4.0/Gemfile index f3fef38fe8..538073fb0e 100644 --- a/gemfiles/4.0/Gemfile +++ b/gemfiles/4.0/Gemfile @@ -6,12 +6,9 @@ ruby "~> 4.0.0" gemspec path: "../.." -gem "ffi" gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" -gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/4.0/Gemfile.lock b/gemfiles/4.0/Gemfile.lock index c7670f7ea1..8514c58291 100644 --- a/gemfiles/4.0/Gemfile.lock +++ b/gemfiles/4.0/Gemfile.lock @@ -7,14 +7,8 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - ffi (1.17.3) - logger (1.7.0) - mini_portile2 (2.8.9) - nokogiri (1.19.0) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) @@ -22,10 +16,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.10.2) - logger - ruby_memcheck (3.0.1) - nokogiri ruby_parser (3.22.0) racc (~> 1.5) sexp_processor (~> 4.16) @@ -37,14 +27,11 @@ PLATFORMS ruby DEPENDENCIES - ffi onigmo parser prism! rake rake-compiler - rbs - ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/4.1/Gemfile b/gemfiles/4.1/Gemfile index 3fde9d4ac1..8beda3da54 100644 --- a/gemfiles/4.1/Gemfile +++ b/gemfiles/4.1/Gemfile @@ -11,7 +11,5 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" -gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/4.1/Gemfile.lock b/gemfiles/4.1/Gemfile.lock index cd652a75b4..db51633a6d 100644 --- a/gemfiles/4.1/Gemfile.lock +++ b/gemfiles/4.1/Gemfile.lock @@ -8,13 +8,8 @@ GEM specs: ast (2.4.3) ffi (1.17.3) - logger (1.7.0) - mini_portile2 (2.8.9) - nokogiri (1.19.0) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) @@ -22,10 +17,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.10.2) - logger - ruby_memcheck (3.0.1) - nokogiri ruby_parser (3.22.0) racc (~> 1.5) sexp_processor (~> 4.16) @@ -43,8 +34,6 @@ DEPENDENCIES prism! rake rake-compiler - rbs - ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/typecheck/Gemfile b/gemfiles/typecheck/Gemfile index b535d28729..3965a1c17d 100644 --- a/gemfiles/typecheck/Gemfile +++ b/gemfiles/typecheck/Gemfile @@ -2,11 +2,11 @@ source "https://rubygems.org" -gem "minitest" gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" +gem "rbi" +gem "rbs-inline" gem "ruby_parser" gem "sorbet", "<= 0.6.12666" # until tapioca is bumped gem "steep", ">= 1.7.0.dev.1" diff --git a/gemfiles/typecheck/Gemfile.lock b/gemfiles/typecheck/Gemfile.lock index d3d512dc9e..a5363e44fb 100644 --- a/gemfiles/typecheck/Gemfile.lock +++ b/gemfiles/typecheck/Gemfile.lock @@ -23,8 +23,7 @@ GEM csv (3.3.5) drb (2.2.3) erubi (1.13.1) - ffi (1.17.3-arm64-darwin) - ffi (1.17.3-x86_64-linux-gnu) + ffi (1.17.3) fileutils (1.8.0) i18n (1.14.7) concurrent-ruby (~> 1.0) @@ -39,11 +38,11 @@ GEM mutex_m (0.3.0) netrc (0.11.0) parallel (1.27.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) - prism (1.7.0) + prism (1.9.0) racc (1.8.1) rainbow (3.1.1) rake (13.3.1) @@ -52,17 +51,21 @@ GEM rb-fsevent (0.11.2) rb-inotify (0.11.1) ffi (~> 1.0) - rbi (0.3.7) + rbi (0.3.9) prism (~> 1.0) rbs (>= 3.4.4) - rbs (3.10.2) + rbs (3.10.3) logger + tsort + rbs-inline (0.13.0) + prism (>= 0.29) + rbs (>= 3.8.0) rexml (3.4.4) ruby_parser (3.22.0) racc (~> 1.5) sexp_processor (~> 4.16) securerandom (0.4.1) - sexp_processor (4.17.4) + sexp_processor (4.17.5) sorbet (0.6.12666) sorbet-static (= 0.6.12666) sorbet-runtime (0.6.12666) @@ -111,11 +114,12 @@ GEM test-unit (3.7.7) power_assert thor (1.4.0) + tsort (0.2.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (3.2.0) unicode-emoji (~> 4.1) - unicode-emoji (4.1.0) + unicode-emoji (4.2.0) uri (1.1.1) yard (0.9.37) yard-sorbet (0.9.0) @@ -127,11 +131,11 @@ PLATFORMS x86_64-linux DEPENDENCIES - minitest parser rake rake-compiler - rbs + rbi + rbs-inline ruby_parser sorbet (<= 0.6.12666) steep (>= 1.7.0.dev.1) diff --git a/include/prism.h b/include/prism.h index c1ce582997..76733b8aaf 100644 --- a/include/prism.h +++ b/include/prism.h @@ -6,7 +6,12 @@ #ifndef PRISM_H #define PRISM_H +#ifdef __cplusplus +extern "C" { +#endif + #include "prism/defines.h" +#include "prism/util/pm_arena.h" #include "prism/util/pm_buffer.h" #include "prism/util/pm_char.h" #include "prism/util/pm_integer.h" @@ -17,7 +22,6 @@ #include "prism/diagnostic.h" #include "prism/node.h" #include "prism/options.h" -#include "prism/pack.h" #include "prism/parser.h" #include "prism/prettyprint.h" #include "prism/regexp.h" @@ -49,8 +53,11 @@ PRISM_EXPORTED_FUNCTION const char * pm_version(void); /** * Initialize a parser with the given start and end pointers. * - * The resulting parser must eventually be freed with `pm_parser_free()`. + * The resulting parser must eventually be freed with `pm_parser_free()`. The + * arena is caller-owned and must outlive the parser — `pm_parser_free()` does + * not free the arena. * + * @param arena The arena to use for all AST-lifetime allocations. * @param parser The parser to initialize. * @param source The source to parse. * @param size The size of the source. @@ -59,7 +66,7 @@ PRISM_EXPORTED_FUNCTION const char * pm_version(void); * * \public \memberof pm_parser */ -PRISM_EXPORTED_FUNCTION void pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options); +PRISM_EXPORTED_FUNCTION void pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options); /** * Register a callback that will be called whenever prism changes the encoding @@ -111,6 +118,7 @@ typedef int (pm_parse_stream_feof_t)(void *stream); /** * Parse a stream of Ruby source and return the tree. * + * @param arena The arena to use for all AST-lifetime allocations. * @param parser The parser to use. * @param buffer The buffer to use. * @param stream The stream to parse. @@ -121,7 +129,7 @@ typedef int (pm_parse_stream_feof_t)(void *stream); * * \public \memberof pm_parser */ -PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options); +PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_arena_t *arena, pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options); // We optionally support serializing to a binary string. For systems that don't // want or need this functionality, it can be turned off with the @@ -330,24 +338,26 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * In order to parse Ruby code, the structures and functions that you're going * to want to use and be aware of are: * + * * `pm_arena_t` - the arena allocator for AST-lifetime memory * * `pm_parser_t` - the main parser structure * * `pm_parser_init()` - initialize a parser * * `pm_parse()` - parse and return the root node - * * `pm_node_destroy()` - deallocate the root node returned by `pm_parse()` * * `pm_parser_free()` - free the internal memory of the parser + * * `pm_arena_free()` - free all AST-lifetime memory * * Putting all of this together would look something like: * * ```c * void parse(const uint8_t *source, size_t length) { + * pm_arena_t arena = { 0 }; * pm_parser_t parser; - * pm_parser_init(&parser, source, length, NULL); + * pm_parser_init(&arena, &parser, source, length, NULL); * * pm_node_t *root = pm_parse(&parser); * printf("PARSED!\n"); * - * pm_node_destroy(&parser, root); * pm_parser_free(&parser); + * pm_arena_free(&arena); * } * ``` * @@ -388,8 +398,9 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * * ```c * void prettyprint(const uint8_t *source, size_t length) { + * pm_arena_t arena = { 0 }; * pm_parser_t parser; - * pm_parser_init(&parser, source, length, NULL); + * pm_parser_init(&arena, &parser, source, length, NULL); * * pm_node_t *root = pm_parse(&parser); * pm_buffer_t buffer = { 0 }; @@ -398,10 +409,14 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * printf("%*.s\n", (int) buffer.length, buffer.value); * * pm_buffer_free(&buffer); - * pm_node_destroy(&parser, root); * pm_parser_free(&parser); + * pm_arena_free(&arena); * } * ``` */ +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/prism/debug_allocator.h b/include/prism/debug_allocator.h new file mode 100644 index 0000000000..3e28a95efb --- /dev/null +++ b/include/prism/debug_allocator.h @@ -0,0 +1,99 @@ +/** + * @file debug_allocator.h + * + * Decorate allocation function to ensure sizes are correct. + */ +#ifndef PRISM_DEBUG_ALLOCATOR_H +#define PRISM_DEBUG_ALLOCATOR_H + +#include +#include +#include + +static inline void * +pm_debug_malloc(size_t size) +{ + size_t *memory = xmalloc(size + sizeof(size_t)); + memory[0] = size; + return memory + 1; +} + +static inline void * +pm_debug_calloc(size_t nmemb, size_t size) +{ + size_t total_size = nmemb * size; + void *ptr = pm_debug_malloc(total_size); + memset(ptr, 0, total_size); + return ptr; +} + +static inline void * +pm_debug_realloc(void *ptr, size_t size) +{ + if (ptr == NULL) { + return pm_debug_malloc(size); + } + + size_t *memory = (size_t *)ptr; + void *raw_memory = memory - 1; + memory = (size_t *)xrealloc(raw_memory, size + sizeof(size_t)); + memory[0] = size; + return memory + 1; +} + +static inline void +pm_debug_free(void *ptr) +{ + if (ptr != NULL) { + size_t *memory = (size_t *)ptr; + xfree(memory - 1); + } +} + +static inline void +pm_debug_free_sized(void *ptr, size_t old_size) +{ + if (ptr != NULL) { + size_t *memory = (size_t *)ptr; + if (old_size != memory[-1]) { + fprintf(stderr, "[BUG] buffer %p was allocated with size %lu but freed with size %lu\n", ptr, memory[-1], old_size); + abort(); + } + xfree_sized(memory - 1, old_size + sizeof(size_t)); + } +} + +static inline void * +pm_debug_realloc_sized(void *ptr, size_t size, size_t old_size) +{ + if (ptr == NULL) { + if (old_size != 0) { + fprintf(stderr, "[BUG] realloc_sized called with NULL pointer and old size %lu\n", old_size); + abort(); + } + return pm_debug_malloc(size); + } + + size_t *memory = (size_t *)ptr; + if (old_size != memory[-1]) { + fprintf(stderr, "[BUG] buffer %p was allocated with size %lu but realloced with size %lu\n", ptr, memory[-1], old_size); + abort(); + } + return pm_debug_realloc(ptr, size); +} + +#undef xmalloc +#undef xrealloc +#undef xcalloc +#undef xfree +#undef xrealloc_sized +#undef xfree_sized + +#define xmalloc pm_debug_malloc +#define xrealloc pm_debug_realloc +#define xcalloc pm_debug_calloc +#define xfree pm_debug_free +#define xrealloc_sized pm_debug_realloc_sized +#define xfree_sized pm_debug_free_sized + +#endif diff --git a/include/prism/defines.h b/include/prism/defines.h index f6bd1dbe40..c48a600b21 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -161,10 +161,12 @@ * ``` * #ifndef PRISM_XALLOCATOR_H * #define PRISM_XALLOCATOR_H - * #define xmalloc my_malloc - * #define xrealloc my_realloc - * #define xcalloc my_calloc - * #define xfree my_free + * #define xmalloc my_malloc + * #define xrealloc my_realloc + * #define xcalloc my_calloc + * #define xfree my_free + * #define xrealloc_sized my_realloc_sized // (optional) + * #define xfree_sized my_free_sized // (optional) * #endif * ``` */ @@ -204,6 +206,28 @@ #endif #endif +#ifndef xfree_sized +/** + * The free_sized function that should be used. This can be overridden with the + * PRISM_XALLOCATOR define. + * If not defined, defaults to calling xfree. + */ + #define xfree_sized(p, s) xfree(((void)(s), (p))) +#endif + +#ifndef xrealloc_sized +/** + * The xrealloc_sized function that should be used. This can be overridden with the + * PRISM_XALLOCATOR define. + * If not defined, defaults to calling xrealloc. + */ + #define xrealloc_sized(p, ns, os) xrealloc((p), ((void)(os), (ns))) +#endif + +#ifdef PRISM_BUILD_DEBUG + #include "prism/debug_allocator.h" +#endif + /** * If PRISM_BUILD_MINIMAL is defined, then we're going to define every possible * switch that will turn off certain features of prism. @@ -215,9 +239,6 @@ /** Exclude the JSON serialization API. */ #define PRISM_EXCLUDE_JSON - /** Exclude the Array#pack parser API. */ - #define PRISM_EXCLUDE_PACK - /** Exclude the prettyprint API. */ #define PRISM_EXCLUDE_PRETTYPRINT @@ -257,6 +278,18 @@ #define PRISM_FALLTHROUGH #endif +/** + * A macro for defining a flexible array member. C99 supports `data[]`, GCC + * supports `data[0]` as an extension, and older compilers require `data[1]`. + */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) + #define PM_FLEX_ARY_LEN /* data[] */ +#elif defined(__GNUC__) && !defined(__STRICT_ANSI__) + #define PM_FLEX_ARY_LEN 0 /* data[0] */ +#else + #define PM_FLEX_ARY_LEN 1 /* data[1] */ +#endif + /** * We need to align nodes in the AST to a pointer boundary so that it can be * safely cast to different node types. Use PRISM_ALIGNAS/PRISM_ALIGNOF to diff --git a/include/prism/node.h b/include/prism/node.h index e8686a327c..253f890055 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -20,41 +20,29 @@ /** * Append a new node onto the end of the node list. * + * @param arena The arena to allocate from. * @param list The list to append to. * @param node The node to append. */ -void pm_node_list_append(pm_node_list_t *list, pm_node_t *node); +void pm_node_list_append(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node); /** * Prepend a new node onto the beginning of the node list. * + * @param arena The arena to allocate from. * @param list The list to prepend to. * @param node The node to prepend. */ -void pm_node_list_prepend(pm_node_list_t *list, pm_node_t *node); +void pm_node_list_prepend(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node); /** * Concatenate the given node list onto the end of the other node list. * + * @param arena The arena to allocate from. * @param list The list to concatenate onto. * @param other The list to concatenate. */ -void pm_node_list_concat(pm_node_list_t *list, pm_node_list_t *other); - -/** - * Free the internal memory associated with the given node list. - * - * @param list The list to free. - */ -void pm_node_list_free(pm_node_list_t *list); - -/** - * Deallocate a node and all of its children. - * - * @param parser The parser that owns the node. - * @param node The node to deallocate. - */ -PRISM_EXPORTED_FUNCTION void pm_node_destroy(pm_parser_t *parser, struct pm_node *node); +void pm_node_list_concat(pm_arena_t *arena, pm_node_list_t *list, pm_node_list_t *other); /** * Returns a string representation of the given node type. @@ -93,9 +81,10 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_typ * const char *source = "1 + 2; 3 + 4"; * size_t size = strlen(source); * + * pm_arena_t arena = { 0 }; * pm_parser_t parser; * pm_options_t options = { 0 }; - * pm_parser_init(&parser, (const uint8_t *) source, size, &options); + * pm_parser_init(&arena, &parser, (const uint8_t *) source, size, &options); * * size_t indent = 0; * pm_node_t *node = pm_parse(&parser); @@ -103,8 +92,8 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_typ * size_t *data = &indent; * pm_visit_node(node, visit, data); * - * pm_node_destroy(&parser, node); * pm_parser_free(&parser); + * pm_arena_free(&arena); * return EXIT_SUCCESS; * } * ``` diff --git a/include/prism/pack.h b/include/prism/pack.h deleted file mode 100644 index 0b0b4b19cc..0000000000 --- a/include/prism/pack.h +++ /dev/null @@ -1,163 +0,0 @@ -/** - * @file pack.h - * - * A pack template string parser. - */ -#ifndef PRISM_PACK_H -#define PRISM_PACK_H - -#include "prism/defines.h" - -// We optionally support parsing String#pack templates. For systems that don't -// want or need this functionality, it can be turned off with the -// PRISM_EXCLUDE_PACK define. -#ifdef PRISM_EXCLUDE_PACK - -void pm_pack_parse(void); - -#else - -#include -#include - -/** The version of the pack template language that we are parsing. */ -typedef enum pm_pack_version { - PM_PACK_VERSION_3_2_0 -} pm_pack_version; - -/** The type of pack template we are parsing. */ -typedef enum pm_pack_variant { - PM_PACK_VARIANT_PACK, - PM_PACK_VARIANT_UNPACK -} pm_pack_variant; - -/** A directive within the pack template. */ -typedef enum pm_pack_type { - PM_PACK_SPACE, - PM_PACK_COMMENT, - PM_PACK_INTEGER, - PM_PACK_UTF8, - PM_PACK_BER, - PM_PACK_FLOAT, - PM_PACK_STRING_SPACE_PADDED, - PM_PACK_STRING_NULL_PADDED, - PM_PACK_STRING_NULL_TERMINATED, - PM_PACK_STRING_MSB, - PM_PACK_STRING_LSB, - PM_PACK_STRING_HEX_HIGH, - PM_PACK_STRING_HEX_LOW, - PM_PACK_STRING_UU, - PM_PACK_STRING_MIME, - PM_PACK_STRING_BASE64, - PM_PACK_STRING_FIXED, - PM_PACK_STRING_POINTER, - PM_PACK_MOVE, - PM_PACK_BACK, - PM_PACK_NULL, - PM_PACK_END -} pm_pack_type; - -/** The signness of a pack directive. */ -typedef enum pm_pack_signed { - PM_PACK_UNSIGNED, - PM_PACK_SIGNED, - PM_PACK_SIGNED_NA -} pm_pack_signed; - -/** The endianness of a pack directive. */ -typedef enum pm_pack_endian { - PM_PACK_AGNOSTIC_ENDIAN, - PM_PACK_LITTLE_ENDIAN, // aka 'VAX', or 'V' - PM_PACK_BIG_ENDIAN, // aka 'network', or 'N' - PM_PACK_NATIVE_ENDIAN, - PM_PACK_ENDIAN_NA -} pm_pack_endian; - -/** The size of an integer pack directive. */ -typedef enum pm_pack_size { - PM_PACK_SIZE_SHORT, - PM_PACK_SIZE_INT, - PM_PACK_SIZE_LONG, - PM_PACK_SIZE_LONG_LONG, - PM_PACK_SIZE_8, - PM_PACK_SIZE_16, - PM_PACK_SIZE_32, - PM_PACK_SIZE_64, - PM_PACK_SIZE_P, - PM_PACK_SIZE_NA -} pm_pack_size; - -/** The type of length of a pack directive. */ -typedef enum pm_pack_length_type { - PM_PACK_LENGTH_FIXED, - PM_PACK_LENGTH_MAX, - PM_PACK_LENGTH_RELATIVE, // special case for unpack @* - PM_PACK_LENGTH_NA -} pm_pack_length_type; - -/** The type of encoding for a pack template string. */ -typedef enum pm_pack_encoding { - PM_PACK_ENCODING_START, - PM_PACK_ENCODING_ASCII_8BIT, - PM_PACK_ENCODING_US_ASCII, - PM_PACK_ENCODING_UTF_8 -} pm_pack_encoding; - -/** The result of parsing a pack template. */ -typedef enum pm_pack_result { - PM_PACK_OK, - PM_PACK_ERROR_UNSUPPORTED_DIRECTIVE, - PM_PACK_ERROR_UNKNOWN_DIRECTIVE, - PM_PACK_ERROR_LENGTH_TOO_BIG, - PM_PACK_ERROR_BANG_NOT_ALLOWED, - PM_PACK_ERROR_DOUBLE_ENDIAN -} pm_pack_result; - -/** - * Parse a single directive from a pack or unpack format string. - * - * @param variant (in) pack or unpack - * @param format (in, out) the start of the next directive to parse on calling, - * and advanced beyond the parsed directive on return, or as much of it as - * was consumed until an error was encountered - * @param format_end (in) the end of the format string - * @param type (out) the type of the directive - * @param signed_type (out) whether the value is signed - * @param endian (out) the endianness of the value - * @param size (out) the size of the value - * @param length_type (out) what kind of length is specified - * @param length (out) the length of the directive - * @param encoding (in, out) takes the current encoding of the string which - * would result from parsing the whole format string, and returns a possibly - * changed directive - the encoding should be `PM_PACK_ENCODING_START` when - * pm_pack_parse is called for the first directive in a format string - * - * @return `PM_PACK_OK` on success or `PM_PACK_ERROR_*` on error - * @note Consult Ruby documentation for the meaning of directives. - */ -PRISM_EXPORTED_FUNCTION pm_pack_result -pm_pack_parse( - pm_pack_variant variant, - const char **format, - const char *format_end, - pm_pack_type *type, - pm_pack_signed *signed_type, - pm_pack_endian *endian, - pm_pack_size *size, - pm_pack_length_type *length_type, - uint64_t *length, - pm_pack_encoding *encoding -); - -/** - * Prism abstracts sizes away from the native system - this converts an abstract - * size to a native size. - * - * @param size The abstract size to convert. - * @return The native size. - */ -PRISM_EXPORTED_FUNCTION size_t pm_size_to_native(pm_pack_size size); - -#endif - -#endif diff --git a/include/prism/parser.h b/include/prism/parser.h index a8d840d3bf..d8e7a550e7 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -11,9 +11,10 @@ #include "prism/encoding.h" #include "prism/options.h" #include "prism/static_literals.h" +#include "prism/util/pm_arena.h" #include "prism/util/pm_constant_pool.h" #include "prism/util/pm_list.h" -#include "prism/util/pm_newline_list.h" +#include "prism/util/pm_line_offset_list.h" #include "prism/util/pm_string.h" #include @@ -635,6 +636,9 @@ typedef uint32_t pm_state_stack_t; * it's considering. */ struct pm_parser { + /** The arena used for all AST-lifetime allocations. Caller-owned. */ + pm_arena_t *arena; + /** * 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 @@ -782,8 +786,8 @@ struct pm_parser { */ pm_constant_pool_t constant_pool; - /** This is the list of newline offsets in the source file. */ - pm_newline_list_t newline_list; + /** This is the list of line offsets in the source file. */ + pm_line_offset_list_t line_offsets; /** * We want to add a flag to integer nodes that indicates their base. We only @@ -881,9 +885,24 @@ struct pm_parser { /** Whether or not we're at the beginning of a command. */ bool command_start; + /** + * Whether or not we're currently parsing the body of an endless method + * definition. In this context, PM_TOKEN_KEYWORD_DO_BLOCK should not be + * consumed by commands (it should bubble up to the outer context). + */ + bool in_endless_def_body; + /** Whether or not we're currently recovering from a syntax error. */ bool recovering; + /** + * Whether or not the source being parsed could become valid if more input + * were appended. This is set to false when the parser encounters a token + * that is definitively wrong (e.g., a stray `end` or `]`) as opposed to + * merely incomplete. + */ + bool continuable; + /** * 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 @@ -914,12 +933,6 @@ struct pm_parser { */ bool semantic_token_seen; - /** - * True if the current regular expression being lexed contains only ASCII - * characters. - */ - bool current_regular_expression_ascii_only; - /** * By default, Ruby always warns about mismatched indentation. This can be * toggled with a magic comment. diff --git a/include/prism/regexp.h b/include/prism/regexp.h index 5366b5a5a0..b3e739b457 100644 --- a/include/prism/regexp.h +++ b/include/prism/regexp.h @@ -17,27 +17,56 @@ #include /** - * This callback is called by pm_regexp_parse() when a named capture group is found. + * Accumulation state for named capture groups found during regexp parsing. + * The caller initializes this with the call node and passes it to + * pm_regexp_parse. The regexp parser populates match and names as groups + * are found. */ -typedef void (*pm_regexp_name_callback_t)(const pm_string_t *name, void *data); +typedef struct { + /** The call node wrapping the regular expression node (for =~). */ + pm_call_node_t *call; + + /** The match write node being built, or NULL if no captures found yet. */ + pm_match_write_node_t *match; + + /** The list of capture names found so far (for deduplication). */ + pm_constant_id_list_t names; +} pm_regexp_name_data_t; /** - * This callback is called by pm_regexp_parse() when a parse error is found. + * Callback invoked by pm_regexp_parse() for each named capture group found. + * + * @param parser The main parser. + * @param name The name of the capture group. + * @param shared Whether the source content is shared (impacts constant storage). + * @param data The accumulation state for named captures. */ -typedef void (*pm_regexp_error_callback_t)(const uint8_t *start, const uint8_t *end, const char *message, void *data); +typedef void (*pm_regexp_name_callback_t)(pm_parser_t *parser, const pm_string_t *name, bool shared, pm_regexp_name_data_t *data); /** - * Parse a regular expression. + * Parse a regular expression, validate its encoding, and optionally extract + * named capture groups. Returns the encoding flags to set on the node. * * @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 extended_mode Whether to parse the regular expression in extended mode. + * @param node The regular expression node to parse and validate. * @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. + * @param name_data The optional accumulation state for named captures. + * @return The encoding flags to set on the node (e.g., FORCED_UTF8_ENCODING). + */ +PRISM_EXPORTED_FUNCTION pm_node_flags_t pm_regexp_parse(pm_parser_t *parser, pm_regular_expression_node_t *node, pm_regexp_name_callback_t name_callback, pm_regexp_name_data_t *name_data); + +/** + * Parse an interpolated regular expression for named capture groups only. + * No encoding validation is performed. + * + * @param parser The parser that is currently being used. + * @param source The source content to parse. + * @param size The length of the source content. + * @param shared Whether the source points into the parser's source buffer. + * @param extended_mode Whether or not the regular expression is in extended mode. + * @param name_callback The callback to call when a named capture group is found. + * @param name_data The accumulation state for named captures. */ -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); +void pm_regexp_parse_named_captures(pm_parser_t *parser, const uint8_t *source, size_t size, bool shared, bool extended_mode, pm_regexp_name_callback_t name_callback, pm_regexp_name_data_t *name_data); #endif diff --git a/include/prism/static_literals.h b/include/prism/static_literals.h index 0f8eb43bfa..6d73e5d04f 100644 --- a/include/prism/static_literals.h +++ b/include/prism/static_literals.h @@ -8,7 +8,7 @@ #include "prism/defines.h" #include "prism/ast.h" -#include "prism/util/pm_newline_list.h" +#include "prism/util/pm_line_offset_list.h" #include #include @@ -91,7 +91,7 @@ typedef struct { /** * Add a node to the set of static literals. * - * @param newline_list The list of newline offsets to use to calculate lines. + * @param line_offsets The list of newline offsets to use to calculate lines. * @param start The start of the source being parsed. * @param start_line The line number that the parser starts on. * @param literals The set of static literals to add the node to. @@ -99,7 +99,7 @@ typedef struct { * @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, const uint8_t *start, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace); +pm_node_t * pm_static_literals_add(const pm_line_offset_list_t *line_offsets, const uint8_t *start, 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. @@ -112,12 +112,12 @@ void pm_static_literals_free(pm_static_literals_t *literals); * Create a string-based representation of the given static literal. * * @param buffer The buffer to write the string to. - * @param newline_list The list of newline offsets to use to calculate lines. + * @param line_offsets The list of newline offsets to use to calculate lines. * @param start The start of the source being parsed. * @param start_line The line number that the parser starts on. * @param encoding_name The name of the encoding of the source being parsed. * @param node The node to create a string representation of. */ -void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_newline_list_t *newline_list, const uint8_t *start, int32_t start_line, const char *encoding_name, const pm_node_t *node); +void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, const char *encoding_name, const pm_node_t *node); #endif diff --git a/include/prism/util/pm_arena.h b/include/prism/util/pm_arena.h new file mode 100644 index 0000000000..f376d13459 --- /dev/null +++ b/include/prism/util/pm_arena.h @@ -0,0 +1,89 @@ +/** + * @file pm_arena.h + * + * A bump allocator for the prism parser. + */ +#ifndef PRISM_ARENA_H +#define PRISM_ARENA_H + +#include "prism/defines.h" + +#include +#include +#include +#include + +/** + * A single block of memory in the arena. Blocks are linked via prev pointers so + * they can be freed by walking the chain. + */ +typedef struct pm_arena_block { + /** The previous block in the chain (for freeing). */ + struct pm_arena_block *prev; + + /** The total usable bytes in data[]. */ + size_t capacity; + + /** The number of bytes consumed so far. */ + size_t used; + + /** The block's data. */ + char data[PM_FLEX_ARY_LEN]; +} pm_arena_block_t; + +/** + * A bump allocator. Allocations are made by bumping a pointer within the + * current block. When a block is full, a new block is allocated and linked to + * the previous one. All blocks are freed at once by walking the chain. + */ +typedef struct { + /** The active block (allocate from here). */ + pm_arena_block_t *current; + + /** The number of blocks allocated. */ + size_t block_count; +} pm_arena_t; + +/** + * Allocate memory from the arena. The returned memory is NOT zeroed. This + * function is infallible — it aborts on allocation failure. + * + * @param arena The arena to allocate from. + * @param size The number of bytes to allocate. + * @param alignment The required alignment (must be a power of 2). + * @returns A pointer to the allocated memory. + */ +void * pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment); + +/** + * Allocate zero-initialized memory from the arena. This function is infallible + * — it aborts on allocation failure. + * + * @param arena The arena to allocate from. + * @param size The number of bytes to allocate. + * @param alignment The required alignment (must be a power of 2). + * @returns A pointer to the allocated, zero-initialized memory. + */ +void * pm_arena_zalloc(pm_arena_t *arena, size_t size, size_t alignment); + +/** + * Allocate memory from the arena and copy the given data into it. This is a + * convenience wrapper around pm_arena_alloc + memcpy. + * + * @param arena The arena to allocate from. + * @param src The source data to copy. + * @param size The number of bytes to allocate and copy. + * @param alignment The required alignment (must be a power of 2). + * @returns A pointer to the allocated copy. + */ +void * pm_arena_memdup(pm_arena_t *arena, const void *src, size_t size, size_t alignment); + +/** + * Free all blocks in the arena. After this call, all pointers returned by + * pm_arena_alloc and pm_arena_zalloc are invalid. + * + * @param arena The arena to free. + */ +PRISM_EXPORTED_FUNCTION void pm_arena_free(pm_arena_t *arena); + +#endif diff --git a/include/prism/util/pm_char.h b/include/prism/util/pm_char.h index b213e8edee..ab1f513a66 100644 --- a/include/prism/util/pm_char.h +++ b/include/prism/util/pm_char.h @@ -7,7 +7,7 @@ #define PRISM_CHAR_H #include "prism/defines.h" -#include "prism/util/pm_newline_list.h" +#include "prism/util/pm_line_offset_list.h" #include #include @@ -30,13 +30,13 @@ size_t pm_strspn_whitespace(const uint8_t *string, ptrdiff_t length); * * @param string The string to search. * @param length The maximum number of characters to search. - * @param newline_list The list of newlines to populate. + * @param line_offsets The list of newlines to populate. * @param start_offset The offset at which the string occurs in the source, for * the purpose of tracking newlines. * @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, uint32_t start_offset); +size_t pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_line_offset_list_t *line_offsets, uint32_t start_offset); /** * 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 6df23f8f50..1d4922a661 100644 --- a/include/prism/util/pm_constant_pool.h +++ b/include/prism/util/pm_constant_pool.h @@ -11,6 +11,7 @@ #define PRISM_CONSTANT_POOL_H #include "prism/defines.h" +#include "prism/util/pm_arena.h" #include #include @@ -54,20 +55,20 @@ void pm_constant_id_list_init(pm_constant_id_list_t *list); /** * Initialize a list of constant ids with a given capacity. * + * @param arena The arena to allocate from. * @param list The list to initialize. * @param capacity The initial capacity of the list. */ -void pm_constant_id_list_init_capacity(pm_constant_id_list_t *list, size_t capacity); +void pm_constant_id_list_init_capacity(pm_arena_t *arena, pm_constant_id_list_t *list, size_t capacity); /** - * Append a constant id to a list of constant ids. Returns false if any - * potential reallocations fail. + * Append a constant id to a list of constant ids. * + * @param arena The arena to allocate from. * @param list The list to append to. * @param id The id to append. - * @return Whether the append succeeded. */ -bool pm_constant_id_list_append(pm_constant_id_list_t *list, pm_constant_id_t id); +void pm_constant_id_list_append(pm_arena_t *arena, pm_constant_id_list_t *list, pm_constant_id_t id); /** * Insert a constant id into a list of constant ids at the specified index. @@ -87,13 +88,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); -/** - * Free the memory associated with a list of constant ids. - * - * @param list The list to free. - */ -void pm_constant_id_list_free(pm_constant_id_list_t *list); - /** * The type of bucket in the constant pool hash map. This determines how the * bucket should be freed. diff --git a/include/prism/util/pm_newline_list.h b/include/prism/util/pm_line_offset_list.h similarity index 64% rename from include/prism/util/pm_newline_list.h rename to include/prism/util/pm_line_offset_list.h index dd3e625089..968eeae52d 100644 --- a/include/prism/util/pm_newline_list.h +++ b/include/prism/util/pm_line_offset_list.h @@ -1,5 +1,5 @@ /** - * @file pm_newline_list.h + * @file pm_line_offset_list.h * * A list of byte offsets of newlines in a string. * @@ -11,8 +11,8 @@ * end column on every node in addition to the offsets that we already store, * but that would be quite a lot of memory overhead. */ -#ifndef PRISM_NEWLINE_LIST_H -#define PRISM_NEWLINE_LIST_H +#ifndef PRISM_LINE_OFFSET_LIST_H +#define PRISM_LINE_OFFSET_LIST_H #include "prism/defines.h" @@ -22,8 +22,8 @@ #include /** - * A list of offsets of newlines in a string. The offsets are assumed to be - * sorted/inserted in ascending order. + * A list of offsets of the start of lines in a string. The offsets are assumed + * to be sorted/inserted in ascending order. */ typedef struct { /** The number of offsets in the list. */ @@ -34,7 +34,7 @@ typedef struct { /** The list of offsets. */ uint32_t *offsets; -} pm_newline_list_t; +} pm_line_offset_list_t; /** * A line and column in a string. @@ -48,32 +48,32 @@ typedef struct { } pm_line_column_t; /** - * Initialize a new newline list with the given capacity. Returns true if the - * allocation of the offsets succeeds, otherwise returns false. + * Initialize a new line offset list with the given capacity. Returns true if + * the allocation of the offsets succeeds, otherwise returns false. * * @param list The list to initialize. * @param capacity The initial capacity of the list. * @return True if the allocation of the offsets succeeds, otherwise false. */ -bool pm_newline_list_init(pm_newline_list_t *list, size_t capacity); +bool pm_line_offset_list_init(pm_line_offset_list_t *list, size_t capacity); /** - * Clear out the newlines that have been appended to the list. + * Clear out the offsets that have been appended to the list. * * @param list The list to clear. */ -void pm_newline_list_clear(pm_newline_list_t *list); +void pm_line_offset_list_clear(pm_line_offset_list_t *list); /** - * Append a new offset to the newline list. Returns true if the reallocation of - * the offsets succeeds (if one was necessary), otherwise returns false. + * Append a new offset to the list. Returns true if the reallocation of the + * offsets succeeds (if one was necessary), otherwise returns false. * * @param list The list to append to. * @param cursor The offset to append. * @return True if the reallocation of the offsets succeeds (if one was * necessary), otherwise false. */ -bool pm_newline_list_append(pm_newline_list_t *list, uint32_t cursor); +bool pm_line_offset_list_append(pm_line_offset_list_t *list, uint32_t cursor); /** * Returns the line of the given offset. If the offset is not in the list, the @@ -84,7 +84,7 @@ bool pm_newline_list_append(pm_newline_list_t *list, uint32_t cursor); * @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, uint32_t cursor, int32_t start_line); +int32_t pm_line_offset_list_line(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); /** * Returns the line and column of the given offset. If the offset is not in the @@ -96,13 +96,13 @@ int32_t pm_newline_list_line(const pm_newline_list_t *list, uint32_t cursor, int * @param start_line The line to start counting from. * @return The line and column of the given offset. */ -pm_line_column_t pm_newline_list_line_column(const pm_newline_list_t *list, uint32_t cursor, int32_t start_line); +PRISM_EXPORTED_FUNCTION pm_line_column_t pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); /** - * Free the internal memory allocated for the newline list. + * Free the internal memory allocated for the list. * * @param list The list to free. */ -void pm_newline_list_free(pm_newline_list_t *list); +void pm_line_offset_list_free(pm_line_offset_list_t *list); #endif diff --git a/include/prism/util/pm_string.h b/include/prism/util/pm_string.h index d8456ff294..76942180b6 100644 --- a/include/prism/util/pm_string.h +++ b/include/prism/util/pm_string.h @@ -94,7 +94,7 @@ void pm_string_owned_init(pm_string_t *string, uint8_t *source, size_t length); * @param source The source of the string. * @param length The length of the string. */ -void pm_string_constant_init(pm_string_t *string, const char *source, size_t length); +PRISM_EXPORTED_FUNCTION 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 diff --git a/java-wasm/README.md b/java-wasm/README.md new file mode 100644 index 0000000000..1c9eaee85e --- /dev/null +++ b/java-wasm/README.md @@ -0,0 +1,29 @@ +This dir contains the chicory-prism artifact, a version of prism compiled to WASM and then AOT compiled to JVM bytecode by the Chicory project. + +## Building + +Generate the templated sources: + +``` +PRISM_EXCLUDE_PRETTYPRINT=1 PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS=1 PRISM_JAVA_BACKEND=jruby bundle exec rake templates +``` + +Compile to WASM using WASI SDK version 25: + +``` +make java-wasm WASI_SDK_PATH=.../wasi-sdk-25.0-arm64-macos +``` + +Build the AOT-compiled machine and wrapper library: + +``` +mvn -f java-wasm/pom.xml clean package +``` + +This should build the chicory-wasm jar file and pass some basic tests. + +The jar will be under `java-wasm/target/chicory-prism-#####-SNAPSHOT.jar` or can be installed by using `install` instead of `pacakge` in the `mvn` command line above. + +## Releasing + +Pass `-Prelease` to enable release plugins for Maven Central (optional for snapshots) and run the `deploy` target for `mvn`. diff --git a/java-wasm/perf-test/.gitignore b/java-wasm/perf-test/.gitignore new file mode 100644 index 0000000000..60286da241 --- /dev/null +++ b/java-wasm/perf-test/.gitignore @@ -0,0 +1 @@ +profile.html diff --git a/java-wasm/perf-test/bench.sh b/java-wasm/perf-test/bench.sh new file mode 100755 index 0000000000..1ad69239b1 --- /dev/null +++ b/java-wasm/perf-test/bench.sh @@ -0,0 +1,6 @@ +#! /bin/bash +set -euxo pipefail + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +jbang --fresh --deps org.openjdk.jmh:jmh-generator-annprocess:1.36 --javaagent=ap-loader@jvm-profiling-tools/ap-loader=start,event=cpu,file=${SCRIPT_DIR}/profile.html ${SCRIPT_DIR}/test \ No newline at end of file diff --git a/java-wasm/perf-test/test b/java-wasm/perf-test/test new file mode 100755 index 0000000000..f2d5492bc4 --- /dev/null +++ b/java-wasm/perf-test/test @@ -0,0 +1,97 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? + +//DEPS org.jruby:chicory-prism:0.0.1-SNAPSHOT +//DEPS org.jruby:jruby-complete:10.0.2.0 + +import static java.lang.System.*; + +import java.io.DataInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.EnumSet; + +import org.jruby.Ruby; + +import org.jruby.parser.prism.wasm.Prism; +import org.ruby_lang.prism.ParsingOptions; + +public class test { + + final static String[] JRUBY_BOOT_FILES = { + "jruby/java.rb", + "jruby/java/core_ext.rb", + "jruby/java/core_ext/object.rb", + "jruby/java/java_ext.rb", + "jruby/kernel.rb", + "jruby/kernel/signal.rb", + "jruby/kernel/kernel.rb", + "jruby/kernel/proc.rb", + "jruby/kernel/process.rb", + "jruby/kernel/enumerator.rb", + "jruby/kernel/enumerable.rb", + "jruby/kernel/io.rb", + "jruby/kernel/gc.rb", + "jruby/kernel/range.rb", + "jruby/kernel/file.rb", + "jruby/kernel/method.rb", + "jruby/kernel/thread.rb", + "jruby/kernel/integer.rb", + "jruby/kernel/time.rb", + "jruby/preludes.rb", + "jruby/kernel/prelude.rb", + "jruby/kernel/enc_prelude.rb", + "META-INF/jruby.home/lib/ruby/stdlib/unicode_normalize.rb", + "jruby/kernel/gem_prelude.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rbconfig.rb", + "jruby/kernel/rbconfig.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/compatibility.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/defaults.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/deprecate.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/errors.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/target_rbconfig.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/exceptions.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/unknown_command_spell_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/specification.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/basic_specification.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/stub_specification.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/platform.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/specification_record.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/util/list.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/requirement.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/version.rb", + }; + + public static void main(String... args) throws Exception { + out.println("Starting"); + var count = 100; + + var prism = new Prism(); + byte[] src = new byte[1024 * 1024]; + + for (int i = 0; i < count; i++) { + for (var file : JRUBY_BOOT_FILES) { + byte[] options = ParsingOptions.serialize( + file.getBytes(StandardCharsets.UTF_8), + 1, + "UTF-8".getBytes(StandardCharsets.UTF_8), + false, + EnumSet.noneOf(ParsingOptions.CommandLine.class), + ParsingOptions.SyntaxVersion.LATEST, + false, + false, + false, + new byte[][][]{} + ); + + try (InputStream fileIn = Ruby.getClassLoader().getResourceAsStream(file)) { + DataInputStream dis = new DataInputStream(fileIn); + int read = dis.read(src); + prism.serialize(options, src, read); + } + } + } + + out.println("End"); + } +} diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index f69028bfd8..2e6baaf7ca 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -2,21 +2,21 @@ 4.0.0 - com.prism - java-prism - 999-SNAPSHOT + org.ruby-lang + prism-parser + 0.0.1-SNAPSHOT Java Prism - Pure Java Prism interpreting WASM + Java API for the Prism Ruby language parser UTF-8 UTF-8 - 11 - 11 + 21 + 21 - 1.6.1 - 6.0.2 + 1.7.3 + 6.0.3 @@ -59,8 +59,74 @@ annotations provided + + org.jruby + jruby-stdlib + 10.0.4.0 + test + + + org.jruby + jruby-base + 10.0.4.0 + provided + + + + release + + + + maven-source-plugin + + + attach-sources + + jar-no-fork + + + + + + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + none + + + + maven-gpg-plugin + 3.2.4 + + + sign-artifacts + verify + + sign + + + + + + --pinentry-mode + loopback + + + + + + + + @@ -79,9 +145,9 @@ org.apache.maven.plugins maven-compiler-plugin - 3.14.1 + 3.15.0 - 11 + 21 com.dylibso.chicory @@ -92,26 +158,26 @@ - org.apache.maven.plugins - maven-surefire-plugin - 3.5.4 + org.apache.maven.plugins + maven-surefire-plugin + 3.5.5 org.codehaus.mojo build-helper-maven-plugin 3.6.1 - - generate-sources - - add-source - - - - ../java - - - + + generate-sources + + add-source + + + + ../java + + + @@ -125,12 +191,21 @@ compile - org.prism.PrismModule + org.ruby_lang.prism.wasm.PrismParser src/test/resources/prism.wasm + + org.sonatype.central + central-publishing-maven-plugin + 0.7.0 + true + + central + + diff --git a/java-wasm/src/main/java-templates/org/prism/WasmResource.java b/java-wasm/src/main/java-templates/org/ruby_lang/prism/wasm/WasmResource.java similarity index 83% rename from java-wasm/src/main/java-templates/org/prism/WasmResource.java rename to java-wasm/src/main/java-templates/org/ruby_lang/prism/wasm/WasmResource.java index 48f2671714..785c2bd916 100644 --- a/java-wasm/src/main/java-templates/org/prism/WasmResource.java +++ b/java-wasm/src/main/java-templates/org/ruby_lang/prism/wasm/WasmResource.java @@ -1,4 +1,4 @@ -package org.prism; +package org.ruby_lang.prism.wasm; public final class WasmResource { public static final String absoluteFile = "file://${project.basedir}/src/test/resources/prism.wasm"; diff --git a/java-wasm/src/main/java/org/prism/Prism.java b/java-wasm/src/main/java/org/prism/Prism.java deleted file mode 100644 index 9578a441a1..0000000000 --- a/java-wasm/src/main/java/org/prism/Prism.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.prism; - -import com.dylibso.chicory.runtime.ByteArrayMemory; -import com.dylibso.chicory.annotations.WasmModuleInterface; -import com.dylibso.chicory.runtime.ImportValues; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasi.WasiOptions; -import com.dylibso.chicory.wasi.WasiPreview1; -import com.dylibso.chicory.wasm.types.MemoryLimits; - -import java.nio.charset.StandardCharsets; - -@WasmModuleInterface(WasmResource.absoluteFile) -public class Prism implements AutoCloseable { - private final WasiPreview1 wasi; - private final Instance instance; - private final Prism_ModuleExports exports; - - public Prism() { - this(WasiOptions.builder().build()); - } - public Prism(WasiOptions wasiOpts) { - wasi = WasiPreview1.builder().withOptions(wasiOpts).build(); - instance = Instance.builder(PrismModule.load()) - .withMemoryFactory(limits -> new ByteArrayMemory(new MemoryLimits(10, MemoryLimits.MAX_PAGES))) - .withMachineFactory(PrismModule::create) - .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) - .build(); - exports = new Prism_ModuleExports(instance); - } - - public Prism_ModuleExports exports() { - return exports; - } - - public byte[] serialize(byte[] packedOptions, byte[] source, int sourceLength) { - int sourcePointer = 0; - int optionsPointer = 0; - int bufferPointer = 0; - int resultPointer = 0; - byte[] result; - try { - sourcePointer = exports.calloc(1, sourceLength); - exports.memory().write(sourcePointer, source); - - optionsPointer = exports.calloc(1, packedOptions.length); - exports.memory().write(optionsPointer, packedOptions); - - bufferPointer = exports.calloc(exports.pmBufferSizeof(), 1); - exports.pmBufferInit(bufferPointer); - - exports.pmSerializeParse(bufferPointer, sourcePointer, sourceLength, optionsPointer); - - resultPointer = exports.pmBufferValue(bufferPointer); - - result = instance.memory().readBytes( - resultPointer, - exports.pmBufferLength(bufferPointer)); - } finally { - if (sourcePointer != 0) { - exports.free(sourcePointer); - } - if (optionsPointer != 0) { - exports.free(optionsPointer); - } - if (bufferPointer != 0) { - exports.free(bufferPointer); - } - if (resultPointer != 0) { - exports.free(resultPointer); - } - } - - return result; - } - - public ParseResult serializeParse(byte[] packedOptions, String source) { - var sourceBytes = source.getBytes(StandardCharsets.US_ASCII); - - byte[] result = serialize(packedOptions, sourceBytes, sourceBytes.length); - - return Loader.load(result, sourceBytes); - } - - @Override - public void close() { - if (wasi != null) { - wasi.close(); - } - } -} diff --git a/java-wasm/src/main/java/org/ruby_lang/prism/wasm/Prism.java b/java-wasm/src/main/java/org/ruby_lang/prism/wasm/Prism.java new file mode 100644 index 0000000000..fece175920 --- /dev/null +++ b/java-wasm/src/main/java/org/ruby_lang/prism/wasm/Prism.java @@ -0,0 +1,160 @@ +package org.ruby_lang.prism.wasm; + +import com.dylibso.chicory.annotations.WasmModuleInterface; +import com.dylibso.chicory.runtime.ByteArrayMemory; +import com.dylibso.chicory.runtime.ImportValues; +import com.dylibso.chicory.runtime.Instance; +import com.dylibso.chicory.wasi.WasiOptions; +import com.dylibso.chicory.wasi.WasiPreview1; +import org.ruby_lang.prism.Loader; +import org.ruby_lang.prism.ParseResult; + +import java.nio.charset.StandardCharsets; + +@WasmModuleInterface(WasmResource.absoluteFile) +public class Prism implements AutoCloseable { + private final WasiPreview1 wasi; + protected final Prism_ModuleExports exports; + private final Instance instance; + + public Prism() { + this(WasiOptions.builder().build()); + } + + public Prism(WasiOptions wasiOpts) { + wasi = WasiPreview1.builder().withOptions(wasiOpts).build(); + instance = Instance.builder(PrismParser.load()) + .withMemoryFactory(ByteArrayMemory::new) + .withMachineFactory(PrismParser::create) + .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) + .build(); + exports = new Prism_ModuleExports(instance); + } + + public String version() { + int versionPointer = exports.pmVersion(); + int length = exports.strchr(versionPointer, 0); + + return new String(instance.memory().readBytes(versionPointer, length - versionPointer)); + } + + public byte[] parse(byte[] sourceBytes, byte[] packedOptions) { + try ( + Buffer buffer = new Buffer(); + Source source = new Source(sourceBytes, 0, sourceBytes.length); + Options options = new Options(packedOptions)) { + + return parse(buffer, source, options); + } + } + + public byte[] lex(byte[] sourceBytes, byte[] packedOptions) { + try ( + Buffer buffer = new Buffer(); + Source source = new Source(sourceBytes, 0, sourceBytes.length); + Options options = new Options(packedOptions)) { + + return lex(buffer, source, options); + } + } + + public byte[] parse(byte[] sourceBytes, int sourceOffset, int sourceLength, byte[] packedOptions) { + try ( + Buffer buffer = new Buffer(); + Source source = new Source(sourceBytes, sourceOffset, sourceLength); + Options options = new Options(packedOptions)) { + + return parse(buffer, source, options); + } + } + + public byte[] parse(Buffer buffer, Source source, Options options) { + exports.pmSerializeParse( + buffer.pointer, source.pointer, source.length, options.pointer); + + return buffer.read(); + } + + public byte[] lex(Buffer buffer, Source source, Options options) { + exports.pmSerializeLex( + buffer.pointer, source.pointer, source.length, options.pointer); + + return buffer.read(); + } + + public class Buffer implements AutoCloseable { + final int pointer; + + Buffer() { + pointer = exports.calloc(exports.pmBufferSizeof(), 1); + clear(); + } + + public void clear() { + exports.pmBufferClear(pointer); + } + + public void close() { + exports.pmBufferFree(pointer); + exports.free(pointer); + } + + public byte[] read() { + return instance.memory().readBytes( + exports.pmBufferValue(pointer), + exports.pmBufferLength(pointer)); + } + } + + class Source implements AutoCloseable{ + final int pointer; + final int length; + + Source(int length) { + pointer = exports.calloc(1, length); + this.length = length; + } + + Source(byte[] bytes, int offset, int length) { + this(length + 1); + write(bytes, offset, length); + } + + public void write(byte[] bytes, int offset, int length) { + assert length + 1 <= this.length; + instance.memory().write(pointer, bytes, offset, length); + instance.memory().writeByte(pointer + length, (byte) 0); + } + + public void close() { + exports.free(pointer); + } + } + + class Options implements AutoCloseable { + final int pointer; + + Options(byte[] packedOptions) { + int pointer = exports.calloc(1, packedOptions.length); + instance.memory().write(pointer, packedOptions); + this.pointer = pointer; + } + + public void close() { + exports.free(pointer); + } + } + + public ParseResult serializeParse(byte[] packedOptions, String source) { + var sourceBytes = source.getBytes(StandardCharsets.ISO_8859_1); + byte[] result = parse(sourceBytes, 0, sourceBytes.length, packedOptions); + return Loader.load(result, sourceBytes); + } + + @Override + public void close() { + if (wasi != null) { + wasi.close(); + } + } +} diff --git a/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java b/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java new file mode 100644 index 0000000000..12c3e4f74d --- /dev/null +++ b/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java @@ -0,0 +1,143 @@ +package org.jruby.parser.prism; + +import org.jruby.Ruby; +import org.junit.jupiter.api.Test; +import org.ruby_lang.prism.ParsingOptions; +import org.ruby_lang.prism.wasm.Prism; + +import java.io.DataInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.EnumSet; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class JRubyTest { + // TODO: This list is hardcoded from JRuby 10.0.4.0 and should be made dynamic + final static String[] JRUBY_BOOT_FILES = { + "jruby/java.rb", + "jruby/java/core_ext.rb", + "jruby/java/core_ext/object.rb", + "jruby/java/java_ext.rb", + "jruby/kernel.rb", + "jruby/kernel/signal.rb", + "jruby/kernel/kernel.rb", + "jruby/kernel/proc.rb", + "jruby/kernel/process.rb", + "jruby/kernel/enumerator.rb", + "jruby/kernel/enumerable.rb", + "jruby/kernel/io.rb", + "jruby/kernel/gc.rb", + "jruby/kernel/range.rb", + "jruby/kernel/file.rb", + "jruby/kernel/method.rb", + "jruby/kernel/thread.rb", + "jruby/kernel/integer.rb", + "jruby/kernel/time.rb", + "jruby/kernel/string.rb", + "jruby/preludes.rb", + "jruby/kernel/prelude.rb", + "jruby/kernel/gem_prelude.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rbconfig.rb", + "jruby/kernel/rbconfig.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/compatibility.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/defaults.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/deprecate.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/errors.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/target_rbconfig.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/exceptions.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/unknown_command_spell_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/specification.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/basic_specification.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/stub_specification.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/platform.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/specification_record.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/util/list.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/requirement.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/version.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/defaults/operating_system.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/defaults/jruby.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/util.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/dependency.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/core_ext/kernel_gem.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/core_ext/kernel_warn.rb", + "META-INF/jruby.home/lib/ruby/stdlib/monitor.rb", + "META-INF/jruby.home/lib/ruby/stdlib/bundled_gems.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/path_support.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/version.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/core_ext/name_error.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/levenshtein.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/jaro_winkler.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/name_error_checkers.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/name_error_checkers/class_name_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/method_name_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/key_error_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/null_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/require_path_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/tree_spell_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/pattern_key_name_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/formatter.rb", + "META-INF/jruby.home/lib/ruby/stdlib/syntax_suggest/core_ext.rb", + }; + + private class TestingPrism extends Prism { + TestingPrism() { + super(); + } + + public int memPages() { + return exports.memory().pages(); + } + } + + @Test + public void jrubyReproducer() throws Exception { + var prism = new TestingPrism(); + + for (int i = 0; i < 3; i++) { + basicJRubyTest(prism); + } + var memoryPagesBefore = prism.memPages(); + for (int i = 0; i < 100; i++) { + var before = System.currentTimeMillis(); + + basicJRubyTest(prism); + + var after = System.currentTimeMillis(); + System.out.println("Elapsed: " + (after - before)); + } + var memoryPagesAfter = prism.memPages(); + assertEquals(memoryPagesBefore, memoryPagesAfter); + } + + private static void basicJRubyTest(Prism prism) throws Exception { + byte[] src = new byte[1024 * 1024]; + + for (var file : JRUBY_BOOT_FILES) { + byte[] options = ParsingOptions.serialize( + file.getBytes(StandardCharsets.UTF_8), + 1, + "UTF-8".getBytes(StandardCharsets.UTF_8), + false, + EnumSet.noneOf(ParsingOptions.CommandLine.class), + ParsingOptions.SyntaxVersion.LATEST, + false, + false, + false, + new byte[][][]{} + ); + + try (InputStream fileIn = Ruby.getClassLoader().getResourceAsStream(file)) { + assertNotNull(fileIn, "Could not find file: " + file); + DataInputStream dis = new DataInputStream(fileIn); + int read = dis.read(src); + prism.parse(src, 0, read, options); + } + } + } +} diff --git a/java-wasm/src/test/java/org/jruby/parser/prism/WASMTest.java b/java-wasm/src/test/java/org/jruby/parser/prism/WASMTest.java new file mode 100644 index 0000000000..9e2711cd6b --- /dev/null +++ b/java-wasm/src/test/java/org/jruby/parser/prism/WASMTest.java @@ -0,0 +1,98 @@ +package org.jruby.parser.prism; + +import org.junit.jupiter.api.Test; +import org.ruby_lang.prism.ParseResult; +import org.ruby_lang.prism.ParsingOptions; +import org.ruby_lang.prism.wasm.Prism; + +import java.util.EnumSet; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class WASMTest { + + private static final byte[] packedOptions = ParsingOptions.serialize( + new byte[] {}, + 1, + new byte[] {}, + false, + EnumSet.noneOf(ParsingOptions.CommandLine.class), + ParsingOptions.SyntaxVersion.LATEST, + false, + false, + false, + new byte[][][] {} + ); + + @Test + public void test1() { + // The Ruby source code to be processed + var source = "1 + 1"; + + ParseResult pr = null; + try (Prism prism = new Prism()) { + pr = prism.serializeParse(packedOptions, source); + } + + assertEquals(1, pr.value.childNodes().length); + System.out.println("Nodes:"); + System.out.println(pr.value.childNodes()[0]); + assertTrue(pr.value.childNodes()[0].toString().contains("IntegerNode")); + } + + @Test + public void test1Aot() { + // The Ruby source code to be processed + var source = "1 + 1"; + + ParseResult pr = null; + try (Prism prism = new Prism()) { + pr = prism.serializeParse(packedOptions, source); + } + + assertEquals(1, pr.value.childNodes().length); + System.out.println("Nodes:"); + System.out.println(pr.value.childNodes()[0]); + assertTrue(pr.value.childNodes()[0].toString().contains("IntegerNode")); + } + + @Test + public void test2() { + // The Ruby source code to be processed + var source = "puts \"h\ne\nl\nl\no\n\""; + + ParseResult pr = null; + try (Prism prism = new Prism()) { + pr = prism.serializeParse(packedOptions, source); + } + + assertEquals(1, pr.value.childNodes().length); + System.out.println("Nodes:"); + System.out.println(pr.value.childNodes()[0]); + assertTrue(pr.value.childNodes()[0].toString().contains("CallNode")); + } + + @Test + public void test2Aot() { + // The Ruby source code to be processed + var source = "puts \"h\ne\nl\nl\no\n\""; + + ParseResult pr = null; + try (Prism prism = new Prism()) { + pr = prism.serializeParse(packedOptions, source); + } + + assertEquals(1, pr.value.childNodes().length); + System.out.println("Nodes:"); + System.out.println(pr.value.childNodes()[0]); + assertTrue(pr.value.childNodes()[0].toString().contains("CallNode")); + } + + @Test + public void testVersion() { + try (Prism prism = new Prism()) { + assertEquals("1.9.0", prism.version()); + } + } +} diff --git a/java-wasm/src/test/java/org/prism/DummyTest.java b/java-wasm/src/test/java/org/prism/DummyTest.java deleted file mode 100644 index 9e49f1afdd..0000000000 --- a/java-wasm/src/test/java/org/prism/DummyTest.java +++ /dev/null @@ -1,154 +0,0 @@ -package org.prism; - -import com.dylibso.chicory.runtime.ImportValues; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasi.WasiOptions; -import com.dylibso.chicory.wasi.WasiPreview1; -import com.dylibso.chicory.wasm.Parser; -import com.dylibso.chicory.wasm.types.Value; -import org.junit.jupiter.api.Test; - -import java.nio.charset.StandardCharsets; -import java.util.EnumSet; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class DummyTest { - - private static final byte[] packedOptions = ParsingOptions.serialize( - new byte[] {}, - 1, - new byte[] {}, - false, - EnumSet.noneOf(ParsingOptions.CommandLine.class), - ParsingOptions.SyntaxVersion.LATEST, - false, - false, - false, - new byte[][][] {} - ); - - @Test - public void test1() { - WasiOptions wasiOpts = WasiOptions.builder().build(); - WasiPreview1 wasi = WasiPreview1.builder().withOptions(wasiOpts).build(); - var wasmPrism = Instance.builder(Parser.parse(DummyTest.class.getResourceAsStream("/prism.wasm"))) - .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) - .build(); - var memory = wasmPrism.memory(); - var calloc = wasmPrism.export("calloc"); - var pmSerializeParse = wasmPrism.export("pm_serialize_parse"); - var pmBufferInit = wasmPrism.export("pm_buffer_init"); - var pmBufferSizeof = wasmPrism.export("pm_buffer_sizeof"); - var pmBufferValue = wasmPrism.export("pm_buffer_value"); - var pmBufferLength = wasmPrism.export("pm_buffer_length"); - - // The Ruby source code to be processed - var source = "1 + 1"; - var sourceBytes = source.getBytes(StandardCharsets.US_ASCII); - - var sourcePointer = calloc.apply(1, source.length()); - memory.writeString((int) sourcePointer[0], source); - - var optionsPointer = calloc.apply(1, packedOptions.length); - memory.write((int) optionsPointer[0], packedOptions); - - var bufferPointer = calloc.apply(pmBufferSizeof.apply()[0], 1); - pmBufferInit.apply(bufferPointer); - - pmSerializeParse.apply( - bufferPointer[0], sourcePointer[0], source.length(), optionsPointer[0]); - - var result = memory.readBytes( - (int) pmBufferValue.apply(bufferPointer[0])[0], - (int) pmBufferLength.apply(bufferPointer[0])[0]); - - System.out.println("RESULT: " + new String(result)); - - ParseResult pr = Loader.load(result, sourceBytes); - - assertEquals(1, pr.value.childNodes().length); - System.out.println("Nodes:"); - System.out.println(pr.value.childNodes()[0]); - assertTrue(pr.value.childNodes()[0].toString().contains("IntegerNode")); - } - - @Test - public void test1Aot() { - // The Ruby source code to be processed - var source = "1 + 1"; - - ParseResult pr = null; - try (Prism prism = new Prism()) { - pr = prism.serializeParse(packedOptions, source); - } - - assertEquals(1, pr.value.childNodes().length); - System.out.println("Nodes:"); - System.out.println(pr.value.childNodes()[0]); - assertTrue(pr.value.childNodes()[0].toString().contains("IntegerNode")); - } - - @Test - public void test2() { - WasiOptions wasiOpts = WasiOptions.builder().build(); - WasiPreview1 wasi = WasiPreview1.builder().withOptions(wasiOpts).build(); - var wasmPrism = Instance.builder(Parser.parse(DummyTest.class.getResourceAsStream("/prism.wasm"))) - .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) - .build(); - var memory = wasmPrism.memory(); - var calloc = wasmPrism.export("calloc"); - var pmSerializeParse = wasmPrism.export("pm_serialize_parse"); - var pmBufferInit = wasmPrism.export("pm_buffer_init"); - var pmBufferSizeof = wasmPrism.export("pm_buffer_sizeof"); - var pmBufferValue = wasmPrism.export("pm_buffer_value"); - var pmBufferLength = wasmPrism.export("pm_buffer_length"); - - // The Ruby source code to be processed - var source = "puts \"h\ne\nl\nl\no\n\""; - var sourceBytes = source.getBytes(StandardCharsets.US_ASCII); - - var sourcePointer = calloc.apply(1, source.length()); - memory.writeString((int) sourcePointer[0], source); - - var optionsPointer = calloc.apply(1, packedOptions.length); - memory.write((int) optionsPointer[0], packedOptions); - - var bufferPointer = calloc.apply(pmBufferSizeof.apply()[0], 1); - pmBufferInit.apply(bufferPointer); - - pmSerializeParse.apply( - bufferPointer[0], sourcePointer[0], source.length(), optionsPointer[0]); - - var result = memory.readBytes( - (int) pmBufferValue.apply(bufferPointer[0])[0], - (int) pmBufferLength.apply(bufferPointer[0])[0]); - - System.out.println("RESULT: " + new String(result)); - - ParseResult pr = Loader.load(result, sourceBytes); - - assertEquals(1, pr.value.childNodes().length); - - System.out.println("Nodes:"); - System.out.println(pr.value.childNodes()[0]); - assertTrue(pr.value.childNodes()[0].toString().contains("CallNode")); - } - - @Test - public void test2Aot() { - // The Ruby source code to be processed - var source = "puts \"h\ne\nl\nl\no\n\""; - - ParseResult pr = null; - try (Prism prism = new Prism()) { - pr = prism.serializeParse(packedOptions, source); - } - - assertEquals(1, pr.value.childNodes().length); - System.out.println("Nodes:"); - System.out.println(pr.value.childNodes()[0]); - assertTrue(pr.value.childNodes()[0].toString().contains("CallNode")); - } -} diff --git a/java/org/prism/MarkNewlinesVisitor.java b/java/org/ruby_lang/prism/MarkNewlinesVisitor.java similarity index 98% rename from java/org/prism/MarkNewlinesVisitor.java rename to java/org/ruby_lang/prism/MarkNewlinesVisitor.java index 27ab8643e7..8d08424942 100644 --- a/java/org/prism/MarkNewlinesVisitor.java +++ b/java/org/ruby_lang/prism/MarkNewlinesVisitor.java @@ -1,4 +1,4 @@ -package org.prism; +package org.ruby_lang.prism; // Keep in sync with Ruby MarkNewlinesVisitor final class MarkNewlinesVisitor extends AbstractNodeVisitor { diff --git a/java/org/prism/ParseResult.java b/java/org/ruby_lang/prism/ParseResult.java similarity index 94% rename from java/org/prism/ParseResult.java rename to java/org/ruby_lang/prism/ParseResult.java index 144ea16e36..7931327b9a 100644 --- a/java/org/prism/ParseResult.java +++ b/java/org/ruby_lang/prism/ParseResult.java @@ -1,4 +1,4 @@ -package org.prism; +package org.ruby_lang.prism; // @formatter:off public final class ParseResult { @@ -69,14 +69,16 @@ public Warning(Nodes.WarningType type, String message, Nodes.Location location, public final Nodes.Location dataLocation; public final Error[] errors; public final Warning[] warnings; + public final boolean continuable; public final Nodes.Source source; - public ParseResult(Nodes.Node value, MagicComment[] magicComments, Nodes.Location dataLocation, Error[] errors, Warning[] warnings, Nodes.Source source) { + public ParseResult(Nodes.Node value, MagicComment[] magicComments, Nodes.Location dataLocation, Error[] errors, Warning[] warnings, boolean continuable, Nodes.Source source) { this.value = value; this.magicComments = magicComments; this.dataLocation = dataLocation; this.errors = errors; this.warnings = warnings; + this.continuable = continuable; this.source = source; } } diff --git a/java/org/prism/Parser.java b/java/org/ruby_lang/prism/Parser.java similarity index 92% rename from java/org/prism/Parser.java rename to java/org/ruby_lang/prism/Parser.java index 717c3e5179..5c60977d80 100644 --- a/java/org/prism/Parser.java +++ b/java/org/ruby_lang/prism/Parser.java @@ -1,4 +1,4 @@ -package org.prism; +package org.ruby_lang.prism; public abstract class Parser { diff --git a/java/org/prism/ParsingOptions.java b/java/org/ruby_lang/prism/ParsingOptions.java similarity index 99% rename from java/org/prism/ParsingOptions.java rename to java/org/ruby_lang/prism/ParsingOptions.java index be0a8a7dba..8990f72104 100644 --- a/java/org/prism/ParsingOptions.java +++ b/java/org/ruby_lang/prism/ParsingOptions.java @@ -1,4 +1,4 @@ -package org.prism; +package org.ruby_lang.prism; import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; diff --git a/javascript/src/parsePrism.js b/javascript/src/parsePrism.js index 38084da3f1..269f84c825 100644 --- a/javascript/src/parsePrism.js +++ b/javascript/src/parsePrism.js @@ -43,7 +43,7 @@ export function parsePrism(prism, source, options = {}) { prism.pm_serialize_parse(bufferPointer, sourcePointer, sourceArray.length, optionsPointer); const serializedView = new Uint8Array(prism.memory.buffer, prism.pm_buffer_value(bufferPointer), prism.pm_buffer_length(bufferPointer)); - const result = deserialize(sourceArray, serializedView); + const result = deserialize(serializedView); prism.pm_buffer_free(bufferPointer); prism.free(sourcePointer); diff --git a/lib/prism.rb b/lib/prism.rb index 781bd4bb01..6b34ab12bf 100644 --- a/lib/prism.rb +++ b/lib/prism.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true # :markup: markdown +#-- +# rbs_inline: enabled # The Prism Ruby parser. # @@ -21,7 +23,6 @@ module Prism autoload :InspectVisitor, "prism/inspect_visitor" autoload :LexCompat, "prism/lex_compat" autoload :MutationCompiler, "prism/mutation_compiler" - autoload :Pack, "prism/pack" autoload :Pattern, "prism/pattern" autoload :Reflection, "prism/reflection" autoload :Relocation, "prism/relocation" @@ -38,14 +39,16 @@ module Prism # Raised when requested to parse as the currently running Ruby version but Prism has no support for it. class CurrentVersionError < ArgumentError # Initialize a new exception for the given ruby version string. + #-- + #: (String version) -> void def initialize(version) message = +"invalid version: Requested to parse as `version: 'current'`; " - segments = + major, minor, = if version.match?(/\A\d+\.\d+.\d+\z/) version.split(".").map(&:to_i) end - if segments && ((segments[0] < 3) || (segments[0] == 3 && segments[1] < 3)) + if major && minor && ((major < 3) || (major == 3 && minor < 3)) message << " #{version} is below the minimum supported syntax." else message << " #{version} is unknown. Please update the `prism` gem." @@ -56,23 +59,53 @@ def initialize(version) end # :call-seq: - # Prism::lex_compat(source, **options) -> LexCompat::Result + # lex_compat(source, **options) -> LexCompat::Result # # Returns a parse result whose value is an array of tokens that closely - # resembles the return value of Ripper::lex. + # resembles the return value of Ripper.lex. # - # For supported options, see Prism::parse. + # For supported options, see Prism.parse. + #-- + #: (String source, **untyped options) -> LexCompat::Result def self.lex_compat(source, **options) LexCompat.new(source, **options).result # steep:ignore end # :call-seq: - # Prism::load(source, serialized, freeze) -> ParseResult + # load(source, serialized, freeze) -> ParseResult # # Load the serialized AST using the source as a reference into a tree. + #-- + #: (String source, String serialized, ?bool freeze) -> ParseResult def self.load(source, serialized, freeze = false) Serialize.load_parse(source, serialized, freeze) end + + # @rbs! + # VERSION: String + # BACKEND: :CEXT | :FFI + # + # interface _Stream + # def gets: (?Integer integer) -> (String | nil) + # end + # + # def self.parse: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseResult + # def self.profile: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> void + # def self.lex: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> LexResult + # def self.parse_lex: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseLexResult + # def self.dump: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> String + # def self.parse_comments: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> Array[Comment] + # def self.parse_success?: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool + # def self.parse_failure?: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool + # def self.parse_stream: (_Stream stream, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseResult + # def self.parse_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseResult + # def self.profile_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> void + # def self.lex_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> LexResult + # def self.parse_lex_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseLexResult + # def self.dump_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> String + # def self.parse_file_comments: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> Array[Comment] + # def self.parse_file_success?: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool + # def self.parse_file_failure?: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool end require_relative "prism/polyfill/byteindex" diff --git a/lib/prism/desugar_compiler.rb b/lib/prism/desugar_compiler.rb index 5d7d38d841..c64d03f64a 100644 --- a/lib/prism/desugar_compiler.rb +++ b/lib/prism/desugar_compiler.rb @@ -1,12 +1,18 @@ # frozen_string_literal: true # :markup: markdown +#-- +# rbs_inline: enabled module Prism class DesugarAndWriteNode # :nodoc: include DSL - attr_reader :node, :default_source, :read_class, :write_class, :arguments + attr_reader :node #: ClassVariableAndWriteNode | ConstantAndWriteNode | GlobalVariableAndWriteNode | InstanceVariableAndWriteNode | LocalVariableAndWriteNode + attr_reader :default_source #: Source + attr_reader :read_class, :write_class #: Symbol + attr_reader :arguments #: Hash[Symbol, untyped] + #: ((ClassVariableAndWriteNode | ConstantAndWriteNode | GlobalVariableAndWriteNode | InstanceVariableAndWriteNode | LocalVariableAndWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void def initialize(node, default_source, read_class, write_class, **arguments) @node = node @default_source = default_source @@ -16,6 +22,8 @@ def initialize(node, default_source, read_class, write_class, **arguments) end # Desugar `x &&= y` to `x && x = y` + #-- + #: () -> node def compile and_node( location: node.location, @@ -36,8 +44,12 @@ def compile class DesugarOrWriteDefinedNode # :nodoc: include DSL - attr_reader :node, :default_source, :read_class, :write_class, :arguments + attr_reader :node #: ClassVariableOrWriteNode | ConstantOrWriteNode | GlobalVariableOrWriteNode + attr_reader :default_source #: Source + attr_reader :read_class, :write_class #: Symbol + attr_reader :arguments #: Hash[Symbol, untyped] + #: ((ClassVariableOrWriteNode | ConstantOrWriteNode | GlobalVariableOrWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void def initialize(node, default_source, read_class, write_class, **arguments) @node = node @default_source = default_source @@ -47,6 +59,8 @@ def initialize(node, default_source, read_class, write_class, **arguments) end # Desugar `x ||= y` to `defined?(x) ? x : x = y` + #-- + #: () -> node def compile if_node( location: node.location, @@ -87,8 +101,12 @@ def compile class DesugarOperatorWriteNode # :nodoc: include DSL - attr_reader :node, :default_source, :read_class, :write_class, :arguments + attr_reader :node #: ClassVariableOperatorWriteNode | ConstantOperatorWriteNode | GlobalVariableOperatorWriteNode | InstanceVariableOperatorWriteNode | LocalVariableOperatorWriteNode + attr_reader :default_source #: Source + attr_reader :read_class, :write_class #: Symbol + attr_reader :arguments #: Hash[Symbol, untyped] + #: ((ClassVariableOperatorWriteNode | ConstantOperatorWriteNode | GlobalVariableOperatorWriteNode | InstanceVariableOperatorWriteNode | LocalVariableOperatorWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void def initialize(node, default_source, read_class, write_class, **arguments) @node = node @default_source = default_source @@ -98,6 +116,8 @@ def initialize(node, default_source, read_class, write_class, **arguments) end # Desugar `x += y` to `x = x + y` + #-- + #: () -> node def compile binary_operator_loc = node.binary_operator_loc.chop @@ -131,8 +151,12 @@ def compile class DesugarOrWriteNode # :nodoc: include DSL - attr_reader :node, :default_source, :read_class, :write_class, :arguments + attr_reader :node #: InstanceVariableOrWriteNode | LocalVariableOrWriteNode + attr_reader :default_source #: Source + attr_reader :read_class, :write_class #: Symbol + attr_reader :arguments #: Hash[Symbol, untyped] + #: ((InstanceVariableOrWriteNode | LocalVariableOrWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void def initialize(node, default_source, read_class, write_class, **arguments) @node = node @default_source = default_source @@ -142,6 +166,8 @@ def initialize(node, default_source, read_class, write_class, **arguments) end # Desugar `x ||= y` to `x || x = y` + #-- + #: () -> node def compile or_node( location: node.location, @@ -162,90 +188,105 @@ def compile private_constant :DesugarAndWriteNode, :DesugarOrWriteNode, :DesugarOrWriteDefinedNode, :DesugarOperatorWriteNode class ClassVariableAndWriteNode + #: () -> node def desugar # :nodoc: DesugarAndWriteNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile end end class ClassVariableOrWriteNode + #: () -> node def desugar # :nodoc: DesugarOrWriteDefinedNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile end end class ClassVariableOperatorWriteNode + #: () -> node def desugar # :nodoc: DesugarOperatorWriteNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile end end class ConstantAndWriteNode + #: () -> node def desugar # :nodoc: DesugarAndWriteNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile end end class ConstantOrWriteNode + #: () -> node def desugar # :nodoc: DesugarOrWriteDefinedNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile end end class ConstantOperatorWriteNode + #: () -> node def desugar # :nodoc: DesugarOperatorWriteNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile end end class GlobalVariableAndWriteNode + #: () -> node def desugar # :nodoc: DesugarAndWriteNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile end end class GlobalVariableOrWriteNode + #: () -> node def desugar # :nodoc: DesugarOrWriteDefinedNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile end end class GlobalVariableOperatorWriteNode + #: () -> node def desugar # :nodoc: DesugarOperatorWriteNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile end end class InstanceVariableAndWriteNode + #: () -> node def desugar # :nodoc: DesugarAndWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile end end class InstanceVariableOrWriteNode + #: () -> node def desugar # :nodoc: DesugarOrWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile end end class InstanceVariableOperatorWriteNode + #: () -> node def desugar # :nodoc: DesugarOperatorWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile end end class LocalVariableAndWriteNode + #: () -> node def desugar # :nodoc: DesugarAndWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile end end class LocalVariableOrWriteNode + #: () -> node def desugar # :nodoc: DesugarOrWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile end end class LocalVariableOperatorWriteNode + #: () -> node def desugar # :nodoc: DesugarOperatorWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile end @@ -254,137 +295,167 @@ def desugar # :nodoc: # DesugarCompiler is a compiler that desugars Ruby code into a more primitive # form. This is useful for consumers that want to deal with fewer node types. class DesugarCompiler < MutationCompiler - # @@foo &&= bar + # `@@foo &&= bar` # # becomes # - # @@foo && @@foo = bar + # `@@foo && @@foo = bar` + #-- + #: (ClassVariableAndWriteNode node) -> node def visit_class_variable_and_write_node(node) node.desugar end - # @@foo ||= bar + # `@@foo ||= bar` # # becomes # - # defined?(@@foo) ? @@foo : @@foo = bar + # `defined?(@@foo) ? @@foo : @@foo = bar` + #-- + #: (ClassVariableOrWriteNode node) -> node def visit_class_variable_or_write_node(node) node.desugar end - # @@foo += bar + # `@@foo += bar` # # becomes # - # @@foo = @@foo + bar + # `@@foo = @@foo + bar` + #-- + #: (ClassVariableOperatorWriteNode node) -> node def visit_class_variable_operator_write_node(node) node.desugar end - # Foo &&= bar + # `Foo &&= bar` # # becomes # - # Foo && Foo = bar + # `Foo && Foo = bar` + #-- + #: (ConstantAndWriteNode node) -> node def visit_constant_and_write_node(node) node.desugar end - # Foo ||= bar + # `Foo ||= bar` # # becomes # - # defined?(Foo) ? Foo : Foo = bar + # `defined?(Foo) ? Foo : Foo = bar` + #-- + #: (ConstantOrWriteNode node) -> node def visit_constant_or_write_node(node) node.desugar end - # Foo += bar + # `Foo += bar` # # becomes # - # Foo = Foo + bar + # `Foo = Foo + bar` + #-- + #: (ConstantOperatorWriteNode node) -> node def visit_constant_operator_write_node(node) node.desugar end - # $foo &&= bar + # `$foo &&= bar` # # becomes # - # $foo && $foo = bar + # `$foo && $foo = bar` + #-- + #: (GlobalVariableAndWriteNode node) -> node def visit_global_variable_and_write_node(node) node.desugar end - # $foo ||= bar + # `$foo ||= bar` # # becomes # - # defined?($foo) ? $foo : $foo = bar + # `defined?($foo) ? $foo : $foo = bar` + #-- + #: (GlobalVariableOrWriteNode node) -> node def visit_global_variable_or_write_node(node) node.desugar end - # $foo += bar + # `$foo += bar` # # becomes # - # $foo = $foo + bar + # `$foo = $foo + bar` + #-- + #: (GlobalVariableOperatorWriteNode node) -> node def visit_global_variable_operator_write_node(node) node.desugar end - # @foo &&= bar + # `@foo &&= bar` # # becomes # - # @foo && @foo = bar + # `@foo && @foo = bar` + #-- + #: (InstanceVariableAndWriteNode node) -> node def visit_instance_variable_and_write_node(node) node.desugar end - # @foo ||= bar + # `@foo ||= bar` # # becomes # - # @foo || @foo = bar + # `@foo || @foo = bar` + #-- + #: (InstanceVariableOrWriteNode node) -> node def visit_instance_variable_or_write_node(node) node.desugar end - # @foo += bar + # `@foo += bar` # # becomes # - # @foo = @foo + bar + # `@foo = @foo + bar` + #-- + #: (InstanceVariableOperatorWriteNode node) -> node def visit_instance_variable_operator_write_node(node) node.desugar end - # foo &&= bar + # `foo &&= bar` # # becomes # - # foo && foo = bar + # `foo && foo = bar` + #-- + #: (LocalVariableAndWriteNode node) -> node def visit_local_variable_and_write_node(node) node.desugar end - # foo ||= bar + # `foo ||= bar` # # becomes # - # foo || foo = bar + # `foo || foo = bar` + #-- + #: (LocalVariableOrWriteNode node) -> node def visit_local_variable_or_write_node(node) node.desugar end - # foo += bar + # `foo += bar` # # becomes # - # foo = foo + bar + # `foo = foo + bar` + #-- + #: (LocalVariableOperatorWriteNode node) -> node def visit_local_variable_operator_write_node(node) node.desugar end diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index 57d878a33f..1bcbfc367c 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -12,7 +12,7 @@ # autoloaded from within a non-main Ractor. require "prism/serialize" if defined?(Ractor) -module Prism +module Prism # :nodoc: module LibRubyParser # :nodoc: extend FFI::Library @@ -423,27 +423,28 @@ def dump_options_command_line(options) # Return the value that should be dumped for the version option. def dump_options_version(version) - checking = - case version - when "current" - RUBY_VERSION - when "latest" - nil - when "nearest" - if RUBY_VERSION <= "3.3" - "3.3" - elsif RUBY_VERSION >= "4.1" - "4.1" - else - RUBY_VERSION - end + case version + when "current" + version_string_to_number(RUBY_VERSION) || raise(CurrentVersionError, RUBY_VERSION) + when "latest", nil + 0 # Handled in pm_parser_init + when "nearest" + dump = version_string_to_number(RUBY_VERSION) + return dump if dump + if RUBY_VERSION < "3.3" + version_string_to_number("3.3") else - version + 0 # Handled in pm_parser_init end + else + version_string_to_number(version) || raise(ArgumentError, "invalid version: #{version}") + end + end - case checking - when nil - 0 # Handled in pm_parser_init + # Converts a version string like "4.0.0" or "4.0" into a number. + # Returns nil if the version is unknown. + def version_string_to_number(version) + case version when /\A3\.3(\.\d+)?\z/ 1 when /\A3\.4(\.\d+)?\z/ @@ -452,12 +453,6 @@ def dump_options_version(version) 3 when /\A4\.1(\.\d+)?\z/ 4 - else - if version == "current" - raise CurrentVersionError, RUBY_VERSION - else - raise ArgumentError, "invalid version: #{version}" - end end end @@ -559,7 +554,7 @@ def dump_options(options) # 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 StringQuery # :nodoc: class << self # Mirrors the C extension's StringQuery::local? method. def local?(string) diff --git a/lib/prism/lex_compat.rb b/lib/prism/lex_compat.rb index 5b685716cc..e1b04fc6ce 100644 --- a/lib/prism/lex_compat.rb +++ b/lib/prism/lex_compat.rb @@ -1,26 +1,58 @@ # frozen_string_literal: true # :markup: markdown +#-- +# rbs_inline: enabled module Prism + # @rbs! + # module Translation + # class Ripper + # EXPR_NONE: Integer + # EXPR_BEG: Integer + # EXPR_MID: Integer + # EXPR_END: Integer + # EXPR_CLASS: Integer + # EXPR_VALUE: Integer + # EXPR_ARG: Integer + # EXPR_CMDARG: Integer + # EXPR_ENDARG: Integer + # EXPR_ENDFN: Integer + # + # class Lexer < Ripper + # class State + # def self.[]: (Integer value) -> State + # end + # end + # end + # end + # This class is responsible for lexing the source using prism and then # converting those tokens to be compatible with Ripper. In the vast majority # of cases, this is a one-to-one mapping of the token type. Everything else # generally lines up. However, there are a few cases that require special # handling. class LexCompat # :nodoc: + # @rbs! + # # A token produced by the Ripper lexer that Prism is replicating. + # type lex_compat_token = [[Integer, Integer], Symbol, String, untyped] + # A result class specialized for holding tokens produced by the lexer. class Result < Prism::Result # The list of tokens that were produced by the lexer. - attr_reader :value + attr_reader :value #: Array[lex_compat_token] # Create a new lex compat result object with the given values. - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) + #-- + #: (Array[lex_compat_token] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source) @value = value - super(comments, magic_comments, data_loc, errors, warnings, source) + super(comments, magic_comments, data_loc, errors, warnings, continuable, source) end # Implement the hash pattern matching interface for Result. - def deconstruct_keys(keys) + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys(keys) # :nodoc: super.merge!(value: value) end end @@ -102,6 +134,7 @@ def deconstruct_keys(keys) KEYWORD_DEF: :on_kw, KEYWORD_DEFINED: :on_kw, KEYWORD_DO: :on_kw, + KEYWORD_DO_BLOCK: :on_kw, KEYWORD_DO_LOOP: :on_kw, KEYWORD_ELSE: :on_kw, KEYWORD_ELSIF: :on_kw, @@ -205,16 +238,19 @@ module Heredoc # :nodoc: # order back into the token stream and set the state of the last token to # the state that the heredoc was opened in. class PlainHeredoc # :nodoc: - attr_reader :tokens + attr_reader :tokens #: Array[lex_compat_token] + #: () -> void def initialize @tokens = [] end + #: (lex_compat_token token) -> void def <<(token) tokens << token end + #: () -> Array[lex_compat_token] def to_a tokens end @@ -224,21 +260,25 @@ def to_a # that need to be split on "\\\n" to mimic Ripper's behavior. We also need # to keep track of the state that the heredoc was opened in. class DashHeredoc # :nodoc: - attr_reader :split, :tokens + attr_reader :split #: bool + attr_reader :tokens #: Array[lex_compat_token] + #: (bool split) -> void def initialize(split) @split = split @tokens = [] end + #: (lex_compat_token token) -> void def <<(token) tokens << token end + #: () -> Array[lex_compat_token] def to_a embexpr_balance = 0 - tokens.each_with_object([]) do |token, results| #$ Array[Token] + tokens.each_with_object([]) do |token, results| #$ Array[lex_compat_token] case token[1] when :on_embexpr_beg embexpr_balance += 1 @@ -285,8 +325,13 @@ def to_a class DedentingHeredoc # :nodoc: TAB_WIDTH = 8 - attr_reader :tokens, :dedent_next, :dedent, :embexpr_balance + attr_reader :tokens #: Array[lex_compat_token] + attr_reader :dedent_next #: bool + attr_reader :dedent #: Integer? + attr_reader :embexpr_balance #: Integer + # @rbs @ended_on_newline: bool + #: () -> void def initialize @tokens = [] @dedent_next = true @@ -298,6 +343,8 @@ def initialize # As tokens are coming in, we track the minimum amount of common leading # whitespace on plain string content tokens. This allows us to later # remove that amount of whitespace from the beginning of each line. + # + #: (lex_compat_token token) -> void def <<(token) case token[1] when :on_embexpr_beg, :on_heredoc_beg @@ -310,7 +357,7 @@ def <<(token) line = token[2] if dedent_next && !(line.strip.empty? && line.end_with?("\n")) - leading = line[/\A(\s*)\n?/, 1] + leading = line[/\A(\s*)\n?/, 1] #: String next_dedent = 0 leading.each_char do |char| @@ -335,11 +382,12 @@ def <<(token) tokens << token end + #: () -> Array[lex_compat_token] def to_a # If every line in the heredoc is blank, we still need to split up the # string content token into multiple tokens. if dedent.nil? - results = [] #: Array[Token] + results = [] #: Array[lex_compat_token] embexpr_balance = 0 tokens.each do |token| @@ -374,7 +422,7 @@ def to_a # If the minimum common whitespace is 0, then we need to concatenate # string nodes together that are immediately adjacent. if dedent == 0 - results = [] #: Array[Token] + results = [] #: Array[lex_compat_token] embexpr_balance = 0 index = 0 @@ -407,7 +455,7 @@ def to_a # insert on_ignored_sp tokens for the amount of dedent that we need to # perform. We also need to remove the dedent from the beginning of # each line of plain string content tokens. - results = [] #: Array[Token] + results = [] #: Array[lex_compat_token] dedent_next = true embexpr_balance = 0 @@ -446,7 +494,8 @@ def to_a # line or this line doesn't start with whitespace, then we # should concatenate the rest of the string to match ripper. if dedent == 0 && (!dedent_next || !line.start_with?(/\s/)) - line = splits[index..].join + unjoined = splits[index..] #: Array[String] + line = unjoined.join index = splits.length end @@ -511,6 +560,8 @@ def to_a # Here we will split between the two types of heredocs and return the # object that will store their tokens. + #-- + #: (lex_compat_token opening) -> (PlainHeredoc | DashHeredoc | DedentingHeredoc) def self.build(opening) case opening[2][2] when "~" @@ -530,31 +581,38 @@ def self.build(opening) BOM_FLUSHED = RUBY_VERSION >= "3.3.0" private_constant :BOM_FLUSHED - attr_reader :options + attr_reader :options #: Hash[Symbol, untyped] + # @rbs @source: String - def initialize(code, **options) - @code = code + #: (String source, **untyped options) -> void + def initialize(source, **options) + @source = source @options = options end + #: () -> Result def result - tokens = [] #: Array[LexCompat::Token] + tokens = [] #: Array[lex_compat_token] state = :default heredoc_stack = [[]] #: Array[Array[Heredoc::PlainHeredoc | Heredoc::DashHeredoc | Heredoc::DedentingHeredoc]] - result = Prism.lex(@code, **options) + result = Prism.lex(@source, **options) source = result.source result_value = result.value - previous_state = nil #: State? + previous_state = nil #: Translation::Ripper::Lexer::State? last_heredoc_end = nil #: Integer? - eof_token = nil + eof_token = nil #: Token? bom = source.slice(0, 3) == "\xEF\xBB\xBF" - result_value.each_with_index do |(token, lex_state), index| - lineno = token.location.start_line - column = token.location.start_column + result_value.each_with_index do |(prism_token, prism_state), index| + lineno = prism_token.location.start_line + column = prism_token.location.start_column + + event = RIPPER.fetch(prism_token.type) + value = prism_token.value + lex_state = Translation::Ripper::Lexer::State[prism_state] # If there's a UTF-8 byte-order mark as the start of the file, then for # certain tokens ripper sets the first token back by 3 bytes. It also @@ -566,43 +624,38 @@ def result if index == 0 && column == 0 && !BOM_FLUSHED flushed = - case token.type + case prism_token.type when :BACK_REFERENCE, :INSTANCE_VARIABLE, :CLASS_VARIABLE, :GLOBAL_VARIABLE, :NUMBERED_REFERENCE, :PERCENT_LOWER_I, :PERCENT_LOWER_X, :PERCENT_LOWER_W, :PERCENT_UPPER_I, :PERCENT_UPPER_W, :STRING_BEGIN true when :REGEXP_BEGIN, :SYMBOL_BEGIN - token.value.start_with?("%") + value.start_with?("%") else false end unless flushed column -= 3 - value = token.value value.prepend(String.new("\xEF\xBB\xBF", encoding: value.encoding)) end end end - event = RIPPER.fetch(token.type) - value = token.value - lex_state = Translation::Ripper::Lexer::State[lex_state] - - token = + lex_compat_token = case event when :on___end__ # Ripper doesn't include the rest of the token in the event, so we need to # trim it down to just the content on the first line. - value = value[0..value.index("\n")] + value = value[0..value.index("\n")] #: String [[lineno, column], event, value, lex_state] when :on_comment [[lineno, column], event, value, lex_state] when :on_heredoc_end # Heredoc end tokens can be emitted in an odd order, so we don't # want to bother comparing the state on them. - last_heredoc_end = token.location.end_offset + last_heredoc_end = prism_token.location.end_offset [[lineno, column], event, value, lex_state] when :on_embexpr_end [[lineno, column], event, value, lex_state] @@ -615,7 +668,7 @@ def result end tokens << [[lineno, column], event, line, lex_state] end - tokens.pop + tokens.pop #: lex_compat_token when :on_regexp_end # On regex end, Ripper scans and then sets end state, so the ripper # lexed output is begin, when it should be end. prism sets lex state @@ -647,7 +700,7 @@ def result [[lineno, column], event, value, lex_state] when :on_eof - eof_token = token + eof_token = prism_token previous_token = result_value[index - 1][0] # If we're at the end of the file and the previous token was a @@ -662,7 +715,7 @@ def result # Use the greater offset of the two to determine the start of # the trailing whitespace. start_offset = [previous_token.location.end_offset, last_heredoc_end].compact.max - end_offset = token.location.start_offset + end_offset = prism_token.location.start_offset if start_offset < end_offset if bom @@ -677,7 +730,7 @@ def result [[lineno, column], event, value, lex_state] else [[lineno, column], event, value, lex_state] - end + end #: lex_compat_token previous_state = lex_state @@ -694,19 +747,19 @@ def result when :default # The default state is when there are no heredocs at all. In this # state we can append the token to the list of tokens and move on. - tokens << token + tokens << lex_compat_token # If we get the declaration of a heredoc, then we open a new heredoc # and move into the heredoc_opened state. if event == :on_heredoc_beg state = :heredoc_opened - heredoc_stack.last << Heredoc.build(token) + heredoc_stack.last << Heredoc.build(lex_compat_token) end when :heredoc_opened # The heredoc_opened state is when we've seen the declaration of a # heredoc and are now lexing the body of the heredoc. In this state we # push tokens onto the most recently created heredoc. - heredoc_stack.last.last << token + heredoc_stack.last.last << lex_compat_token case event when :on_heredoc_beg @@ -714,7 +767,7 @@ def result # heredoc, this means we have nested heredocs. In this case we'll # push a new heredoc onto the stack and stay in the heredoc_opened # state since we're now lexing the body of the new heredoc. - heredoc_stack << [Heredoc.build(token)] + heredoc_stack << [Heredoc.build(lex_compat_token)] when :on_heredoc_end # If we receive the end of a heredoc, then we're done lexing the # body of the heredoc. In this case we now have a completed heredoc @@ -723,10 +776,10 @@ def result state = :heredoc_closed end when :heredoc_closed - if %i[on_nl on_ignored_nl on_comment].include?(event) || (event == :on_tstring_content && value.end_with?("\n")) + if %i[on_nl on_ignored_nl on_comment].include?(event) || ((event == :on_tstring_content) && value.end_with?("\n")) if heredoc_stack.size > 1 - flushing = heredoc_stack.pop - heredoc_stack.last.last << token + flushing = heredoc_stack.pop #: Array[Heredoc::PlainHeredoc | Heredoc::DashHeredoc | Heredoc::DedentingHeredoc] + heredoc_stack.last.last << lex_compat_token flushing.each do |heredoc| heredoc.to_a.each do |flushed_token| @@ -738,12 +791,12 @@ def result next end elsif event == :on_heredoc_beg - tokens << token + tokens << lex_compat_token state = :heredoc_opened - heredoc_stack.last << Heredoc.build(token) + heredoc_stack.last << Heredoc.build(lex_compat_token) next elsif heredoc_stack.size > 1 - heredoc_stack[-2].last << token + heredoc_stack[-2].last << lex_compat_token next end @@ -754,13 +807,15 @@ def result heredoc_stack.last.clear state = :default - tokens << token + tokens << lex_compat_token end end # Drop the EOF token from the list. The EOF token may not be # present if the source was syntax invalid - tokens = tokens[0...-1] if tokens.dig(-1, 1) == :on_eof + if tokens.dig(-1, 1) == :on_eof + tokens = tokens[0...-1] #: Array[lex_compat_token] + end # We sort by location because Ripper.lex sorts. tokens.sort_by! do |token| @@ -768,21 +823,25 @@ def result source.byte_offset(line, column) end - # Add :on_sp tokens - tokens = insert_on_sp(tokens, source, result.data_loc, bom, eof_token) + tokens = post_process_tokens(tokens, source, result.data_loc, bom, eof_token) - Result.new(tokens, result.comments, result.magic_comments, result.data_loc, result.errors, result.warnings, source) + Result.new(tokens, result.comments, result.magic_comments, result.data_loc, result.errors, result.warnings, result.continuable?, source) end private - def insert_on_sp(tokens, source, data_loc, bom, eof_token) - new_tokens = [] + #: (Array[lex_compat_token] tokens, Source source, Location? data_loc, bool bom, Token? eof_token) -> Array[lex_compat_token] + def post_process_tokens(tokens, source, data_loc, bom, eof_token) + new_tokens = [] #: Array[lex_compat_token] prev_token_state = Translation::Ripper::Lexer::State[Translation::Ripper::EXPR_BEG] prev_token_end = bom ? 3 : 0 tokens.each do |token| + # Skip missing heredoc ends. + next if token[1] == :on_heredoc_end && token[2] == "" + + # Add :on_sp tokens. line, column = token[0] start_offset = source.byte_offset(line, column) @@ -803,8 +862,8 @@ def insert_on_sp(tokens, source, data_loc, bom, eof_token) next_whitespace_index = continuation_index + 1 next_whitespace_index += 1 if sp_value.byteslice(next_whitespace_index) == "\r" next_whitespace_index += 1 - first_whitespace = sp_value[0...continuation_index] - continuation = sp_value[continuation_index...next_whitespace_index] + first_whitespace = sp_value[0...continuation_index] #: String + continuation = sp_value[continuation_index...next_whitespace_index] #: String second_whitespace = sp_value[next_whitespace_index..] || "" new_tokens << [[sp_line, sp_column], :on_sp, first_whitespace, prev_token_state] unless first_whitespace.empty? diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index 469e54ca0c..4457c26fbe 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true # :markup: markdown +#-- +# rbs_inline: enabled #-- # Here we are reopening the prism module to provide methods on nodes that aren't @@ -7,9 +9,9 @@ #++ module Prism class Node + #: (*String replacements) -> void def deprecated(*replacements) # :nodoc: - location = caller_locations(1, 1) - location = location[0].label if location + location = caller_locations(1, 1)&.[](0)&.label suggest = replacements.map { |replacement| "#{self.class}##{replacement}" } warn(<<~MSG, uplevel: 1, category: :deprecated) @@ -23,7 +25,9 @@ def deprecated(*replacements) # :nodoc: module RegularExpressionOptions # :nodoc: # Returns a numeric value that represents the flags that were used to create # the regular expression. - def options + #-- + #: (Integer flags) -> Integer + def self.options(flags) o = 0 o |= Regexp::IGNORECASE if flags.anybits?(RegularExpressionFlags::IGNORE_CASE) o |= Regexp::EXTENDED if flags.anybits?(RegularExpressionFlags::EXTENDED) @@ -35,43 +39,87 @@ def options end class InterpolatedMatchLastLineNode < Node - include RegularExpressionOptions + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + #-- + #: () -> Integer + def options + RegularExpressionOptions.options(flags) + end end class InterpolatedRegularExpressionNode < Node - include RegularExpressionOptions + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + #-- + #: () -> Integer + def options + RegularExpressionOptions.options(flags) + end end class MatchLastLineNode < Node - include RegularExpressionOptions + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + #-- + #: () -> Integer + def options + RegularExpressionOptions.options(flags) + end end class RegularExpressionNode < Node - include RegularExpressionOptions + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + #-- + #: () -> Integer + def options + RegularExpressionOptions.options(flags) + end end private_constant :RegularExpressionOptions module HeredocQuery # :nodoc: # Returns true if this node was represented as a heredoc in the source code. - def heredoc? + #-- + #: (String? opening) -> bool? + def self.heredoc?(opening) + # @type self: InterpolatedStringNode | InterpolatedXStringNode | StringNode | XStringNode opening&.start_with?("<<") end end class InterpolatedStringNode < Node - include HeredocQuery + # Returns true if this node was represented as a heredoc in the source code. + #-- + #: () -> bool? + def heredoc? + HeredocQuery.heredoc?(opening) + end end class InterpolatedXStringNode < Node - include HeredocQuery + # Returns true if this node was represented as a heredoc in the source code. + #-- + #: () -> bool? + def heredoc? + HeredocQuery.heredoc?(opening) + end end class StringNode < Node - include HeredocQuery + # Returns true if this node was represented as a heredoc in the source code. + #-- + #: () -> bool? + def heredoc? + HeredocQuery.heredoc?(opening) + end # Occasionally it's helpful to treat a string as if it were interpolated so # that there's a consistent interface for working with strings. + #-- + #: () -> InterpolatedStringNode def to_interpolated InterpolatedStringNode.new( source, @@ -86,10 +134,17 @@ def to_interpolated end class XStringNode < Node - include HeredocQuery + # Returns true if this node was represented as a heredoc in the source code. + #-- + #: () -> bool? + def heredoc? + HeredocQuery.heredoc?(opening) + end # Occasionally it's helpful to treat a string as if it were interpolated so # that there's a consistent interface for working with strings. + #-- + #: () -> InterpolatedXStringNode def to_interpolated InterpolatedXStringNode.new( source, @@ -107,6 +162,8 @@ def to_interpolated class ImaginaryNode < Node # Returns the value of the node as a Ruby Complex. + #-- + #: () -> Complex def value Complex(0, numeric.value) end @@ -114,12 +171,16 @@ def value class RationalNode < Node # Returns the value of the node as a Ruby Rational. + #-- + #: () -> Rational def value 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. + #-- + #: () -> (IntegerNode | FloatNode) def numeric deprecated("value", "numerator", "denominator") @@ -134,11 +195,15 @@ def numeric class ConstantReadNode < Node # Returns the list of parts for the full name of this constant. # For example: [:Foo] + #-- + #: () -> Array[Symbol] def full_name_parts [name] end # Returns the full name of this constant. For example: "Foo" + #-- + #: () -> String def full_name name.to_s end @@ -147,11 +212,15 @@ def full_name class ConstantWriteNode < Node # Returns the list of parts for the full name of this constant. # For example: [:Foo] + #-- + #: () -> Array[Symbol] def full_name_parts [name] end # Returns the full name of this constant. For example: "Foo" + #-- + #: () -> String def full_name name.to_s end @@ -173,6 +242,8 @@ class MissingNodesInConstantPathError < StandardError; end # Returns the list of parts for the full name of this constant path. # For example: [:Foo, :Bar] + #-- + #: () -> Array[Symbol] def full_name_parts parts = [] #: Array[Symbol] current = self #: node? @@ -195,6 +266,8 @@ def full_name_parts end # Returns the full name of this constant path. For example: "Foo::Bar" + #-- + #: () -> String def full_name full_name_parts.join("::") end @@ -202,10 +275,12 @@ def full_name # Previously, we had a child node on this class that contained either a # constant read or a missing node. To not cause a breaking change, we # continue to supply that API. + #-- + #: () -> (ConstantReadNode | MissingNode) def child deprecated("name", "name_loc") - if name + if (name = self.name) ConstantReadNode.new(source, -1, name_loc, 0, name) else MissingNode.new(source, -1, location, 0) @@ -216,9 +291,11 @@ def child class ConstantPathTargetNode < Node # Returns the list of parts for the full name of this constant path. # For example: [:Foo, :Bar] + #-- + #: () -> Array[Symbol] def full_name_parts parts = - case parent + case (parent = self.parent) when ConstantPathNode, ConstantReadNode parent.full_name_parts when nil @@ -228,7 +305,7 @@ def full_name_parts raise ConstantPathNode::DynamicPartsInConstantPathError, "Constant target path contains dynamic parts. Cannot compute full name" end - if name.nil? + if (name = self.name).nil? raise ConstantPathNode::MissingNodesInConstantPathError, "Constant target path contains missing nodes. Cannot compute full name" end @@ -236,6 +313,8 @@ def full_name_parts end # Returns the full name of this constant path. For example: "Foo::Bar" + #-- + #: () -> String def full_name full_name_parts.join("::") end @@ -243,10 +322,12 @@ def full_name # Previously, we had a child node on this class that contained either a # constant read or a missing node. To not cause a breaking change, we # continue to supply that API. + #-- + #: () -> (ConstantReadNode | MissingNode) def child deprecated("name", "name_loc") - if name + if (name = self.name) ConstantReadNode.new(source, -1, name_loc, 0, name) else MissingNode.new(source, -1, location, 0) @@ -257,11 +338,15 @@ def child class ConstantTargetNode < Node # Returns the list of parts for the full name of this constant. # For example: [:Foo] + #-- + #: () -> Array[Symbol] def full_name_parts [name] end # Returns the full name of this constant. For example: "Foo" + #-- + #: () -> String def full_name name.to_s end @@ -269,6 +354,8 @@ def full_name class ParametersNode < Node # Mirrors the Method#parameters method. + #-- + #: () -> Array[[Symbol, Symbol] | [Symbol]] def signature names = [] #: Array[[Symbol, Symbol] | [Symbol]] @@ -278,7 +365,7 @@ def signature optionals.each { |param| names << [:opt, param.name] } - if rest && rest.is_a?(RestParameterNode) + if (rest = self.rest).is_a?(RestParameterNode) names << [:rest, rest.name || :*] end @@ -286,7 +373,9 @@ def signature case param when MultiTargetNode names << [:req] - when NoKeywordsParameterNode, KeywordRestParameterNode, ForwardingParameterNode + when NoKeywordsParameterNode, KeywordRestParameterNode, + NoBlockParameterNode, BlockParameterNode, + ForwardingParameterNode # Invalid syntax, e.g. "def f(**nil, ...)" moves the NoKeywordsParameterNode to posts raise "Invalid syntax" else @@ -307,7 +396,7 @@ def signature keyopt.each { |param| names << [:key, param.name] } - case keyword_rest + case (keyword_rest = self.keyword_rest) when ForwardingParameterNode names.concat([[:rest, :*], [:keyrest, :**], [:block, :&]]) when KeywordRestParameterNode @@ -316,7 +405,13 @@ def signature names << [:nokey] end - names << [:block, block.name || :&] if block + case (block = self.block) + when BlockParameterNode + names << [:block, block.name || :&] + when NoBlockParameterNode + names << [:noblock] + end + names end end @@ -331,6 +426,8 @@ class CallNode < Node # 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. + #-- + #: () -> Location? def full_message_loc attribute_write? ? message_loc&.adjoin("=") : message_loc end @@ -339,6 +436,8 @@ def full_message_loc class CallOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -346,6 +445,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -355,6 +456,8 @@ def operator_loc class ClassVariableOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -362,6 +465,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -371,6 +476,8 @@ def operator_loc class ConstantOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -378,6 +485,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -387,6 +496,8 @@ def operator_loc class ConstantPathOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -394,6 +505,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -403,6 +516,8 @@ def operator_loc class GlobalVariableOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -410,6 +525,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -419,6 +536,8 @@ def operator_loc class IndexOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -426,6 +545,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -435,6 +556,8 @@ def operator_loc class InstanceVariableOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -442,6 +565,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -451,6 +576,8 @@ def operator_loc class LocalVariableOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -458,6 +585,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -467,6 +596,8 @@ def operator_loc class CaseMatchNode < Node # Returns the else clause of the case match node. This method is deprecated # in favor of #else_clause. + #-- + #: () -> ElseNode? def consequent deprecated("else_clause") else_clause @@ -476,6 +607,8 @@ def consequent class CaseNode < Node # Returns the else clause of the case node. This method is deprecated in # favor of #else_clause. + #-- + #: () -> ElseNode? def consequent deprecated("else_clause") else_clause @@ -485,6 +618,8 @@ def consequent class IfNode < Node # Returns the subsequent if/elsif/else clause of the if node. This method is # deprecated in favor of #subsequent. + #-- + #: () -> (IfNode | ElseNode)? def consequent deprecated("subsequent") subsequent @@ -494,6 +629,8 @@ def consequent class RescueNode < Node # Returns the subsequent rescue clause of the rescue node. This method is # deprecated in favor of #subsequent. + #-- + #: () -> RescueNode? def consequent deprecated("subsequent") subsequent @@ -503,6 +640,8 @@ def consequent class UnlessNode < Node # Returns the else clause of the unless node. This method is deprecated in # favor of #else_clause. + #-- + #: () -> ElseNode? def consequent deprecated("else_clause") else_clause diff --git a/lib/prism/pack.rb b/lib/prism/pack.rb deleted file mode 100644 index 166c04c3c0..0000000000 --- a/lib/prism/pack.rb +++ /dev/null @@ -1,230 +0,0 @@ -# frozen_string_literal: true -# :markup: markdown -# typed: ignore - -# -module Prism - # A parser for the pack template language. - module Pack - %i[ - SPACE - COMMENT - INTEGER - UTF8 - BER - FLOAT - STRING_SPACE_PADDED - STRING_NULL_PADDED - STRING_NULL_TERMINATED - STRING_MSB - STRING_LSB - STRING_HEX_HIGH - STRING_HEX_LOW - STRING_UU - STRING_MIME - STRING_BASE64 - STRING_FIXED - STRING_POINTER - MOVE - BACK - NULL - - UNSIGNED - SIGNED - SIGNED_NA - - AGNOSTIC_ENDIAN - LITTLE_ENDIAN - BIG_ENDIAN - NATIVE_ENDIAN - ENDIAN_NA - - SIZE_SHORT - SIZE_INT - SIZE_LONG - SIZE_LONG_LONG - SIZE_8 - SIZE_16 - SIZE_32 - SIZE_64 - SIZE_P - SIZE_NA - - LENGTH_FIXED - LENGTH_MAX - LENGTH_RELATIVE - LENGTH_NA - ].each do |const| - const_set(const, const) - end - - # A directive in the pack template language. - class Directive - # A symbol representing the version of Ruby. - attr_reader :version - - # A symbol representing whether or not we are packing or unpacking. - attr_reader :variant - - # A byteslice of the source string that this directive represents. - attr_reader :source - - # The type of the directive. - attr_reader :type - - # The type of signedness of the directive. - attr_reader :signed - - # The type of endianness of the directive. - attr_reader :endian - - # The size of the directive. - attr_reader :size - - # The length type of this directive (used for integers). - attr_reader :length_type - - # The length of this directive (used for integers). - attr_reader :length - - # Initialize a new directive with the given values. - def initialize(version, variant, source, type, signed, endian, size, length_type, length) - @version = version - @variant = variant - @source = source - @type = type - @signed = signed - @endian = endian - @size = size - @length_type = length_type - @length = length - end - - # The descriptions of the various types of endianness. - ENDIAN_DESCRIPTIONS = { - AGNOSTIC_ENDIAN: "agnostic", - LITTLE_ENDIAN: "little-endian (VAX)", - BIG_ENDIAN: "big-endian (network)", - NATIVE_ENDIAN: "native-endian", - ENDIAN_NA: "n/a" - } - - # The descriptions of the various types of signedness. - SIGNED_DESCRIPTIONS = { - UNSIGNED: "unsigned", - SIGNED: "signed", - SIGNED_NA: "n/a" - } - - # The descriptions of the various types of sizes. - SIZE_DESCRIPTIONS = { - SIZE_SHORT: "short", - SIZE_INT: "int-width", - SIZE_LONG: "long", - SIZE_LONG_LONG: "long long", - SIZE_8: "8-bit", - SIZE_16: "16-bit", - SIZE_32: "32-bit", - SIZE_64: "64-bit", - SIZE_P: "pointer-width" - } - - # Provide a human-readable description of the directive. - def describe - case type - when SPACE - "whitespace" - when COMMENT - "comment" - when INTEGER - if size == SIZE_8 - base = "#{SIGNED_DESCRIPTIONS[signed]} #{SIZE_DESCRIPTIONS[size]} integer" - else - base = "#{SIGNED_DESCRIPTIONS[signed]} #{SIZE_DESCRIPTIONS[size]} #{ENDIAN_DESCRIPTIONS[endian]} integer" - end - case length_type - when LENGTH_FIXED - if length > 1 - base + ", x#{length}" - else - base - end - when LENGTH_MAX - base + ", as many as possible" - else - raise - end - when UTF8 - "UTF-8 character" - when BER - "BER-compressed integer" - when FLOAT - "#{SIZE_DESCRIPTIONS[size]} #{ENDIAN_DESCRIPTIONS[endian]} float" - when STRING_SPACE_PADDED - "arbitrary binary string (space padded)" - when STRING_NULL_PADDED - "arbitrary binary string (null padded, count is width)" - when STRING_NULL_TERMINATED - "arbitrary binary string (null padded, count is width), except that null is added with *" - when STRING_MSB - "bit string (MSB first)" - when STRING_LSB - "bit string (LSB first)" - when STRING_HEX_HIGH - "hex string (high nibble first)" - when STRING_HEX_LOW - "hex string (low nibble first)" - when STRING_UU - "UU-encoded string" - when STRING_MIME - "quoted printable, MIME encoding" - when STRING_BASE64 - "base64 encoded string" - when STRING_FIXED - "pointer to a structure (fixed-length string)" - when STRING_POINTER - "pointer to a null-terminated string" - when MOVE - "move to absolute position" - when BACK - "back up a byte" - when NULL - "null byte" - else - raise - end - end - end - - # The result of parsing a pack template. - class Format - # A list of the directives in the template. - attr_reader :directives - - # The encoding of the template. - attr_reader :encoding - - # Create a new Format with the given directives and encoding. - def initialize(directives, encoding) - @directives = directives - @encoding = encoding - end - - # Provide a human-readable description of the format. - def describe - source_width = directives.map { |d| d.source.inspect.length }.max - directive_lines = directives.map do |directive| - if directive.type == SPACE - source = directive.source.inspect - else - source = directive.source - end - # @type var source_width: Integer - " #{source.ljust(source_width)} #{directive.describe}" - end - - (["Directives:"] + directive_lines + ["Encoding:", " #{encoding}"]).join("\n") - end - end - end -end diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 2498ae7e14..5c4d4fcb8a 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -1,7 +1,16 @@ # frozen_string_literal: true # :markup: markdown +#-- +# rbs_inline: enabled module Prism + # @rbs! + # # An internal interface for a cache that can be used to compute code + # # units from byte offsets. + # interface _CodeUnitsCache + # def []: (Integer byte_offset) -> Integer + # end + # This represents a source of Ruby code that has been parsed. It is used in # conjunction with locations to allow them to resolve line numbers and source # ranges. @@ -10,7 +19,17 @@ class Source # be used instead of `new` and it will return either a `Source` or a # specialized and more performant `ASCIISource` if no multibyte characters # are present in the source code. - def self.for(source, start_line = 1, offsets = []) + # + # Note that if you are calling this method manually, you will need to supply + # the start_line and offsets parameters. start_line is the line number that + # the source starts on, which is typically 1 but can be different if this + # source is a subset of a larger source or if this is an eval. offsets is an + # array of byte offsets for the start of each line in the source code, which + # can be calculated by iterating through the source code and recording the + # byte offset whenever a newline character is encountered. + #-- + #: (String source, Integer start_line, Array[Integer] offsets) -> Source + def self.for(source, start_line, offsets) if source.ascii_only? ASCIISource.new(source, start_line, offsets) elsif source.encoding == Encoding::BINARY @@ -34,49 +53,63 @@ def self.for(source, start_line = 1, offsets = []) end # The source code that this source object represents. - attr_reader :source + attr_reader :source #: String # The line number where this source starts. - attr_reader :start_line + attr_reader :start_line #: Integer # The list of newline byte offsets in the source code. - attr_reader :offsets + attr_reader :offsets #: Array[Integer] # Create a new source object with the given source code. - def initialize(source, start_line = 1, offsets = []) + #-- + #: (String source, Integer start_line, Array[Integer] offsets) -> void + def initialize(source, start_line, offsets) @source = source @start_line = start_line # set after parsing is done @offsets = offsets # set after parsing is done end # Replace the value of start_line with the given value. + #-- + #: (Integer start_line) -> void def replace_start_line(start_line) @start_line = start_line end # Replace the value of offsets with the given value. + #-- + #: (Array[Integer] offsets) -> void def replace_offsets(offsets) @offsets.replace(offsets) end # Returns the encoding of the source code, which is set by parameters to the # parser or by the encoding magic comment. + #-- + #: () -> Encoding def encoding source.encoding end # Returns the lines of the source code as an array of strings. + #-- + #: () -> Array[String] def lines source.lines end # Perform a byteslice on the source code using the given byte offset and # byte length. + #-- + #: (Integer byte_offset, Integer length) -> String def slice(byte_offset, length) source.byteslice(byte_offset, length) or raise end # Converts the line number and column in bytes to a byte offset. + #-- + #: (Integer line, Integer column) -> Integer def byte_offset(line, column) normal = line - @start_line raise IndexError if normal < 0 @@ -87,33 +120,45 @@ def byte_offset(line, column) # Binary search through the offsets to find the line number for the given # byte offset. + #-- + #: (Integer byte_offset) -> Integer def line(byte_offset) start_line + find_line(byte_offset) end # Return the byte offset of the start of the line corresponding to the given # byte offset. + #-- + #: (Integer byte_offset) -> Integer def line_start(byte_offset) offsets[find_line(byte_offset)] end # Returns the byte offset of the end of the line corresponding to the given # byte offset. + #-- + #: (Integer byte_offset) -> Integer def line_end(byte_offset) offsets[find_line(byte_offset) + 1] || source.bytesize end # Return the column in bytes for the given byte offset. + #-- + #: (Integer byte_offset) -> Integer def column(byte_offset) byte_offset - line_start(byte_offset) end # Return the character offset for the given byte offset. + #-- + #: (Integer byte_offset) -> Integer def character_offset(byte_offset) (source.byteslice(0, byte_offset) or raise).length end # Return the column in characters for the given byte offset. + #-- + #: (Integer byte_offset) -> Integer def character_column(byte_offset) character_offset(byte_offset) - character_offset(line_start(byte_offset)) end @@ -130,6 +175,8 @@ def character_column(byte_offset) # 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. + #-- + #: (Integer byte_offset, Encoding encoding) -> Integer def code_units_offset(byte_offset, encoding) byteslice = (source.byteslice(0, byte_offset) or raise).encode(encoding, invalid: :replace, undef: :replace) @@ -142,17 +189,23 @@ def code_units_offset(byte_offset, encoding) # Generate a cache that targets a specific encoding for calculating code # unit offsets. + #-- + #: (Encoding encoding) -> CodeUnitsCache def code_units_cache(encoding) CodeUnitsCache.new(source, encoding) end # Returns the column in code units for the given encoding for the # given byte offset. + #-- + #: (Integer byte_offset, Encoding encoding) -> Integer def code_units_column(byte_offset, encoding) code_units_offset(byte_offset, encoding) - code_units_offset(line_start(byte_offset), encoding) end # Freeze this object and the objects it contains. + #-- + #: () -> void def deep_freeze source.freeze offsets.freeze @@ -163,7 +216,9 @@ def deep_freeze # Binary search through the offsets to find the line number for the given # byte offset. - def find_line(byte_offset) + #-- + #: (Integer byte_offset) -> Integer + def find_line(byte_offset) # :nodoc: index = offsets.bsearch_index { |offset| offset > byte_offset } || offsets.length index - 1 end @@ -185,30 +240,47 @@ def find_line(byte_offset) # class CodeUnitsCache class UTF16Counter # :nodoc: + # @rbs @source: String + # @rbs @encoding: Encoding + + #: (String source, Encoding encoding) -> void def initialize(source, encoding) @source = source @encoding = encoding end + #: (Integer byte_offset, Integer byte_length) -> Integer def count(byte_offset, byte_length) - @source.byteslice(byte_offset, byte_length).encode(@encoding, invalid: :replace, undef: :replace).bytesize / 2 + (@source.byteslice(byte_offset, byte_length) or raise).encode(@encoding, invalid: :replace, undef: :replace).bytesize / 2 end end class LengthCounter # :nodoc: + # @rbs @source: String + # @rbs @encoding: Encoding + + #: (String source, Encoding encoding) -> void def initialize(source, encoding) @source = source @encoding = encoding end + #: (Integer byte_offset, Integer byte_length) -> Integer def count(byte_offset, byte_length) - @source.byteslice(byte_offset, byte_length).encode(@encoding, invalid: :replace, undef: :replace).length + (@source.byteslice(byte_offset, byte_length) or raise).encode(@encoding, invalid: :replace, undef: :replace).length end end private_constant :UTF16Counter, :LengthCounter + # @rbs @source: String + # @rbs @counter: UTF16Counter | LengthCounter + # @rbs @cache: Hash[Integer, Integer] + # @rbs @offsets: Array[Integer] + # Initialize a new cache with the given source and encoding. + #-- + #: (String source, Encoding encoding) -> void def initialize(source, encoding) @source = source @counter = @@ -223,6 +295,8 @@ def initialize(source, encoding) end # Retrieve the code units offset from the given byte offset. + #-- + #: (Integer byte_offset) -> Integer def [](byte_offset) @cache[byte_offset] ||= if (index = @offsets.bsearch_index { |offset| offset > byte_offset }).nil? @@ -249,11 +323,15 @@ def [](byte_offset) # at that point we will treat everything as single-byte characters. class ASCIISource < Source # Return the character offset for the given byte offset. + #-- + #: (Integer byte_offset) -> Integer def character_offset(byte_offset) byte_offset end # Return the column in characters for the given byte offset. + #-- + #: (Integer byte_offset) -> Integer def character_column(byte_offset) byte_offset - line_start(byte_offset) end @@ -264,6 +342,8 @@ 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. + #-- + #: (Integer byte_offset, Encoding encoding) -> Integer def code_units_offset(byte_offset, encoding) byte_offset end @@ -271,6 +351,8 @@ def code_units_offset(byte_offset, encoding) # 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. + #-- + #: (Encoding encoding) -> _CodeUnitsCache def code_units_cache(encoding) ->(byte_offset) { byte_offset } end @@ -278,6 +360,8 @@ def code_units_cache(encoding) # Specialized version of `code_units_column` that does not depend on # `code_units_offset`, which is a more expensive operation. This is # essentially the same as `Prism::Source#column`. + #-- + #: (Integer byte_offset, Encoding encoding) -> Integer def code_units_column(byte_offset, encoding) byte_offset - line_start(byte_offset) end @@ -287,18 +371,23 @@ def code_units_column(byte_offset, encoding) class Location # A Source object that is used to determine more information from the given # offset and length. - attr_reader :source + attr_reader :source #: Source protected :source # The byte offset from the beginning of the source where this location # starts. - attr_reader :start_offset + attr_reader :start_offset #: Integer # The length of this location in bytes. - attr_reader :length + attr_reader :length #: Integer + + # @rbs @leading_comments: Array[Comment]? + # @rbs @trailing_comments: Array[Comment]? # Create a new location object with the given source, start byte offset, and # byte length. + #-- + #: (Source source, Integer start_offset, Integer length) -> void def initialize(source, start_offset, length) @source = source @start_offset = start_offset @@ -313,53 +402,73 @@ def initialize(source, start_offset, length) # These are the comments that are associated with this location that exist # before the start of this location. + #-- + #: () -> Array[Comment] def leading_comments @leading_comments ||= [] end # Attach a comment to the leading comments of this location. + #-- + #: (Comment comment) -> void def leading_comment(comment) leading_comments << comment end # These are the comments that are associated with this location that exist # after the end of this location. + #-- + #: () -> Array[Comment] def trailing_comments @trailing_comments ||= [] end # Attach a comment to the trailing comments of this location. + #-- + #: (Comment comment) -> void def trailing_comment(comment) trailing_comments << comment end # Returns all comments that are associated with this location (both leading # and trailing comments). + #-- + #: () -> Array[Comment] def comments - [*@leading_comments, *@trailing_comments] + [*@leading_comments, *@trailing_comments] #: Array[Comment] end # Create a new location object with the given options. + #-- + #: (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location def copy(source: self.source, start_offset: self.start_offset, length: self.length) Location.new(source, start_offset, length) end # Returns a new location that is the result of chopping off the last byte. + #-- + #: () -> Location def chop copy(length: length == 0 ? length : length - 1) end # Returns a string representation of this location. - def inspect + #-- + #: () -> String + def inspect # :nodoc: "#" end # Returns all of the lines of the source code associated with this location. + #-- + #: () -> Array[String] def source_lines source.lines end # The source code that this location represents. + #-- + #: () -> String def slice source.slice(start_offset, length) end @@ -367,6 +476,8 @@ def slice # The source code that this location represents starting from the beginning # of the line that this location starts on to the end of the line that this # location ends on. + #-- + #: () -> String def slice_lines line_start = source.line_start(start_offset) line_end = source.line_end(end_offset) @@ -375,118 +486,160 @@ def slice_lines # The character offset from the beginning of the source where this location # starts. + #-- + #: () -> Integer def start_character_offset source.character_offset(start_offset) end # The offset from the start of the file in code units of the given encoding. + #-- + #: (Encoding encoding) -> Integer 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. + #-- + #: (_CodeUnitsCache cache) -> Integer def cached_start_code_units_offset(cache) cache[start_offset] end # The byte offset from the beginning of the source where this location ends. + #-- + #: () -> Integer def end_offset start_offset + length end # The character offset from the beginning of the source where this location # ends. + #-- + #: () -> Integer def end_character_offset source.character_offset(end_offset) end # The offset from the start of the file in code units of the given encoding. + #-- + #: (Encoding encoding) -> Integer 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. + #-- + #: (_CodeUnitsCache cache) -> Integer def cached_end_code_units_offset(cache) cache[end_offset] end # The line number where this location starts. + #-- + #: () -> Integer def start_line source.line(start_offset) end # The content of the line where this location starts before this location. + #-- + #: () -> String def start_line_slice offset = source.line_start(start_offset) source.slice(offset, start_offset - offset) end # The line number where this location ends. + #-- + #: () -> Integer def end_line source.line(end_offset) end # The column in bytes where this location starts from the start of # the line. + #-- + #: () -> Integer def start_column source.column(start_offset) end # The column in characters where this location ends from the start of # the line. + #-- + #: () -> Integer def start_character_column source.character_column(start_offset) end # The column in code units of the given encoding where this location # starts from the start of the line. + #-- + #: (?Encoding encoding) -> Integer 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. + #-- + #: (_CodeUnitsCache cache) -> Integer def cached_start_code_units_column(cache) cache[start_offset] - cache[source.line_start(start_offset)] end # The column in bytes where this location ends from the start of the # line. + #-- + #: () -> Integer def end_column source.column(end_offset) end # The column in characters where this location ends from the start of # the line. + #-- + #: () -> Integer def end_character_column source.character_column(end_offset) end # The column in code units of the given encoding where this location # ends from the start of the line. + #-- + #: (?Encoding encoding) -> Integer 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. + #-- + #: (_CodeUnitsCache cache) -> Integer 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) + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys(keys) # :nodoc: { start_offset: start_offset, end_offset: end_offset } end # Implement the pretty print interface for Location. - def pretty_print(q) + #-- + #: (PP q) -> void + def pretty_print(q) # :nodoc: q.text("(#{start_line},#{start_column})-(#{end_line},#{end_column})") end # Returns true if the given other location is equal to this location. + #-- + #: (untyped other) -> bool def ==(other) Location === other && other.start_offset == start_offset && @@ -496,6 +649,8 @@ def ==(other) # Returns a new location that stretches from this location to the given # other location. Raises an error if this location is not before the other # location or if they don't share the same source. + #-- + #: (Location other) -> Location def join(other) raise "Incompatible sources" if source != other.source raise "Incompatible locations" if start_offset > other.start_offset @@ -506,6 +661,8 @@ def join(other) # Join this location with the first occurrence of the string in the source # that occurs after this location on the same line, and return the new # location. This will raise an error if the string does not exist. + #-- + #: (String string) -> Location def adjoin(string) line_suffix = source.slice(end_offset, source.line_end(end_offset) - end_offset) @@ -519,23 +676,38 @@ def adjoin(string) # This represents a comment that was encountered during parsing. It is the # base class for all comment types. class Comment - # The location of this comment in the source. - attr_reader :location + # The Location of this comment in the source. + attr_reader :location #: Location # Create a new comment object with the given location. + #-- + #: (Location location) -> void def initialize(location) @location = location end # Implement the hash pattern matching interface for Comment. - def deconstruct_keys(keys) + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys(keys) # :nodoc: { location: location } end # Returns the content of the comment by slicing it from the source code. + #-- + #: () -> String def slice location.slice end + + # Returns true if this comment happens on the same line as other code and + # false if the comment is by itself. This can only be true for inline + # comments and should be false for block comments. + #-- + #: () -> bool + def trailing? + raise NotImplementedError, "trailing? is not implemented for #{self.class}" + end end # InlineComment objects are the most common. They correspond to comments in @@ -543,12 +715,16 @@ def slice class InlineComment < Comment # Returns true if this comment happens on the same line as other code and # false if the comment is by itself. + #-- + #: () -> bool def trailing? !location.start_line_slice.strip.empty? end # Returns a string representation of this comment. - def inspect + #-- + #: () -> String + def inspect # :nodoc: "#" end end @@ -556,13 +732,17 @@ def inspect # EmbDocComment objects correspond to comments that are surrounded by =begin # and =end. class EmbDocComment < Comment - # This can only be true for inline comments. + # Returns false. This can only be true for inline comments. + #-- + #: () -> bool def trailing? false end # Returns a string representation of this comment. - def inspect + #-- + #: () -> String + def inspect # :nodoc: "#" end end @@ -570,34 +750,44 @@ def inspect # This represents a magic comment that was encountered during parsing. class MagicComment # A Location object representing the location of the key in the source. - attr_reader :key_loc + attr_reader :key_loc #: Location # A Location object representing the location of the value in the source. - attr_reader :value_loc + attr_reader :value_loc #: Location # Create a new magic comment object with the given key and value locations. + #-- + #: (Location key_loc, Location value_loc) -> void def initialize(key_loc, value_loc) @key_loc = key_loc @value_loc = value_loc end # Returns the key of the magic comment by slicing it from the source code. + #-- + #: () -> String def key key_loc.slice end # Returns the value of the magic comment by slicing it from the source code. + #-- + #: () -> String def value value_loc.slice end # Implement the hash pattern matching interface for MagicComment. - def deconstruct_keys(keys) + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys(keys) # :nodoc: { key_loc: key_loc, value_loc: value_loc } end # Returns a string representation of this magic comment. - def inspect + #-- + #: () -> String + def inspect # :nodoc: "#" end end @@ -606,18 +796,20 @@ def inspect class ParseError # The type of error. This is an _internal_ symbol that is used for # communicating with translation layers. It is not meant to be public API. - attr_reader :type + attr_reader :type #: Symbol # The message associated with this error. - attr_reader :message + attr_reader :message #: String # A Location object representing the location of this error in the source. - attr_reader :location + attr_reader :location #: Location # The level of this error. - attr_reader :level + attr_reader :level #: Symbol # Create a new error object with the given message and location. + #-- + #: (Symbol type, String message, Location location, Symbol level) -> void def initialize(type, message, location, level) @type = type @message = message @@ -626,12 +818,16 @@ def initialize(type, message, location, level) end # Implement the hash pattern matching interface for ParseError. - def deconstruct_keys(keys) + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys(keys) # :nodoc: { type: type, message: message, location: location, level: level } end # Returns a string representation of this error. - def inspect + #-- + #: () -> String + def inspect # :nodoc: "#" end end @@ -640,18 +836,20 @@ def inspect class ParseWarning # The type of warning. This is an _internal_ symbol that is used for # communicating with translation layers. It is not meant to be public API. - attr_reader :type + attr_reader :type #: Symbol # The message associated with this warning. - attr_reader :message + attr_reader :message #: String # A Location object representing the location of this warning in the source. - attr_reader :location + attr_reader :location #: Location # The level of this warning. - attr_reader :level + attr_reader :level #: Symbol # Create a new warning object with the given message and location. + #-- + #: (Symbol type, String message, Location location, Symbol level) -> void def initialize(type, message, location, level) @type = type @message = message @@ -660,73 +858,116 @@ def initialize(type, message, location, level) end # Implement the hash pattern matching interface for ParseWarning. - def deconstruct_keys(keys) + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys(keys) # :nodoc: { type: type, message: message, location: location, level: level } end # Returns a string representation of this warning. - def inspect + #-- + #: () -> String + def inspect # :nodoc: "#" end end - # This represents the result of a call to ::parse or ::parse_file. It contains - # the requested structure, any comments that were encounters, and any errors - # that were encountered. + # This represents the result of a call to Prism.parse or Prism.parse_file. + # It contains the requested structure, any comments that were encounters, + # and any errors that were encountered. class Result # The list of comments that were encountered during parsing. - attr_reader :comments + attr_reader :comments #: Array[Comment] # The list of magic comments that were encountered during parsing. - attr_reader :magic_comments + attr_reader :magic_comments #: Array[MagicComment] # An optional location that represents the location of the __END__ marker # and the rest of the content of the file. This content is loaded into the # DATA constant when the file being parsed is the main file being executed. - attr_reader :data_loc + attr_reader :data_loc #: Location? # The list of errors that were generated during parsing. - attr_reader :errors + attr_reader :errors #: Array[ParseError] # The list of warnings that were generated during parsing. - attr_reader :warnings + attr_reader :warnings #: Array[ParseWarning] # A Source instance that represents the source code that was parsed. - attr_reader :source + attr_reader :source #: Source # Create a new result object with the given values. - def initialize(comments, magic_comments, data_loc, errors, warnings, source) + #-- + #: (Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize(comments, magic_comments, data_loc, errors, warnings, continuable, source) @comments = comments @magic_comments = magic_comments @data_loc = data_loc @errors = errors @warnings = warnings + @continuable = continuable @source = source end # Implement the hash pattern matching interface for Result. - def deconstruct_keys(keys) + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys(keys) # :nodoc: { comments: comments, magic_comments: magic_comments, data_loc: data_loc, errors: errors, warnings: warnings } end # Returns the encoding of the source code that was parsed. + #-- + #: () -> Encoding def encoding source.encoding end # Returns true if there were no errors during parsing and false if there # were. + #-- + #: () -> bool def success? errors.empty? end # Returns true if there were errors during parsing and false if there were # not. + #-- + #: () -> bool def failure? !success? end + # Returns true if the parsed source is an incomplete expression that could + # become valid with additional input. This is useful for REPL contexts (such + # as IRB) where the user may be entering a multi-line expression one line at + # a time and the implementation needs to determine whether to wait for more + # input or to evaluate what has been entered so far. + # + # Concretely, this returns true when every error present is caused by the + # parser reaching the end of the input before a construct was closed (e.g. + # an unclosed string, array, block, or keyword), and returns false when any + # error is caused by a token that makes the input structurally invalid + # regardless of what might follow (e.g. a stray `end`, `]`, or `)` with no + # matching opener). + # + # Examples: + # + # Prism.parse("1 + [").continuable? #=> true (unclosed array) + # Prism.parse("1 + ]").continuable? #=> false (stray ]) + # Prism.parse("tap do").continuable? #=> true (unclosed block) + # Prism.parse("end.tap do").continuable? #=> false (stray end) + # + #-- + #: () -> bool + def continuable? + @continuable + end + # Create a code units cache for the given encoding. + #-- + #: (Encoding encoding) -> _CodeUnitsCache def code_units_cache(encoding) source.code_units_cache(encoding) end @@ -743,32 +984,42 @@ class ParseResult < Result private_constant :Newlines # The syntax tree that was parsed from the source code. - attr_reader :value + attr_reader :value #: ProgramNode # Create a new parse result object with the given values. - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) + #-- + #: (ProgramNode value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source) @value = value - super(comments, magic_comments, data_loc, errors, warnings, source) + super(comments, magic_comments, data_loc, errors, warnings, continuable, source) end # Implement the hash pattern matching interface for ParseResult. - def deconstruct_keys(keys) + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys(keys) # :nodoc: super.merge!(value: value) end # Attach the list of comments to their respective locations in the tree. + #-- + #: () -> void 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. + #-- + #: () -> void 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. + #-- + #: () -> String def errors_format Errors.new(self).format end @@ -777,16 +1028,20 @@ def errors_format # This is a result specific to the `lex` and `lex_file` methods. class LexResult < Result # The list of tokens that were parsed from the source code. - attr_reader :value + attr_reader :value #: Array[[Token, Integer]] # Create a new lex result object with the given values. - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) + #-- + #: (Array[[Token, Integer]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source) @value = value - super(comments, magic_comments, data_loc, errors, warnings, source) + super(comments, magic_comments, data_loc, errors, warnings, continuable, source) end # Implement the hash pattern matching interface for LexResult. - def deconstruct_keys(keys) + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys(keys) # :nodoc: super.merge!(value: value) end end @@ -795,16 +1050,20 @@ def deconstruct_keys(keys) class ParseLexResult < Result # A tuple of the syntax tree and the list of tokens that were parsed from # the source code. - attr_reader :value + attr_reader :value #: [ProgramNode, Array[[Token, Integer]]] # Create a new parse lex result object with the given values. - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) + #-- + #: ([ProgramNode, Array[[Token, Integer]]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source) @value = value - super(comments, magic_comments, data_loc, errors, warnings, source) + super(comments, magic_comments, data_loc, errors, warnings, continuable, source) end # Implement the hash pattern matching interface for ParseLexResult. - def deconstruct_keys(keys) + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys(keys) # :nodoc: super.merge!(value: value) end end @@ -812,16 +1071,20 @@ def deconstruct_keys(keys) # This represents a token from the Ruby source. class Token # The Source object that represents the source this token came from. - attr_reader :source + attr_reader :source #: Source private :source # The type of token that this token is. - attr_reader :type + attr_reader :type #: Symbol # A byteslice of the source that this token represents. - attr_reader :value + attr_reader :value #: String + + # @rbs @location: Location | Integer # Create a new token object with the given type, value, and location. + #-- + #: (Source source, Symbol type, String value, Location | Integer location) -> void def initialize(source, type, value, location) @source = source @type = type @@ -830,11 +1093,15 @@ def initialize(source, type, value, location) end # Implement the hash pattern matching interface for Token. - def deconstruct_keys(keys) + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys(keys) # :nodoc: { type: type, value: value, location: location } end # A Location object representing the location of this token in the source. + #-- + #: () -> Location def location location = @location return location if location.is_a?(Location) @@ -842,7 +1109,9 @@ def location end # Implement the pretty print interface for Token. - def pretty_print(q) + #-- + #: (PP q) -> void + def pretty_print(q) # :nodoc: q.group do q.text(type.to_s) self.location.pretty_print(q) @@ -857,6 +1126,8 @@ def pretty_print(q) end # Returns true if the given other token is equal to this token. + #-- + #: (untyped other) -> bool def ==(other) Token === other && other.type == type && @@ -864,12 +1135,16 @@ def ==(other) end # Returns a string representation of this token. - def inspect + #-- + #: () -> String + def inspect # :nodoc: location super end # Freeze this object and the objects it contains. + #-- + #: () -> void def deep_freeze value.freeze location.freeze @@ -884,14 +1159,16 @@ def deep_freeze class Scope # The list of local variables that are defined in this scope. This should be # defined as an array of symbols. - attr_reader :locals + attr_reader :locals #: Array[Symbol] # The list of local variables that are forwarded to the next scope. This # should by defined as an array of symbols containing the specific values of # :*, :**, :&, or :"...". - attr_reader :forwarding + attr_reader :forwarding #: Array[Symbol] # Create a new scope object with the given locals and forwarding. + #-- + #: (Array[Symbol] locals, Array[Symbol] forwarding) -> void def initialize(locals, forwarding) @locals = locals @forwarding = forwarding @@ -901,6 +1178,8 @@ def initialize(locals, forwarding) # Create a new scope with the given locals and forwarding options that is # suitable for passing into one of the Prism.* methods that accepts the # `scopes` option. + #-- + #: (?locals: Array[Symbol], ?forwarding: Array[Symbol]) -> Scope def self.scope(locals: [], forwarding: []) Scope.new(locals, forwarding) end diff --git a/lib/prism/parse_result/comments.rb b/lib/prism/parse_result/comments.rb index 3e93316aff..df80792d39 100644 --- a/lib/prism/parse_result/comments.rb +++ b/lib/prism/parse_result/comments.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true # :markup: markdown +#-- +# rbs_inline: enabled module Prism class ParseResult < Result @@ -18,32 +20,49 @@ class ParseResult < Result # the comment. Otherwise it will favor attaching to the nearest location # that is after the comment. class Comments + # @rbs! + # # An internal interface for a target that comments can be attached + # # to. This is either going to be a NodeTarget or a CommentTarget. + # interface _CommentTarget + # def start_offset: () -> Integer + # def end_offset: () -> Integer + # def encloses?: (Comment) -> bool + # def leading_comment: (Comment) -> void + # def trailing_comment: (Comment) -> void + # end + # A target for attaching comments that is based on a specific node's # location. class NodeTarget # :nodoc: - attr_reader :node + attr_reader :node #: node + #: (node node) -> void def initialize(node) @node = node end + #: () -> Integer def start_offset node.start_offset end + #: () -> Integer def end_offset node.end_offset end + #: (Comment comment) -> bool def encloses?(comment) start_offset <= comment.location.start_offset && comment.location.end_offset <= end_offset end + #: (Comment comment) -> void def leading_comment(comment) node.location.leading_comment(comment) end + #: (Comment comment) -> void def trailing_comment(comment) node.location.trailing_comment(comment) end @@ -52,44 +71,54 @@ def trailing_comment(comment) # A target for attaching comments that is based on a location field on a # node. For example, the `end` token of a ClassNode. class LocationTarget # :nodoc: - attr_reader :location + attr_reader :location #: Location + #: (Location location) -> void def initialize(location) @location = location end + #: () -> Integer def start_offset location.start_offset end + #: () -> Integer def end_offset location.end_offset end + #: (Comment comment) -> bool def encloses?(comment) false end + #: (Comment comment) -> void def leading_comment(comment) location.leading_comment(comment) end + #: (Comment comment) -> void def trailing_comment(comment) location.trailing_comment(comment) end end # The parse result that we are attaching comments to. - attr_reader :parse_result + attr_reader :parse_result #: ParseResult # Create a new Comments object that will attach comments to the given # parse result. + #-- + #: (ParseResult parse_result) -> void def initialize(parse_result) @parse_result = parse_result end # Attach the comments to their respective locations in the tree by # mutating the parse result. + #-- + #: () -> void def attach! parse_result.comments.each do |comment| preceding, enclosing, following = nearest_targets(parse_result.value, comment) @@ -117,11 +146,13 @@ def attach! # Responsible for finding the nearest targets to the given comment within # the context of the given encapsulating node. + #-- + #: (node node, Comment comment) -> [_CommentTarget?, _CommentTarget?, _CommentTarget?] def nearest_targets(node, comment) comment_start = comment.location.start_offset comment_end = comment.location.end_offset - targets = [] #: Array[_Target] + targets = [] #: Array[_CommentTarget] node.comment_targets.map do |value| case value when StatementsNode @@ -134,8 +165,8 @@ def nearest_targets(node, comment) end targets.sort_by!(&:start_offset) - preceding = nil #: _Target? - following = nil #: _Target? + preceding = nil #: _CommentTarget? + following = nil #: _CommentTarget? left = 0 right = targets.length diff --git a/lib/prism/parse_result/errors.rb b/lib/prism/parse_result/errors.rb index 26c376b3ce..388309d23d 100644 --- a/lib/prism/parse_result/errors.rb +++ b/lib/prism/parse_result/errors.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true # :markup: markdown +#-- +# rbs_inline: enabled require "stringio" @@ -9,14 +11,18 @@ class ParseResult < Result # 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 + attr_reader :parse_result #: ParseResult # Initialize a new set of errors from the given parse result. + #-- + #: (ParseResult parse_result) -> void def initialize(parse_result) @parse_result = parse_result end # Formats the errors in a human-readable way and return them as a string. + #-- + #: () -> String def format error_lines = {} #: Hash[Integer, Array[ParseError]] parse_result.errors.each do |error| diff --git a/lib/prism/parse_result/newlines.rb b/lib/prism/parse_result/newlines.rb index e7fd62cafe..450c790226 100644 --- a/lib/prism/parse_result/newlines.rb +++ b/lib/prism/parse_result/newlines.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true # :markup: markdown +#-- +# rbs_inline: enabled module Prism class ParseResult < Result @@ -24,13 +26,20 @@ class ParseResult < Result # 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 + # The map of lines indices to whether or not they have been marked as + # emitting a newline event. + # @rbs @lines: Array[bool] + # Create a new Newlines visitor with the given newline offsets. + #-- + #: (Integer lines) -> void def initialize(lines) - # @type var lines: Integer @lines = Array.new(1 + lines, false) end - # Permit block/lambda nodes to mark newlines within themselves. + # Permit block nodes to mark newlines within themselves. + #-- + #: (BlockNode node) -> void def visit_block_node(node) old_lines = @lines @lines = Array.new(old_lines.size, false) @@ -42,17 +51,39 @@ def visit_block_node(node) end end - alias_method :visit_lambda_node, :visit_block_node + # Permit lambda nodes to mark newlines within themselves. + #-- + #: (LambdaNode node) -> void + def visit_lambda_node(node) + old_lines = @lines + @lines = Array.new(old_lines.size, false) + + begin + super(node) + ensure + @lines = old_lines + end + end - # Mark if/unless nodes as newlines. + # Mark if nodes as newlines. + #-- + #: (IfNode node) -> void def visit_if_node(node) node.newline_flag!(@lines) super(node) end - alias_method :visit_unless_node, :visit_if_node + # Mark unless nodes as newlines. + #-- + #: (UnlessNode node) -> void + def visit_unless_node(node) + node.newline_flag!(@lines) + super(node) + end # Permit statements lists to mark newlines within themselves. + #-- + #: (StatementsNode node) -> void def visit_statements_node(node) node.body.each do |child| child.newline_flag!(@lines) @@ -63,10 +94,16 @@ def visit_statements_node(node) end class Node + # Tracks whether or not this node should emit a newline event when the + # instructions that it represents are executed. + # @rbs @newline_flag: bool + + #: () -> bool def newline_flag? # :nodoc: !!defined?(@newline_flag) end + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: line = location.start_line unless lines[line] @@ -77,48 +114,56 @@ def newline_flag!(lines) # :nodoc: end class BeginNode < Node + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: # Never mark BeginNode with a newline flag, mark children instead. end end class ParenthesesNode < Node + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: # Never mark ParenthesesNode with a newline flag, mark children instead. end end class IfNode < Node + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: predicate.newline_flag!(lines) end end class UnlessNode < Node + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: predicate.newline_flag!(lines) end end class UntilNode < Node + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: predicate.newline_flag!(lines) end end class WhileNode < Node + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: predicate.newline_flag!(lines) end end class RescueModifierNode < Node + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: expression.newline_flag!(lines) end end class InterpolatedMatchLastLineNode < Node + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: first = parts.first first.newline_flag!(lines) if first @@ -126,6 +171,7 @@ def newline_flag!(lines) # :nodoc: end class InterpolatedRegularExpressionNode < Node + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: first = parts.first first.newline_flag!(lines) if first @@ -133,6 +179,7 @@ def newline_flag!(lines) # :nodoc: end class InterpolatedStringNode < Node + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: first = parts.first first.newline_flag!(lines) if first @@ -140,6 +187,7 @@ def newline_flag!(lines) # :nodoc: end class InterpolatedSymbolNode < Node + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: first = parts.first first.newline_flag!(lines) if first @@ -147,6 +195,7 @@ def newline_flag!(lines) # :nodoc: end class InterpolatedXStringNode < Node + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: first = parts.first first.newline_flag!(lines) if first diff --git a/lib/prism/pattern.rb b/lib/prism/pattern.rb index 6ad2d9e5b9..be0493df05 100644 --- a/lib/prism/pattern.rb +++ b/lib/prism/pattern.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true # :markup: markdown +#-- +# rbs_inline: enabled module Prism # A pattern is an object that wraps a Ruby pattern matching expression. The @@ -41,7 +43,9 @@ class Pattern class CompilationError < StandardError # Create a new CompilationError with the given representation of the node # that caused the error. - def initialize(repr) + #-- + #: (String repr) -> void + def initialize(repr) # :nodoc: super(<<~ERROR) prism was unable to compile the pattern you provided into a usable expression. It failed on to understand the node represented by: @@ -57,10 +61,13 @@ def initialize(repr) end # The query that this pattern was initialized with. - attr_reader :query + attr_reader :query #: String + # @rbs @compiled: Proc? # Create a new pattern with the given query. The query should be a string # containing a Ruby pattern matching expression. + #-- + #: (String query) -> void def initialize(query) @query = query @compiled = nil @@ -68,6 +75,8 @@ def initialize(query) # Compile the query into a callable object that can be used to match against # nodes. + #-- + #: () -> Proc def compile result = Prism.parse("case nil\nin #{query}\nend") @@ -84,7 +93,10 @@ def compile # pattern. If a block is given, it will be called with each node that # matches the pattern. If no block is given, an enumerator will be returned # that will yield each node that matches the pattern. - def scan(root) + #-- + #: (node root) -> Enumerator[node, void] + #: (node root) { (node) -> void } -> void + def scan(root, &blk) return to_enum(:scan, root) unless block_given? @compiled ||= compile @@ -100,23 +112,33 @@ def scan(root) # Shortcut for combining two procs into one that returns true if both return # true. - def combine_and(left, right) + #-- + #: (Proc left, Proc right) -> Proc + def combine_and(left, right) # :nodoc: ->(other) { left.call(other) && right.call(other) } end # Shortcut for combining two procs into one that returns true if either # returns true. - def combine_or(left, right) + #-- + #: (Proc left, Proc right) -> Proc + def combine_or(left, right) # :nodoc: ->(other) { left.call(other) || right.call(other) } end - # Raise an error because the given node is not supported. - def compile_error(node) + # Raise an error because the given node is not supported. Note purposefully + # not typing this method since it is a no return method that Steep does not + # understand. + #-- + #: (node node) -> bot + def compile_error(node) # :nodoc: raise CompilationError, node.inspect end # in [foo, bar, baz] - def compile_array_pattern_node(node) + #-- + #: (ArrayPatternNode node) -> Proc + def compile_array_pattern_node(node) # :nodoc: compile_error(node) if !node.rest.nil? || node.posts.any? constant = node.constant @@ -141,12 +163,16 @@ def compile_array_pattern_node(node) end # in foo | bar - def compile_alternation_pattern_node(node) + #-- + #: (AlternationPatternNode node) -> Proc + def compile_alternation_pattern_node(node) # :nodoc: combine_or(compile_node(node.left), compile_node(node.right)) end # in Prism::ConstantReadNode - def compile_constant_path_node(node) + #-- + #: (ConstantPathNode node) -> Proc + def compile_constant_path_node(node) # :nodoc: parent = node.parent if parent.is_a?(ConstantReadNode) && parent.slice == "Prism" @@ -161,12 +187,16 @@ def compile_constant_path_node(node) # in ConstantReadNode # in String - def compile_constant_read_node(node) + #-- + #: (ConstantReadNode node) -> Proc + def compile_constant_read_node(node) # :nodoc: compile_constant_name(node, node.name) end # Compile a name associated with a constant. - def compile_constant_name(node, name) + #-- + #: ((ConstantPathNode | ConstantReadNode) node, Symbol name) -> Proc + def compile_constant_name(node, name) # :nodoc: if Prism.const_defined?(name, false) clazz = Prism.const_get(name) @@ -182,9 +212,14 @@ def compile_constant_name(node, name) # in InstanceVariableReadNode[name: Symbol] # in { name: Symbol } - def compile_hash_pattern_node(node) + #-- + #: (HashPatternNode node) -> Proc + def compile_hash_pattern_node(node) # :nodoc: compile_error(node) if node.rest - compiled_constant = compile_node(node.constant) if node.constant + + if (constant = node.constant) + compiled_constant = compile_node(constant) + end preprocessed = node.elements.to_h do |element| @@ -212,12 +247,16 @@ def compile_hash_pattern_node(node) end # in nil - def compile_nil_node(node) + #-- + #: (NilNode node) -> Proc + def compile_nil_node(node) # :nodoc: ->(attribute) { attribute.nil? } end # in /foo/ - def compile_regular_expression_node(node) + #-- + #: (RegularExpressionNode node) -> Proc + def compile_regular_expression_node(node) # :nodoc: regexp = Regexp.new(node.unescaped, node.closing[1..]) ->(attribute) { regexp === attribute } @@ -225,7 +264,9 @@ def compile_regular_expression_node(node) # in "" # in "foo" - def compile_string_node(node) + #-- + #: (StringNode node) -> Proc + def compile_string_node(node) # :nodoc: string = node.unescaped ->(attribute) { string === attribute } @@ -233,7 +274,9 @@ def compile_string_node(node) # in :+ # in :foo - def compile_symbol_node(node) + #-- + #: (SymbolNode node) -> Proc + def compile_symbol_node(node) # :nodoc: symbol = node.unescaped.to_sym ->(attribute) { symbol === attribute } @@ -241,7 +284,9 @@ def compile_symbol_node(node) # Compile any kind of node. Dispatch out to the individual compilation # methods based on the type of node. - def compile_node(node) + #-- + #: (node node) -> Proc + def compile_node(node) # :nodoc: case node when AlternationPatternNode compile_alternation_pattern_node(node) diff --git a/lib/prism/relocation.rb b/lib/prism/relocation.rb index 3e9210a785..af0f792827 100644 --- a/lib/prism/relocation.rb +++ b/lib/prism/relocation.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true # :markup: markdown +#-- +# rbs_inline: enabled module Prism # Prism parses deterministically for the same input. This provides a nice @@ -12,6 +14,33 @@ module Prism # "save" nodes and locations using a minimal amount of memory (just the # node_id and a field identifier) and then reify them later. module Relocation + # @rbs! + # type entry_value = untyped + # type entry_values = Hash[Symbol, entry_value] + # + # interface _Value + # def start_line: () -> Integer + # def end_line: () -> Integer + # def start_offset: () -> Integer + # def end_offset: () -> Integer + # def start_character_offset: () -> Integer + # def end_character_offset: () -> Integer + # def cached_start_code_units_offset: (_CodeUnitsCache cache) -> Integer + # def cached_end_code_units_offset: (_CodeUnitsCache cache) -> Integer + # def start_column: () -> Integer + # def end_column: () -> Integer + # def start_character_column: () -> Integer + # def end_character_column: () -> Integer + # def cached_start_code_units_column: (_CodeUnitsCache cache) -> Integer + # def cached_end_code_units_column: (_CodeUnitsCache cache) -> Integer + # def leading_comments: () -> Array[Comment] + # def trailing_comments: () -> Array[Comment] + # end + # + # interface _Field + # def fields: (_Value value) -> entry_values + # end + # An entry in a repository that will lazily reify its values when they are # first accessed. class Entry @@ -21,109 +50,152 @@ class Entry class MissingValueError < StandardError end + # @rbs @repository: Repository? + # @rbs @values: Hash[Symbol, untyped]? + # Initialize a new entry with the given repository. + #-- + #: (Repository repository) -> void def initialize(repository) @repository = repository @values = nil end # Fetch the filepath of the value. + #-- + #: () -> String def filepath fetch_value(:filepath) end # Fetch the start line of the value. + #-- + #: () -> Integer def start_line fetch_value(:start_line) end # Fetch the end line of the value. + #-- + #: () -> Integer def end_line fetch_value(:end_line) end # Fetch the start byte offset of the value. + #-- + #: () -> Integer def start_offset fetch_value(:start_offset) end # Fetch the end byte offset of the value. + #-- + #: () -> Integer def end_offset fetch_value(:end_offset) end # Fetch the start character offset of the value. + #-- + #: () -> Integer def start_character_offset fetch_value(:start_character_offset) end # Fetch the end character offset of the value. + #-- + #: () -> Integer def end_character_offset fetch_value(:end_character_offset) end # Fetch the start code units offset of the value, for the encoding that # was configured on the repository. + #-- + #: () -> Integer def start_code_units_offset fetch_value(:start_code_units_offset) end # Fetch the end code units offset of the value, for the encoding that was # configured on the repository. + #-- + #: () -> Integer def end_code_units_offset fetch_value(:end_code_units_offset) end # Fetch the start byte column of the value. + #-- + #: () -> Integer def start_column fetch_value(:start_column) end # Fetch the end byte column of the value. + #-- + #: () -> Integer def end_column fetch_value(:end_column) end # Fetch the start character column of the value. + #-- + #: () -> Integer def start_character_column fetch_value(:start_character_column) end # Fetch the end character column of the value. + #-- + #: () -> Integer def end_character_column fetch_value(:end_character_column) end # Fetch the start code units column of the value, for the encoding that # was configured on the repository. + #-- + #: () -> Integer def start_code_units_column fetch_value(:start_code_units_column) end # Fetch the end code units column of the value, for the encoding that was # configured on the repository. + #-- + #: () -> Integer def end_code_units_column fetch_value(:end_code_units_column) end # Fetch the leading comments of the value. + #-- + #: () -> Array[CommentsField::Comment] def leading_comments fetch_value(:leading_comments) end # Fetch the trailing comments of the value. + #-- + #: () -> Array[CommentsField::Comment] def trailing_comments fetch_value(:trailing_comments) end # Fetch the leading and trailing comments of the value. + #-- + #: () -> Array[CommentsField::Comment] def comments - leading_comments.concat(trailing_comments) + [*leading_comments, *trailing_comments] end # Reify the values on this entry with the given values. This is an # internal-only API that is called from the repository when it is time to # reify the values. + #-- + #: (entry_values values) -> void def reify!(values) # :nodoc: @repository = nil @values = values @@ -132,6 +204,8 @@ def reify!(values) # :nodoc: private # Fetch a value from the entry, raising an error if it is missing. + #-- + #: (Symbol name) -> entry_value def fetch_value(name) values.fetch(name) do raise MissingValueError, "No value for #{name}, make sure the " \ @@ -140,27 +214,35 @@ def fetch_value(name) end # Return the values from the repository, reifying them if necessary. + #-- + #: () -> entry_values def values - @values || (@repository.reify!; @values) + @values || (@repository&.reify!; @values) #: entry_values end end # Represents the source of a repository that will be reparsed. class Source # The value that will need to be reparsed. - attr_reader :value + attr_reader :value #: untyped # Initialize the source with the given value. + #-- + #: (untyped value) -> void def initialize(value) @value = value end # Reparse the value and return the parse result. + #-- + #: () -> ParseResult def result raise NotImplementedError, "Subclasses must implement #result" end # Create a code units cache for the given encoding. + #-- + #: (Encoding encoding) -> _CodeUnitsCache def code_units_cache(encoding) result.code_units_cache(encoding) end @@ -169,6 +251,8 @@ def code_units_cache(encoding) # A source that is represented by a file path. class SourceFilepath < Source # Reparse the file and return the parse result. + #-- + #: () -> ParseResult def result Prism.parse_file(value) end @@ -177,6 +261,8 @@ def result # A source that is represented by a string. class SourceString < Source # Reparse the string and return the parse result. + #-- + #: () -> ParseResult def result Prism.parse(value) end @@ -185,14 +271,18 @@ def result # A field that represents the file path. class FilepathField # The file path that this field represents. - attr_reader :value + attr_reader :value #: String # Initialize a new field with the given file path. + #-- + #: (String value) -> void def initialize(value) @value = value end # Fetch the file path. + #-- + #: (_Value _value) -> entry_values def fields(_value) { filepath: value } end @@ -201,6 +291,8 @@ def fields(_value) # A field representing the start and end lines. class LinesField # Fetches the start and end line of a value. + #-- + #: (_Value value) -> entry_values def fields(value) { start_line: value.start_line, end_line: value.end_line } end @@ -209,6 +301,8 @@ def fields(value) # A field representing the start and end byte offsets. class OffsetsField # Fetches the start and end byte offset of a value. + #-- + #: (_Value value) -> entry_values def fields(value) { start_offset: value.start_offset, end_offset: value.end_offset } end @@ -217,6 +311,8 @@ def fields(value) # A field representing the start and end character offsets. class CharacterOffsetsField # Fetches the start and end character offset of a value. + #-- + #: (_Value value) -> entry_values def fields(value) { start_character_offset: value.start_character_offset, @@ -229,12 +325,16 @@ def fields(value) class CodeUnitOffsetsField # A pointer to the repository object that is used for lazily creating a # code units cache. - attr_reader :repository + attr_reader :repository #: Repository # The associated encoding for the code units. - attr_reader :encoding + attr_reader :encoding #: Encoding + + # @rbs @cache: _CodeUnitsCache? # Initialize a new field with the associated repository and encoding. + #-- + #: (Repository repository, Encoding encoding) -> void def initialize(repository, encoding) @repository = repository @encoding = encoding @@ -243,6 +343,8 @@ def initialize(repository, encoding) # Fetches the start and end code units offset of a value for a particular # encoding. + #-- + #: (_Value value) -> entry_values def fields(value) { start_code_units_offset: value.cached_start_code_units_offset(cache), @@ -253,6 +355,8 @@ def fields(value) private # Lazily create a code units cache for the associated encoding. + #-- + #: () -> _CodeUnitsCache def cache @cache ||= repository.code_units_cache(encoding) end @@ -261,6 +365,8 @@ def cache # A field representing the start and end byte columns. class ColumnsField # Fetches the start and end byte column of a value. + #-- + #: (_Value value) -> entry_values def fields(value) { start_column: value.start_column, end_column: value.end_column } end @@ -269,6 +375,8 @@ def fields(value) # A field representing the start and end character columns. class CharacterColumnsField # Fetches the start and end character column of a value. + #-- + #: (_Value value) -> entry_values def fields(value) { start_character_column: value.start_character_column, @@ -282,12 +390,16 @@ def fields(value) class CodeUnitColumnsField # The repository object that is used for lazily creating a code units # cache. - attr_reader :repository + attr_reader :repository #: Repository # The associated encoding for the code units. - attr_reader :encoding + attr_reader :encoding #: Encoding + + # @rbs @cache: _CodeUnitsCache? # Initialize a new field with the associated repository and encoding. + #-- + #: (Repository repository, Encoding encoding) -> void def initialize(repository, encoding) @repository = repository @encoding = encoding @@ -296,6 +408,8 @@ def initialize(repository, encoding) # Fetches the start and end code units column of a value for a particular # encoding. + #-- + #: (_Value value) -> entry_values def fields(value) { start_code_units_column: value.cached_start_code_units_column(cache), @@ -306,6 +420,8 @@ def fields(value) private # Lazily create a code units cache for the associated encoding. + #-- + #: () -> _CodeUnitsCache def cache @cache ||= repository.code_units_cache(encoding) end @@ -316,9 +432,11 @@ class CommentsField # An object that represents a slice of a comment. class Comment # The slice of the comment. - attr_reader :slice + attr_reader :slice #: String # Initialize a new comment with the given slice. + # + #: (String slice) -> void def initialize(slice) @slice = slice end @@ -327,6 +445,8 @@ def initialize(slice) private # Create comment objects from the given values. + #-- + #: (entry_value values) -> Array[Comment] def comments(values) values.map { |value| Comment.new(value.slice) } end @@ -335,6 +455,8 @@ def comments(values) # A field representing the leading comments. class LeadingCommentsField < CommentsField # Fetches the leading comments of a value. + #-- + #: (_Value value) -> entry_values def fields(value) { leading_comments: comments(value.leading_comments) } end @@ -343,6 +465,8 @@ def fields(value) # A field representing the trailing comments. class TrailingCommentsField < CommentsField # Fetches the trailing comments of a value. + #-- + #: (_Value value) -> entry_values def fields(value) { trailing_comments: comments(value.trailing_comments) } end @@ -358,15 +482,17 @@ class ConfigurationError < StandardError # The source associated with this repository. This will be either a # SourceFilepath (the most common use case) or a SourceString. - attr_reader :source + attr_reader :source #: Source # The fields that have been configured on this repository. - attr_reader :fields + attr_reader :fields #: Hash[Symbol, _Field] # The entries that have been saved on this repository. - attr_reader :entries + attr_reader :entries #: Hash[Integer, Hash[Symbol, Entry]] # Initialize a new repository with the given source. + #-- + #: (Source source) -> void def initialize(source) @source = source @fields = {} @@ -374,69 +500,93 @@ def initialize(source) end # Create a code units cache for the given encoding from the source. + #-- + #: (Encoding encoding) -> _CodeUnitsCache def code_units_cache(encoding) source.code_units_cache(encoding) end # Configure the filepath field for this repository and return self. + #-- + #: () -> self def filepath raise ConfigurationError, "Can only specify filepath for a filepath source" unless source.is_a?(SourceFilepath) field(:filepath, FilepathField.new(source.value)) end # Configure the lines field for this repository and return self. + #-- + #: () -> self def lines field(:lines, LinesField.new) end # Configure the offsets field for this repository and return self. + #-- + #: () -> self def offsets field(:offsets, OffsetsField.new) end # Configure the character offsets field for this repository and return # self. + #-- + #: () -> self def character_offsets field(:character_offsets, CharacterOffsetsField.new) end # Configure the code unit offsets field for this repository for a specific # encoding and return self. + #-- + #: (Encoding encoding) -> self def code_unit_offsets(encoding) field(:code_unit_offsets, CodeUnitOffsetsField.new(self, encoding)) end # Configure the columns field for this repository and return self. + #-- + #: () -> self def columns field(:columns, ColumnsField.new) end # Configure the character columns field for this repository and return # self. + #-- + #: () -> self def character_columns field(:character_columns, CharacterColumnsField.new) end # Configure the code unit columns field for this repository for a specific # encoding and return self. + #-- + #: (Encoding encoding) -> self def code_unit_columns(encoding) field(:code_unit_columns, CodeUnitColumnsField.new(self, encoding)) end # Configure the leading comments field for this repository and return # self. + #-- + #: () -> self def leading_comments field(:leading_comments, LeadingCommentsField.new) end # Configure the trailing comments field for this repository and return # self. + #-- + #: () -> self def trailing_comments field(:trailing_comments, TrailingCommentsField.new) end # Configure both the leading and trailing comment fields for this # repository and return self. + #-- + #: () -> self def comments leading_comments.trailing_comments end @@ -444,6 +594,8 @@ def comments # This method is called from nodes and locations when they want to enter # themselves into the repository. It it internal-only and meant to be # called from the #save* APIs. + #-- + #: (Integer node_id, Symbol field_name) -> Entry def enter(node_id, field_name) # :nodoc: entry = Entry.new(self) @entries[node_id][field_name] = entry @@ -453,6 +605,8 @@ def enter(node_id, field_name) # :nodoc: # This method is called from the entries in the repository when they need # to reify their values. It is internal-only and meant to be called from # the various value APIs. + #-- + #: () -> void def reify! # :nodoc: result = source.result @@ -466,7 +620,7 @@ def reify! # :nodoc: while (node = queue.shift) @entries[node.node_id].each do |field_name, entry| value = node.public_send(field_name) - values = {} #: Hash[Symbol, untyped] + values = {} #: entry_values fields.each_value do |field| values.merge!(field.fields(value)) @@ -485,6 +639,8 @@ def reify! # :nodoc: # Append the given field to the repository and return the repository so # that these calls can be chained. + #-- + #: (Symbol name, _Field) -> self def field(name, value) raise ConfigurationError, "Cannot specify multiple #{name} fields" if @fields.key?(name) @fields[name] = value @@ -493,11 +649,15 @@ def field(name, value) end # Create a new repository for the given filepath. + #-- + #: (String value) -> Repository def self.filepath(value) Repository.new(SourceFilepath.new(value)) end # Create a new repository for the given string. + #-- + #: (String value) -> Repository def self.string(value) Repository.new(SourceString.new(value)) end diff --git a/lib/prism/string_query.rb b/lib/prism/string_query.rb index 547f58d2fa..99ce57e5fe 100644 --- a/lib/prism/string_query.rb +++ b/lib/prism/string_query.rb @@ -1,29 +1,44 @@ # frozen_string_literal: true # :markup: markdown +#-- +# rbs_inline: enabled 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 + # @rbs! + # def self.local?: (String string) -> bool + # def self.constant?: (String string) -> bool + # def self.method_name?: (String string) -> bool + # The string that this query is wrapping. - attr_reader :string + attr_reader :string #: String # Initialize a new query with the given string. + #-- + #: (String string) -> void def initialize(string) @string = string end # Whether or not this string is a valid local variable name. + #-- + #: () -> bool def local? StringQuery.local?(string) end # Whether or not this string is a valid constant name. + #-- + #: () -> bool def constant? StringQuery.constant?(string) end # Whether or not this string is a valid method name. + #-- + #: () -> bool def method_name? StringQuery.method_name?(string) end diff --git a/lib/prism/translation.rb b/lib/prism/translation.rb index 57b57135bc..5a086a7542 100644 --- a/lib/prism/translation.rb +++ b/lib/prism/translation.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true # :markup: markdown +#-- +# rbs_inline: enabled module Prism # This module is responsible for converting the prism syntax tree into other diff --git a/lib/prism/translation/parser.rb b/lib/prism/translation/parser.rb index fed4ac4cd1..70031f133a 100644 --- a/lib/prism/translation/parser.rb +++ b/lib/prism/translation/parser.rb @@ -33,7 +33,7 @@ class Parser < ::Parser::Base # The parser gem has a list of diagnostics with a hard-coded set of error # messages. We create our own diagnostic class in order to set our own # error messages. - class PrismDiagnostic < Diagnostic + class PrismDiagnostic < Diagnostic # :nodoc: # This is the cached message coming from prism. attr_reader :message diff --git a/lib/prism/translation/parser/builder.rb b/lib/prism/translation/parser/builder.rb index 6b620c25bc..7fc3bba6b7 100644 --- a/lib/prism/translation/parser/builder.rb +++ b/lib/prism/translation/parser/builder.rb @@ -7,12 +7,14 @@ class Parser # A builder that knows how to convert more modern Ruby syntax # into whitequark/parser gem's syntax tree. class Builder < ::Parser::Builders::Default - # It represents the `it` block argument, which is not yet implemented in the Parser gem. + # It represents the `it` block argument, which is not yet implemented in + # the Parser gem. def itarg n(:itarg, [:it], nil) end - # The following three lines have been added to support the `it` block parameter syntax in the source code below. + # The following three lines have been added to support the `it` block + # parameter syntax in the source code below. # # if args.type == :itarg # block_type = :itblock @@ -56,6 +58,12 @@ def block(method_call, begin_t, args, body, end_t) method_call.loc.with_expression(join_exprs(method_call, block))) end end + + # def foo(&nil); end + # ^^^^ + def blocknilarg(amper_t, nil_t) + n0(:blocknilarg, arg_prefix_map(amper_t, nil_t)) + end end end end diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb index bd3618b162..21aa7796c3 100644 --- a/lib/prism/translation/parser/compiler.rb +++ b/lib/prism/translation/parser/compiler.rb @@ -6,9 +6,9 @@ module Translation class Parser # A visitor that knows how to convert a prism syntax tree into the # whitequark/parser gem's syntax tree. - class Compiler < ::Prism::Compiler + class Compiler < ::Prism::Compiler # :nodoc: # Raised when the tree is malformed or there is a bug in the compiler. - class CompilationError < StandardError + class CompilationError < StandardError # :nodoc: end # The Parser::Base instance that is being used to build the AST. @@ -1390,6 +1390,12 @@ def visit_nil_node(node) builder.nil(token(node.location)) end + # def foo(&nil); end + # ^^^^ + def visit_no_block_parameter_node(node) + builder.blocknilarg(token(node.operator_loc), token(node.keyword_loc)) + end + # def foo(**nil); end # ^^^^^ def visit_no_keywords_parameter_node(node) diff --git a/lib/prism/translation/parser/lexer.rb b/lib/prism/translation/parser/lexer.rb index 0491e79cd2..e82042867f 100644 --- a/lib/prism/translation/parser/lexer.rb +++ b/lib/prism/translation/parser/lexer.rb @@ -10,7 +10,7 @@ module Translation class Parser # Accepts a list of prism tokens and converts them into the expected # format for the parser gem. - class Lexer + class Lexer # :nodoc: # These tokens are always skipped TYPES_ALWAYS_SKIP = Set.new(%i[IGNORED_NEWLINE __END__ EOF]) private_constant :TYPES_ALWAYS_SKIP @@ -87,6 +87,7 @@ class Lexer KEYWORD_DEF: :kDEF, KEYWORD_DEFINED: :kDEFINED, KEYWORD_DO: :kDO, + KEYWORD_DO_BLOCK: :kDO_BLOCK, KEYWORD_DO_LOOP: :kDO_COND, KEYWORD_END: :kEND, KEYWORD_END_UPCASE: :klEND, @@ -188,8 +189,8 @@ class Lexer # without them. We should find another way to do this, but in the # meantime we'll hide them from the documentation and mark them as # private constants. - EXPR_BEG = 0x1 # :nodoc: - EXPR_LABEL = 0x400 # :nodoc: + EXPR_BEG = 0x1 + EXPR_LABEL = 0x400 # It is used to determine whether `do` is of the token type `kDO` or `kDO_LAMBDA`. # @@ -232,7 +233,7 @@ def initialize(source_buffer, lexed, offset_cache) @offset_cache = offset_cache end - Range = ::Parser::Source::Range # :nodoc: + Range = ::Parser::Source::Range private_constant :Range # Convert the prism tokens into the expected format for the parser gem. diff --git a/lib/prism/translation/parser_current.rb b/lib/prism/translation/parser_current.rb index f13eff6bbe..f7c1070e30 100644 --- a/lib/prism/translation/parser_current.rb +++ b/lib/prism/translation/parser_current.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true # :markup: markdown +#-- # typed: ignore -# module Prism module Translation case RUBY_VERSION diff --git a/lib/prism/translation/ripper.rb b/lib/prism/translation/ripper.rb index 5b2aa37833..d1c28a2401 100644 --- a/lib/prism/translation/ripper.rb +++ b/lib/prism/translation/ripper.rb @@ -594,6 +594,8 @@ def parse # Visitor methods ########################################################################## + # :stopdoc: + # alias foo bar # ^^^^^^^^^^^^^ def visit_alias_method_node(node) @@ -2621,6 +2623,13 @@ def visit_nil_node(node) on_var_ref(on_kw("nil")) end + # def foo(&nil); end + # ^^^^ + def visit_no_block_parameter_node(node) + bounds(node.location) + on_blockarg(:nil) + end + # def foo(**nil); end # ^^^^^ def visit_no_keywords_parameter_node(node) @@ -3458,6 +3467,8 @@ def bounds(location) @column = location.start_column end + # :startdoc: + ########################################################################## # Ripper interface ########################################################################## diff --git a/lib/prism/translation/ripper/lexer.rb b/lib/prism/translation/ripper/lexer.rb index cbcdcd47cc..c6aeae4bd7 100644 --- a/lib/prism/translation/ripper/lexer.rb +++ b/lib/prism/translation/ripper/lexer.rb @@ -7,8 +7,7 @@ module Prism module Translation class Ripper class Lexer < Ripper # :nodoc: - # :stopdoc: - class State + class State # :nodoc: attr_reader :to_int, :to_s def initialize(i) @@ -48,7 +47,7 @@ def self.[](i) end end - class Elem + class Elem # :nodoc: attr_accessor :pos, :event, :tok, :state, :message def initialize(pos, event, tok, state, message = nil) @@ -128,8 +127,6 @@ def parse(...) def scan(...) parse(...) end - - # :startdoc: end end end diff --git a/lib/prism/translation/ripper/sexp.rb b/lib/prism/translation/ripper/sexp.rb index 8cfefc8472..46c0333544 100644 --- a/lib/prism/translation/ripper/sexp.rb +++ b/lib/prism/translation/ripper/sexp.rb @@ -8,9 +8,7 @@ module Translation class Ripper # This class mirrors the ::Ripper::SexpBuilder subclass of ::Ripper that # returns the arrays of [type, *children]. - class SexpBuilder < Ripper - # :stopdoc: - + class SexpBuilder < Ripper # :nodoc: attr_reader :error private @@ -65,16 +63,12 @@ def on_error(mesg) remove_method :on_parse_error alias on_parse_error on_error alias compile_error on_error - - # :startdoc: end # This class mirrors the ::Ripper::SexpBuilderPP subclass of ::Ripper that # returns the same values as ::Ripper::SexpBuilder except with a couple of # niceties that flatten linked lists into arrays. - class SexpBuilderPP < SexpBuilder - # :stopdoc: - + class SexpBuilderPP < SexpBuilder # :nodoc: private def on_heredoc_dedent(val, width) @@ -118,8 +112,6 @@ def on_mlhs_add_post(list, post) alias_method "on_#{event}", :_dispatch_event_push end end - - # :startdoc: end end end diff --git a/lib/prism/translation/ruby_parser.rb b/lib/prism/translation/ruby_parser.rb index c026c4ad9c..c1fb8adfc1 100644 --- a/lib/prism/translation/ruby_parser.rb +++ b/lib/prism/translation/ruby_parser.rb @@ -19,7 +19,7 @@ module Translation # seattlerb/ruby_parser gem's syntax tree. class RubyParser # A prism visitor that builds Sexp objects. - class Compiler < ::Prism::Compiler + class Compiler < ::Prism::Compiler # :nodoc: # This is the name of the file that we are compiling. We set it on every # Sexp object that is generated, and also use it to compile `__FILE__` # nodes. @@ -40,34 +40,26 @@ def initialize(file, in_def: false, in_pattern: false) @in_pattern = in_pattern end - # ``` # alias foo bar # ^^^^^^^^^^^^^ - # ``` def visit_alias_method_node(node) s(node, :alias, visit(node.new_name), visit(node.old_name)) end - # ``` # alias $foo $bar # ^^^^^^^^^^^^^^^ - # ``` def visit_alias_global_variable_node(node) s(node, :valias, node.new_name.name, node.old_name.name) end - # ``` # foo => bar | baz # ^^^^^^^^^ - # ``` def visit_alternation_pattern_node(node) s(node, :or, visit(node.left), visit(node.right)) end - # ``` # a and b # ^^^^^^^ - # ``` def visit_and_node(node) left = visit(node.left) @@ -84,10 +76,8 @@ def visit_and_node(node) end end - # ``` # [] # ^^ - # ``` def visit_array_node(node) if in_pattern s(node, :array_pat, nil).concat(visit_all(node.elements)) @@ -96,10 +86,8 @@ def visit_array_node(node) end end - # ``` # foo => [bar] # ^^^^^ - # ``` def visit_array_pattern_node(node) if node.constant.nil? && node.requireds.empty? && node.rest.nil? && node.posts.empty? s(node, :array_pat) @@ -121,29 +109,23 @@ def visit_array_pattern_node(node) end end - # ``` # foo(bar) # ^^^ - # ``` def visit_arguments_node(node) raise "Cannot visit arguments directly" end - # ``` # { a: 1 } # ^^^^ - # ``` def visit_assoc_node(node) [visit(node.key), visit(node.value)] end - # ``` # def foo(**); bar(**); end # ^^ # # { **foo } # ^^^^^ - # ``` def visit_assoc_splat_node(node) if node.value.nil? [s(node, :kwsplat)] @@ -152,18 +134,14 @@ def visit_assoc_splat_node(node) end end - # ``` # $+ # ^^ - # ``` def visit_back_reference_read_node(node) s(node, :back_ref, node.name.to_s.delete_prefix("$").to_sym) end - # ``` # begin end # ^^^^^^^^^ - # ``` def visit_begin_node(node) result = node.statements.nil? ? s(node, :nil) : visit(node.statements) @@ -195,20 +173,16 @@ def visit_begin_node(node) result end - # ``` # foo(&bar) # ^^^^ - # ``` def visit_block_argument_node(node) s(node, :block_pass).tap do |result| result << visit(node.expression) unless node.expression.nil? end end - # ``` # foo { |; bar| } # ^^^ - # ``` def visit_block_local_variable_node(node) node.name end @@ -218,10 +192,8 @@ def visit_block_node(node) s(node, :block_pass, visit(node.expression)) end - # ``` # def foo(&bar); end # ^^^^ - # ``` def visit_block_parameter_node(node) :"&#{node.name}" end @@ -262,13 +234,11 @@ def visit_block_parameters_node(node) result end - # ``` # break # ^^^^^ # # break foo # ^^^^^^^^^ - # ``` def visit_break_node(node) if node.arguments.nil? s(node, :break) @@ -279,7 +249,6 @@ def visit_break_node(node) end end - # ``` # foo # ^^^ # @@ -288,7 +257,6 @@ def visit_break_node(node) # # foo.bar() {} # ^^^^^^^^^^^^ - # ``` def visit_call_node(node) case node.name when :!~ @@ -327,10 +295,8 @@ def visit_call_node(node) visit_block(node, result, block) end - # ``` # foo.bar += baz # ^^^^^^^^^^^^^^^ - # ``` 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.binary_operator) @@ -339,10 +305,8 @@ def visit_call_operator_write_node(node) end end - # ``` # foo.bar &&= baz # ^^^^^^^^^^^^^^^ - # ``` def visit_call_and_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, :"&&") @@ -351,10 +315,8 @@ def visit_call_and_write_node(node) end end - # ``` # foo.bar ||= baz # ^^^^^^^^^^^^^^^ - # ``` def visit_call_or_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, :"||") @@ -376,42 +338,32 @@ def visit_call_or_write_node(node) node.safe_navigation? ? :"safe_#{type}" : type end - # ``` # foo.bar, = 1 # ^^^^^^^ - # ``` def visit_call_target_node(node) s(node, :attrasgn, visit(node.receiver), node.name) end - # ``` # foo => bar => baz # ^^^^^^^^^^ - # ``` def visit_capture_pattern_node(node) visit(node.target) << visit(node.value) end - # ``` # case foo; when bar; end # ^^^^^^^^^^^^^^^^^^^^^^^ - # ``` def visit_case_node(node) 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.else_clause) end - # ``` # class Foo; end # ^^^^^^^^^^^^^^ - # ``` def visit_class_node(node) name = if node.constant_path.is_a?(ConstantReadNode) @@ -434,53 +386,41 @@ def visit_class_node(node) result end - # ``` # @@foo # ^^^^^ - # ``` def visit_class_variable_read_node(node) s(node, :cvar, node.name) end - # ``` # @@foo = 1 # ^^^^^^^^^ # # @@foo, @@bar = 1 # ^^^^^ ^^^^^ - # ``` def visit_class_variable_write_node(node) s(node, class_variable_write_type, node.name, visit_write_value(node.value)) end - # ``` # @@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.binary_operator, visit_write_value(node.value))) end - # ``` # @@foo &&= bar # ^^^^^^^^^^^^^ - # ``` def visit_class_variable_and_write_node(node) s(node, :op_asgn_and, s(node, :cvar, node.name), s(node, class_variable_write_type, node.name, visit_write_value(node.value))) end - # ``` # @@foo ||= bar # ^^^^^^^^^^^^^ - # ``` def visit_class_variable_or_write_node(node) s(node, :op_asgn_or, s(node, :cvar, node.name), s(node, class_variable_write_type, node.name, visit_write_value(node.value))) end - # ``` # @@foo, = bar # ^^^^^ - # ``` def visit_class_variable_target_node(node) s(node, class_variable_write_type, node.name) end @@ -491,61 +431,47 @@ def visit_class_variable_target_node(node) in_def ? :cvasgn : :cvdecl end - # ``` # Foo # ^^^ - # ``` def visit_constant_read_node(node) s(node, :const, node.name) end - # ``` # Foo = 1 # ^^^^^^^ # # Foo, Bar = 1 # ^^^ ^^^ - # ``` def visit_constant_write_node(node) s(node, :cdecl, node.name, visit_write_value(node.value)) end - # ``` # Foo += bar # ^^^^^^^^^^^ - # ``` def visit_constant_operator_write_node(node) s(node, :cdecl, node.name, s(node, :call, s(node, :const, node.name), node.binary_operator, visit_write_value(node.value))) end - # ``` # Foo &&= bar # ^^^^^^^^^^^^ - # ``` def visit_constant_and_write_node(node) s(node, :op_asgn_and, s(node, :const, node.name), s(node, :cdecl, node.name, visit(node.value))) end - # ``` # Foo ||= bar # ^^^^^^^^^^^^ - # ``` def visit_constant_or_write_node(node) s(node, :op_asgn_or, s(node, :const, node.name), s(node, :cdecl, node.name, visit(node.value))) end - # ``` # Foo, = bar # ^^^ - # ``` def visit_constant_target_node(node) s(node, :cdecl, node.name) end - # ``` # Foo::Bar # ^^^^^^^^ - # ``` def visit_constant_path_node(node) if node.parent.nil? s(node, :colon3, node.name) @@ -554,45 +480,35 @@ def visit_constant_path_node(node) end end - # ``` # Foo::Bar = 1 # ^^^^^^^^^^^^ # # Foo::Foo, Bar::Bar = 1 # ^^^^^^^^ ^^^^^^^^ - # ``` def visit_constant_path_write_node(node) s(node, :cdecl, visit(node.target), visit_write_value(node.value)) end - # ``` # Foo::Bar += baz # ^^^^^^^^^^^^^^^ - # ``` def visit_constant_path_operator_write_node(node) s(node, :op_asgn, visit(node.target), node.binary_operator, visit_write_value(node.value)) end - # ``` # Foo::Bar &&= baz # ^^^^^^^^^^^^^^^^ - # ``` def visit_constant_path_and_write_node(node) s(node, :op_asgn_and, visit(node.target), visit_write_value(node.value)) end - # ``` # Foo::Bar ||= baz # ^^^^^^^^^^^^^^^^ - # ``` def visit_constant_path_or_write_node(node) s(node, :op_asgn_or, visit(node.target), visit_write_value(node.value)) end - # ``` # Foo::Bar, = baz # ^^^^^^^^ - # ``` def visit_constant_path_target_node(node) inner = if node.parent.nil? @@ -604,13 +520,11 @@ def visit_constant_path_target_node(node) s(node, :const, inner) end - # ``` # def foo; end # ^^^^^^^^^^^^ # # def self.foo; end # ^^^^^^^^^^^^^^^^^ - # ``` def visit_def_node(node) name = node.name_loc.slice.to_sym result = @@ -639,71 +553,55 @@ def visit_def_node(node) end end - # ``` # defined? a # ^^^^^^^^^^ # # defined?(a) # ^^^^^^^^^^^ - # ``` def visit_defined_node(node) s(node, :defined, visit(node.value)) end - # ``` # if foo then bar else baz end # ^^^^^^^^^^^^ - # ``` def visit_else_node(node) visit(node.statements) end - # ``` # "foo #{bar}" # ^^^^^^ - # ``` def visit_embedded_statements_node(node) result = s(node, :evstr) result << visit(node.statements) unless node.statements.nil? result end - # ``` # "foo #@bar" # ^^^^^ - # ``` def visit_embedded_variable_node(node) s(node, :evstr, visit(node.variable)) end - # ``` # begin; foo; ensure; bar; end # ^^^^^^^^^^^^ - # ``` def visit_ensure_node(node) node.statements.nil? ? s(node, :nil) : visit(node.statements) end - # ``` # false # ^^^^^ - # ``` def visit_false_node(node) s(node, :false) end - # ``` # foo => [*, bar, *] # ^^^^^^^^^^^ - # ``` def visit_find_pattern_node(node) s(node, :find_pat, visit_pattern_constant(node.constant), :"*#{node.left.expression&.name}", *visit_all(node.requireds), :"*#{node.right.expression&.name}") end - # ``` # if foo .. bar; end # ^^^^^^^^^^ - # ``` def visit_flip_flop_node(node) if node.left.is_a?(IntegerNode) && node.right.is_a?(IntegerNode) s(node, :lit, Range.new(node.left.value, node.right.value, node.exclude_end?)) @@ -712,112 +610,86 @@ def visit_flip_flop_node(node) end end - # ``` # 1.0 # ^^^ - # ``` def visit_float_node(node) s(node, :lit, node.value) end - # ``` # for foo in bar do end # ^^^^^^^^^^^^^^^^^^^^^ - # ``` def visit_for_node(node) s(node, :for, visit(node.collection), visit(node.index), visit(node.statements)) end - # ``` # def foo(...); bar(...); end # ^^^ - # ``` def visit_forwarding_arguments_node(node) s(node, :forward_args) end - # ``` # def foo(...); end # ^^^ - # ``` def visit_forwarding_parameter_node(node) s(node, :forward_args) end - # ``` # super # ^^^^^ # # super {} # ^^^^^^^^ - # ``` def visit_forwarding_super_node(node) visit_block(node, s(node, :zsuper), node.block) end - # ``` # $foo # ^^^^ - # ``` def visit_global_variable_read_node(node) s(node, :gvar, node.name) end - # ``` # $foo = 1 # ^^^^^^^^ # # $foo, $bar = 1 # ^^^^ ^^^^ - # ``` def visit_global_variable_write_node(node) s(node, :gasgn, node.name, visit_write_value(node.value)) end - # ``` # $foo += bar # ^^^^^^^^^^^ - # ``` def visit_global_variable_operator_write_node(node) s(node, :gasgn, node.name, s(node, :call, s(node, :gvar, node.name), node.binary_operator, visit(node.value))) end - # ``` # $foo &&= bar # ^^^^^^^^^^^^ - # ``` def visit_global_variable_and_write_node(node) s(node, :op_asgn_and, s(node, :gvar, node.name), s(node, :gasgn, node.name, visit_write_value(node.value))) end - # ``` # $foo ||= bar # ^^^^^^^^^^^^ - # ``` def visit_global_variable_or_write_node(node) s(node, :op_asgn_or, s(node, :gvar, node.name), s(node, :gasgn, node.name, visit_write_value(node.value))) end - # ``` # $foo, = bar # ^^^^ - # ``` def visit_global_variable_target_node(node) s(node, :gasgn, node.name) end - # ``` # {} # ^^ - # ``` def visit_hash_node(node) s(node, :hash).concat(node.elements.flat_map { |element| visit(element) }) end - # ``` # foo => {} # ^^ - # ``` def visit_hash_pattern_node(node) result = s(node, :hash_pat, visit_pattern_constant(node.constant)).concat(node.elements.flat_map { |element| visit(element) }) @@ -831,7 +703,6 @@ def visit_hash_pattern_node(node) result end - # ``` # if foo then bar end # ^^^^^^^^^^^^^^^^^^^ # @@ -840,7 +711,6 @@ 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.subsequent)) end @@ -850,24 +720,18 @@ def visit_imaginary_node(node) s(node, :lit, node.value) end - # ``` # { foo: } # ^^^^ - # ``` def visit_implicit_node(node) end - # ``` # foo { |bar,| } # ^ - # ``` def visit_implicit_rest_node(node) end - # ``` # case foo; in bar; end # ^^^^^^^^^^^^^^^^^^^^^ - # ``` def visit_in_node(node) pattern = if node.pattern.is_a?(ConstantPathNode) @@ -879,10 +743,8 @@ def visit_in_node(node) s(node, :in, pattern).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body)) end - # ``` # foo[bar] += baz # ^^^^^^^^^^^^^^^ - # ``` def visit_index_operator_write_node(node) arglist = nil @@ -894,10 +756,8 @@ def visit_index_operator_write_node(node) s(node, :op_asgn1, visit(node.receiver), arglist, node.binary_operator, visit_write_value(node.value)) end - # ``` # foo[bar] &&= baz # ^^^^^^^^^^^^^^^^ - # ``` def visit_index_and_write_node(node) arglist = nil @@ -909,10 +769,8 @@ def visit_index_and_write_node(node) s(node, :op_asgn1, visit(node.receiver), arglist, :"&&", visit_write_value(node.value)) end - # ``` # foo[bar] ||= baz # ^^^^^^^^^^^^^^^^ - # ``` def visit_index_or_write_node(node) arglist = nil @@ -924,10 +782,8 @@ def visit_index_or_write_node(node) s(node, :op_asgn1, visit(node.receiver), arglist, :"||", visit_write_value(node.value)) end - # ``` # foo[bar], = 1 # ^^^^^^^^ - # ``` def visit_index_target_node(node) arguments = visit_all(node.arguments&.arguments || []) arguments << visit(node.block) unless node.block.nil? @@ -935,69 +791,53 @@ def visit_index_target_node(node) s(node, :attrasgn, visit(node.receiver), :[]=).concat(arguments) end - # ``` # @foo # ^^^^ - # ``` def visit_instance_variable_read_node(node) s(node, :ivar, node.name) end - # ``` # @foo = 1 # ^^^^^^^^ # # @foo, @bar = 1 # ^^^^ ^^^^ - # ``` def visit_instance_variable_write_node(node) s(node, :iasgn, node.name, visit_write_value(node.value)) end - # ``` # @foo += bar # ^^^^^^^^^^^ - # ``` def visit_instance_variable_operator_write_node(node) s(node, :iasgn, node.name, s(node, :call, s(node, :ivar, node.name), node.binary_operator, visit_write_value(node.value))) end - # ``` # @foo &&= bar # ^^^^^^^^^^^^ - # ``` def visit_instance_variable_and_write_node(node) s(node, :op_asgn_and, s(node, :ivar, node.name), s(node, :iasgn, node.name, visit(node.value))) end - # ``` # @foo ||= bar # ^^^^^^^^^^^^ - # ``` def visit_instance_variable_or_write_node(node) s(node, :op_asgn_or, s(node, :ivar, node.name), s(node, :iasgn, node.name, visit(node.value))) end - # ``` # @foo, = bar # ^^^^ - # ``` def visit_instance_variable_target_node(node) s(node, :iasgn, node.name) end - # ``` # 1 # ^ - # ``` def visit_integer_node(node) s(node, :lit, node.value) end - # ``` # if /foo #{bar}/ then end # ^^^^^^^^^^^^ - # ``` def visit_interpolated_match_last_line_node(node) parts = visit_interpolated_parts(node.parts) regexp = @@ -1013,10 +853,8 @@ def visit_interpolated_match_last_line_node(node) s(node, :match, regexp) end - # ``` # /foo #{bar}/ # ^^^^^^^^^^^^ - # ``` def visit_interpolated_regular_expression_node(node) parts = visit_interpolated_parts(node.parts) @@ -1030,28 +868,22 @@ def visit_interpolated_regular_expression_node(node) end end - # ``` # "foo #{bar}" # ^^^^^^^^^^^^ - # ``` def visit_interpolated_string_node(node) parts = visit_interpolated_parts(node.parts) parts.length == 1 ? s(node, :str, parts.first) : s(node, :dstr).concat(parts) end - # ``` # :"foo #{bar}" # ^^^^^^^^^^^^^ - # ``` def visit_interpolated_symbol_node(node) parts = visit_interpolated_parts(node.parts) parts.length == 1 ? s(node, :lit, parts.first.to_sym) : s(node, :dsym).concat(parts) end - # ``` # `foo #{bar}` # ^^^^^^^^^^^^ - # ``` def visit_interpolated_x_string_node(node) source = node.heredoc? ? node.parts.first : node parts = visit_interpolated_parts(node.parts) @@ -1131,29 +963,23 @@ def visit_interpolated_x_string_node(node) results 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) s(node, :hash).concat(node.elements.flat_map { |element| visit(element) }) end - # ``` # def foo(**bar); end # ^^^^^ # # def foo(**); end # ^^ - # ``` def visit_keyword_rest_parameter_node(node) :"**#{node.name}" end @@ -1175,10 +1001,8 @@ def visit_lambda_node(node) end end - # ``` # foo # ^^^ - # ``` def visit_local_variable_read_node(node) if node.name.match?(/^_\d$/) s(node, :call, nil, node.name) @@ -1187,77 +1011,59 @@ def visit_local_variable_read_node(node) end end - # ``` # foo = 1 # ^^^^^^^ # # foo, bar = 1 # ^^^ ^^^ - # ``` def visit_local_variable_write_node(node) s(node, :lasgn, node.name, visit_write_value(node.value)) end - # ``` # foo += bar # ^^^^^^^^^^ - # ``` def visit_local_variable_operator_write_node(node) s(node, :lasgn, node.name, s(node, :call, s(node, :lvar, node.name), node.binary_operator, visit_write_value(node.value))) end - # ``` # foo &&= bar # ^^^^^^^^^^^ - # ``` def visit_local_variable_and_write_node(node) s(node, :op_asgn_and, s(node, :lvar, node.name), s(node, :lasgn, node.name, visit_write_value(node.value))) end - # ``` # foo ||= bar # ^^^^^^^^^^^ - # ``` def visit_local_variable_or_write_node(node) s(node, :op_asgn_or, s(node, :lvar, node.name), s(node, :lasgn, node.name, visit_write_value(node.value))) end - # ``` # foo, = bar # ^^^ - # ``` def visit_local_variable_target_node(node) s(node, :lasgn, node.name) end - # ``` # if /foo/ then end # ^^^^^ - # ``` def visit_match_last_line_node(node) s(node, :match, s(node, :lit, Regexp.new(node.unescaped, node.options))) end - # ``` # foo in bar # ^^^^^^^^^^ - # ``` def visit_match_predicate_node(node) s(node, :case, visit(node.value), s(node, :in, node.pattern.accept(copy_compiler(in_pattern: true)), nil), nil) end - # ``` # foo => bar # ^^^^^^^^^^ - # ``` def visit_match_required_node(node) s(node, :case, visit(node.value), s(node, :in, node.pattern.accept(copy_compiler(in_pattern: true)), nil), nil) end - # ``` # /(?foo)/ =~ bar # ^^^^^^^^^^^^^^^^^^^^ - # ``` def visit_match_write_node(node) s(node, :match2, visit(node.call.receiver), visit(node.call.arguments.arguments.first)) end @@ -1269,10 +1075,8 @@ def visit_missing_node(node) raise "Cannot visit missing node directly" end - # ``` # module Foo; end # ^^^^^^^^^^^^^^^ - # ``` def visit_module_node(node) name = if node.constant_path.is_a?(ConstantReadNode) @@ -1295,10 +1099,8 @@ def visit_module_node(node) result end - # ``` # foo, bar = baz # ^^^^^^^^ - # ``` def visit_multi_target_node(node) targets = [*node.lefts] targets << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) @@ -1307,10 +1109,8 @@ def visit_multi_target_node(node) s(node, :masgn, s(node, :array).concat(visit_all(targets))) end - # ``` # foo, bar = baz # ^^^^^^^^^^^^^^ - # ``` def visit_multi_write_node(node) targets = [*node.lefts] targets << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) @@ -1330,13 +1130,11 @@ def visit_multi_write_node(node) s(node, :masgn, s(node, :array).concat(visit_all(targets)), value) end - # ``` # next # ^^^^ # # next foo # ^^^^^^^^ - # ``` def visit_next_node(node) if node.arguments.nil? s(node, :next) @@ -1348,58 +1146,50 @@ def visit_next_node(node) end end - # ``` # nil # ^^^ - # ``` def visit_nil_node(node) s(node, :nil) end - # ``` + # def foo(&nil); end + # ^^^^ + def visit_no_block_parameter_node(node) + :"&nil" + end + # def foo(**nil); end # ^^^^^ - # ``` def visit_no_keywords_parameter_node(node) in_pattern ? s(node, :kwrest, :"**nil") : :"**nil" end - # ``` # -> { _1 + _2 } # ^^^^^^^^^^^^^^ - # ``` def visit_numbered_parameters_node(node) raise "Cannot visit numbered parameters directly" end - # ``` # $1 # ^^ - # ``` def visit_numbered_reference_read_node(node) s(node, :nth_ref, node.number) end - # ``` # def foo(bar: baz); end # ^^^^^^^^ - # ``` def visit_optional_keyword_parameter_node(node) s(node, :kwarg, node.name, visit(node.value)) end - # ``` # def foo(bar = 1); end # ^^^^^^^ - # ``` def visit_optional_parameter_node(node) s(node, :lasgn, node.name, visit(node.value)) end - # ``` # a or b # ^^^^^^ - # ``` def visit_or_node(node) left = visit(node.left) @@ -1416,10 +1206,8 @@ def visit_or_node(node) end end - # ``` # def foo(bar, *baz); end # ^^^^^^^^^ - # ``` def visit_parameters_node(node) children = node.each_child_node.map do |element| @@ -1433,10 +1221,8 @@ def visit_parameters_node(node) s(node, :args).concat(children) end - # ``` # def foo((bar, baz)); end # ^^^^^^^^^^ - # ``` private def visit_destructured_parameter(node) children = [*node.lefts, *node.rest, *node.rights].map do |child| @@ -1455,13 +1241,11 @@ def visit_parameters_node(node) s(node, :masgn).concat(children) end - # ``` # () # ^^ # # (1) # ^^^ - # ``` def visit_parentheses_node(node) if node.body.nil? s(node, :nil) @@ -1470,18 +1254,14 @@ def visit_parentheses_node(node) end end - # ``` # foo => ^(bar) # ^^^^^^ - # ``` def visit_pinned_expression_node(node) node.expression.accept(copy_compiler(in_pattern: false)) end - # ``` # foo = 1 and bar => ^foo # ^^^^ - # ``` def visit_pinned_variable_node(node) if node.variable.is_a?(LocalVariableReadNode) && node.variable.name.match?(/^_\d$/) s(node, :lvar, node.variable.name) @@ -1505,10 +1285,8 @@ def visit_program_node(node) visit(node.statements) end - # ``` # 0..5 # ^^^^ - # ``` def visit_range_node(node) if !in_pattern && !node.left.nil? && !node.right.nil? && ([node.left.type, node.right.type] - %i[nil_node integer_node]).empty? left = node.left.value if node.left.is_a?(IntegerNode) @@ -1529,58 +1307,44 @@ def visit_range_node(node) end end - # ``` # 1r # ^^ - # ``` def visit_rational_node(node) s(node, :lit, node.value) end - # ``` # redo # ^^^^ - # ``` def visit_redo_node(node) s(node, :redo) end - # ``` # /foo/ # ^^^^^ - # ``` def visit_regular_expression_node(node) s(node, :lit, Regexp.new(node.unescaped, node.options)) end - # ``` # def foo(bar:); end # ^^^^ - # ``` def visit_required_keyword_parameter_node(node) s(node, :kwarg, node.name) end - # ``` # def foo(bar); end # ^^^ - # ``` def visit_required_parameter_node(node) node.name end - # ``` # foo rescue bar # ^^^^^^^^^^^^^^ - # ``` def visit_rescue_modifier_node(node) s(node, :rescue, visit(node.expression), s(node.rescue_expression, :resbody, s(node.rescue_expression, :array), visit(node.rescue_expression))) end - # ``` # begin; rescue; end # ^^^^^^^ - # ``` def visit_rescue_node(node) exceptions = if node.exceptions.length == 1 && node.exceptions.first.is_a?(SplatNode) @@ -1596,32 +1360,26 @@ def visit_rescue_node(node) s(node, :resbody, exceptions).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body)) end - # ``` # def foo(*bar); end # ^^^^ # # def foo(*); end # ^ - # ``` def visit_rest_parameter_node(node) :"*#{node.name}" end - # ``` # retry # ^^^^^ - # ``` def visit_retry_node(node) s(node, :retry) end - # ``` # return # ^^^^^^ # # return 1 # ^^^^^^^^ - # ``` def visit_return_node(node) if node.arguments.nil? s(node, :return) @@ -1633,10 +1391,8 @@ def visit_return_node(node) end end - # ``` # self # ^^^^ - # ``` def visit_self_node(node) s(node, :self) end @@ -1646,42 +1402,33 @@ def visit_shareable_constant_node(node) visit(node.write) end - # ``` # class << self; end # ^^^^^^^^^^^^^^^^^^ - # ``` def visit_singleton_class_node(node) s(node, :sclass, visit(node.expression)).tap do |sexp| sexp << node.body.accept(copy_compiler(in_def: false)) unless node.body.nil? end end - # ``` # __ENCODING__ # ^^^^^^^^^^^^ - # ``` def visit_source_encoding_node(node) # TODO s(node, :colon2, s(node, :const, :Encoding), :UTF_8) end - # ``` # __FILE__ # ^^^^^^^^ - # ``` def visit_source_file_node(node) s(node, :str, node.filepath) end - # ``` # __LINE__ # ^^^^^^^^ - # ``` def visit_source_line_node(node) s(node, :lit, node.location.start_line) end - # ``` # foo(*bar) # ^^^^ # @@ -1690,7 +1437,6 @@ def visit_source_line_node(node) # # def foo(*); bar(*); end # ^ - # ``` def visit_splat_node(node) if node.expression.nil? s(node, :splat) @@ -1710,10 +1456,8 @@ def visit_statements_node(node) end end - # ``` # "foo" # ^^^^^ - # ``` def visit_string_node(node) unescaped = node.unescaped @@ -1725,10 +1469,8 @@ def visit_string_node(node) s(node, :str, unescaped) end - # ``` # super(foo) # ^^^^^^^^^^ - # ``` def visit_super_node(node) arguments = node.arguments&.arguments || [] block = node.block @@ -1741,76 +1483,60 @@ def visit_super_node(node) visit_block(node, s(node, :super).concat(visit_all(arguments)), block) end - # ``` # :foo # ^^^^ - # ``` def visit_symbol_node(node) node.value == "!@" ? s(node, :lit, :"!@") : s(node, :lit, node.unescaped.to_sym) end - # ``` # true # ^^^^ - # ``` def visit_true_node(node) s(node, :true) end - # ``` # undef foo # ^^^^^^^^^ - # ``` def visit_undef_node(node) names = node.names.map { |name| s(node, :undef, visit(name)) } names.length == 1 ? names.first : s(node, :block).concat(names) end - # ``` # unless foo; bar end # ^^^^^^^^^^^^^^^^^^^ # # bar unless foo # ^^^^^^^^^^^^^^ - # ``` def visit_unless_node(node) s(node, :if, visit(node.predicate), visit(node.else_clause), visit(node.statements)) end - # ``` # until foo; bar end # ^^^^^^^^^^^^^^^^^ # # bar until foo # ^^^^^^^^^^^^^ - # ``` def visit_until_node(node) s(node, :until, visit(node.predicate), visit(node.statements), !node.begin_modifier?) end - # ``` # case foo; when bar; end # ^^^^^^^^^^^^^ - # ``` def visit_when_node(node) s(node, :when, s(node, :array).concat(visit_all(node.conditions))).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body)) end - # ``` # while foo; bar end # ^^^^^^^^^^^^^^^^^^ # # bar while foo # ^^^^^^^^^^^^^ - # ``` def visit_while_node(node) s(node, :while, visit(node.predicate), visit(node.statements), !node.begin_modifier?) end - # ``` # `foo` # ^^^^^ - # ``` def visit_x_string_node(node) result = s(node, :xstr, node.unescaped) @@ -1822,13 +1548,11 @@ def visit_x_string_node(node) result end - # ``` # yield # ^^^^^ # # yield 1 # ^^^^^^^ - # ``` def visit_yield_node(node) s(node, :yield).concat(visit_all(node.arguments&.arguments || [])) end diff --git a/lib/prism/wasm.rb b/lib/prism/wasm.rb new file mode 100644 index 0000000000..e57c6bb375 --- /dev/null +++ b/lib/prism/wasm.rb @@ -0,0 +1,377 @@ +# frozen_string_literal: true +# :markup: markdown +# typed: ignore + +# This file is responsible for mirroring the API provided by the C extension by +# using FFI to call into the shared library. + +require "rbconfig" +require "ffi" + +# We want to eagerly load this file if there are Ractors so that it does not get +# autoloaded from within a non-main Ractor. +require "prism/serialize" if defined?(Ractor) + +# Load the prism-parser-wasm jar +require 'jar-dependencies' +require_jar('org.ruby-lang', 'prism-parser-wasm', '0.0.1-SNAPSHOT') +require_jar('com.dylibso.chicory', 'runtime', '1.6.1') +require_jar('com.dylibso.chicory', 'wasi', '1.6.1') +require_jar('com.dylibso.chicory', 'wasm', '1.6.1') +require_jar('com.dylibso.chicory', 'log', '1.6.1') + +module Prism # :nodoc: + module WASM + java_import org.ruby_lang.prism.wasm.Prism + + # TODO: concurrency + PRISM = org.ruby_lang.prism.wasm.Prism.new + end + private_constant :WASM + + # The version constant is set by reading the result of calling pm_version. + VERSION = WASM::PRISM.version + + class << self + # Mirror the Prism.dump API by using the serialization API. + def dump(source, **options) + parsed = WASM::PRISM.parse(source.to_java_bytes, dump_options(options).to_java_bytes) + String.from_java_bytes(parsed) + end + + # Mirror the Prism.dump_file API by using the serialization API. + def dump_file(filepath, **options) + dump_file(File.read(filepath), filepath: filepath, **options) + end + + # Mirror the Prism.lex API by using the serialization API. + def lex(source, **options) + lexed = WASM::PRISM.lex(source.to_java_bytes, dump_options(options).to_java_bytes) + Serialize.load_lex(source, lexed, options.fetch(:freeze, false)) + end + + # Mirror the Prism.lex_file API by using the serialization API. + def lex_file(filepath, **options) + lex_file(File.read(filepath), filepath: filepath, **options) + end + + # Mirror the Prism.parse API by using the serialization API. + def parse(source, **options) + serialized = dump(source, **options) + Serialize.load_parse(source, serialized, options.fetch(:freeze, false)) + end + + # Mirror the Prism.parse_file API by using the serialization API. This uses + # native strings instead of Ruby strings because it allows us to use mmap + # when it is available. + def parse_file(filepath, **options) + parse(File.read(filepath), filepath: filepath, **options) + end + + # Mirror the Prism.parse_stream API by using the serialization API. + def parse_stream(stream, **options) + LibRubyParser::PrismBuffer.with do |buffer| + source = +"" + callback = -> (string, size, _) { + raise "Expected size to be >= 0, got: #{size}" if size <= 0 + + if !(line = stream.gets(size - 1)).nil? + source << line + string.write_string("#{line}\x00", line.bytesize + 1) + end + } + + eof_callback = -> (_) { stream.eof? } + + # In the pm_serialize_parse_stream function it accepts a pointer to the + # IO object as a void* and then passes it through to the callback as the + # third argument, but it never touches it itself. As such, since we have + # access to the IO object already through the closure of the lambda, we + # can pass a null pointer here and not worry. + LibRubyParser.pm_serialize_parse_stream(buffer.pointer, nil, callback, eof_callback, dump_options(options)) + Prism.load(source, buffer.read, options.fetch(:freeze, false)) + end + end + + # Mirror the Prism.parse_comments API by using the serialization API. + def parse_comments(code, **options) + LibRubyParser::PrismString.with_string(code) { |string| parse_comments_common(string, code, options) } + end + + # Mirror the Prism.parse_file_comments API by using the serialization + # API. This uses native strings instead of Ruby strings because it allows us + # to use mmap when it is available. + def parse_file_comments(filepath, **options) + options[:filepath] = filepath + LibRubyParser::PrismString.with_file(filepath) { |string| parse_comments_common(string, string.read, options) } + end + + # Mirror the Prism.parse_lex API by using the serialization API. + def parse_lex(code, **options) + LibRubyParser::PrismString.with_string(code) { |string| parse_lex_common(string, code, options) } + end + + # Mirror the Prism.parse_lex_file API by using the serialization API. + def parse_lex_file(filepath, **options) + options[:filepath] = filepath + LibRubyParser::PrismString.with_file(filepath) { |string| parse_lex_common(string, string.read, options) } + end + + # Mirror the Prism.parse_success? API by using the serialization API. + def parse_success?(code, **options) + LibRubyParser::PrismString.with_string(code) { |string| parse_file_success_common(string, options) } + end + + # Mirror the Prism.parse_failure? API by using the serialization API. + def parse_failure?(code, **options) + !parse_success?(code, **options) + end + + # Mirror the Prism.parse_file_success? API by using the serialization API. + def parse_file_success?(filepath, **options) + options[:filepath] = filepath + LibRubyParser::PrismString.with_file(filepath) { |string| parse_file_success_common(string, options) } + end + + # Mirror the Prism.parse_file_failure? API by using the serialization API. + 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 lex_common(string, code, options) # :nodoc: + LibRubyParser::PrismBuffer.with do |buffer| + LibRubyParser.pm_serialize_lex(buffer.pointer, string.pointer, string.length, dump_options(options)) + Serialize.load_lex(code, buffer.read, options.fetch(:freeze, false)) + end + end + + def parse_common(string, code, options) # :nodoc: + serialized = dump_common(string, options) + Serialize.load_parse(code, serialized, options.fetch(:freeze, false)) + end + + def parse_comments_common(string, code, options) # :nodoc: + LibRubyParser::PrismBuffer.with do |buffer| + LibRubyParser.pm_serialize_parse_comments(buffer.pointer, string.pointer, string.length, dump_options(options)) + Serialize.load_parse_comments(code, buffer.read, options.fetch(:freeze, false)) + end + end + + def parse_lex_common(string, code, options) # :nodoc: + LibRubyParser::PrismBuffer.with do |buffer| + LibRubyParser.pm_serialize_parse_lex(buffer.pointer, string.pointer, string.length, dump_options(options)) + Serialize.load_parse_lex(code, buffer.read, options.fetch(:freeze, false)) + end + end + + def parse_file_success_common(string, options) # :nodoc: + LibRubyParser.pm_parse_success_p(string.pointer, string.length, dump_options(options)) + end + + # Return the value that should be dumped for the command_line option. + def dump_options_command_line(options) + command_line = options.fetch(:command_line, "") + raise ArgumentError, "command_line must be a string" unless command_line.is_a?(String) + + command_line.each_char.inject(0) do |value, char| + case char + when "a" then value | 0b000001 + when "e" then value | 0b000010 + when "l" then value | 0b000100 + when "n" then value | 0b001000 + when "p" then value | 0b010000 + when "x" then value | 0b100000 + else raise ArgumentError, "invalid command_line option: #{char}" + end + end + end + + # Return the value that should be dumped for the version option. + def dump_options_version(version) + case version + when "current" + version_string_to_number(RUBY_VERSION) || raise(CurrentVersionError, RUBY_VERSION) + when "latest", nil + 0 # Handled in pm_parser_init + when "nearest" + dump = version_string_to_number(RUBY_VERSION) + return dump if dump + if RUBY_VERSION < "3.3" + version_string_to_number("3.3") + else + 0 # Handled in pm_parser_init + end + else + version_string_to_number(version) || raise(ArgumentError, "invalid version: #{version}") + end + end + + # Converts a version string like "4.0.0" or "4.0" into a number. + # Returns nil if the version is unknown. + def version_string_to_number(version) + case version + when /\A3\.3(\.\d+)?\z/ + 1 + when /\A3\.4(\.\d+)?\z/ + 2 + when /\A3\.5(\.\d+)?\z/, /\A4\.0(\.\d+)?\z/ + 3 + when /\A4\.1(\.\d+)?\z/ + 4 + end + end + + # Convert the given options into a serialized options string. + def dump_options(options) + template = +"" + values = [] + + template << "L" + if (filepath = options[:filepath]) + values.push(filepath.bytesize, filepath.b) + template << "A*" + else + values << 0 + end + + template << "l" + values << options.fetch(:line, 1) + + template << "L" + if (encoding = options[:encoding]) + name = encoding.is_a?(Encoding) ? encoding.name : encoding + values.push(name.bytesize, name.b) + template << "A*" + else + values << 0 + end + + template << "C" + values << (options.fetch(:frozen_string_literal, false) ? 1 : 0) + + template << "C" + values << dump_options_command_line(options) + + template << "C" + 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 << "C" + values << (options.fetch(:freeze, false) ? 1 : 0) + + template << "L" + if (scopes = options[:scopes]) + values << scopes.length + + scopes.each do |scope| + locals = nil + forwarding = 0 + + case scope + when Array + locals = scope + when Scope + locals = scope.locals + + scope.forwarding.each do |forward| + case forward + when :* then forwarding |= 0x1 + when :** then forwarding |= 0x2 + when :& then forwarding |= 0x4 + when :"..." then forwarding |= 0x8 + else raise ArgumentError, "invalid forwarding value: #{forward}" + end + end + else + raise TypeError, "wrong argument type #{scope.class.inspect} (expected Array or Prism::Scope)" + end + + template << "L" + values << locals.length + + template << "C" + values << forwarding + + locals.each do |local| + name = local.name + template << "L" + values << name.bytesize + + template << "A*" + values << name.b + end + end + else + values << 0 + end + + 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 # :nodoc: + 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/prism.gemspec b/prism.gemspec index 20c66a562e..d8b86c6fba 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -42,28 +42,30 @@ Gem::Specification.new do |spec| "docs/serialization.md", "docs/testing.md", "ext/prism/api_node.c", - "ext/prism/api_pack.c", + "ext/prism/extconf.rb", "ext/prism/extension.c", "ext/prism/extension.h", "include/prism.h", "include/prism/ast.h", + "include/prism/debug_allocator.h", "include/prism/defines.h", "include/prism/diagnostic.h", "include/prism/encoding.h", "include/prism/node.h", + "include/prism/node_new.h", "include/prism/options.h", - "include/prism/pack.h", "include/prism/parser.h", "include/prism/prettyprint.h", "include/prism/regexp.h", "include/prism/static_literals.h", + "include/prism/util/pm_arena.h", "include/prism/util/pm_buffer.h", "include/prism/util/pm_char.h", "include/prism/util/pm_constant_pool.h", "include/prism/util/pm_integer.h", "include/prism/util/pm_list.h", "include/prism/util/pm_memchr.h", - "include/prism/util/pm_newline_list.h", + "include/prism/util/pm_line_offset_list.h", "include/prism/util/pm_strncasecmp.h", "include/prism/util/pm_string.h", "include/prism/util/pm_strpbrk.h", @@ -80,7 +82,6 @@ Gem::Specification.new do |spec| "lib/prism/mutation_compiler.rb", "lib/prism/node_ext.rb", "lib/prism/node.rb", - "lib/prism/pack.rb", "lib/prism/parse_result.rb", "lib/prism/parse_result/comments.rb", "lib/prism/parse_result/errors.rb", @@ -110,56 +111,71 @@ Gem::Specification.new do |spec| "lib/prism/translation/ruby_parser.rb", "lib/prism/visitor.rb", "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/generated/prism.rbi", + "rbi/generated/prism/compiler.rbi", + "rbi/generated/prism/desugar_compiler.rbi", + "rbi/generated/prism/dispatcher.rbi", + "rbi/generated/prism/dot_visitor.rbi", + "rbi/generated/prism/dsl.rbi", + "rbi/generated/prism/inspect_visitor.rbi", + "rbi/generated/prism/lex_compat.rbi", + "rbi/generated/prism/mutation_compiler.rbi", + "rbi/generated/prism/node.rbi", + "rbi/generated/prism/node_ext.rbi", + "rbi/generated/prism/parse_result.rbi", + "rbi/generated/prism/pattern.rbi", + "rbi/generated/prism/reflection.rbi", + "rbi/generated/prism/relocation.rbi", + "rbi/generated/prism/serialize.rbi", + "rbi/generated/prism/string_query.rbi", + "rbi/generated/prism/translation.rbi", + "rbi/generated/prism/visitor.rbi", + "rbi/generated/prism/parse_result/comments.rbi", + "rbi/generated/prism/parse_result/errors.rbi", + "rbi/generated/prism/parse_result/newlines.rbi", "rbi/prism/translation/parser.rbi", "rbi/prism/translation/parser_versions.rbi", "rbi/prism/translation/ripper.rbi", - "rbi/prism/visitor.rbi", - "sig/prism.rbs", - "sig/prism/compiler.rbs", - "sig/prism/dispatcher.rbs", - "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", - "sig/prism/pack.rbs", - "sig/prism/parse_result.rbs", - "sig/prism/parse_result/comments.rbs", - "sig/prism/pattern.rbs", - "sig/prism/reflection.rbs", - "sig/prism/relocation.rbs", - "sig/prism/serialize.rbs", - "sig/prism/string_query.rbs", - "sig/prism/visitor.rbs", + "sig/generated/prism.rbs", + "sig/generated/prism/compiler.rbs", + "sig/generated/prism/desugar_compiler.rbs", + "sig/generated/prism/dispatcher.rbs", + "sig/generated/prism/dot_visitor.rbs", + "sig/generated/prism/dsl.rbs", + "sig/generated/prism/inspect_visitor.rbs", + "sig/generated/prism/lex_compat.rbs", + "sig/generated/prism/mutation_compiler.rbs", + "sig/generated/prism/node.rbs", + "sig/generated/prism/node_ext.rbs", + "sig/generated/prism/parse_result.rbs", + "sig/generated/prism/pattern.rbs", + "sig/generated/prism/reflection.rbs", + "sig/generated/prism/relocation.rbs", + "sig/generated/prism/serialize.rbs", + "sig/generated/prism/string_query.rbs", + "sig/generated/prism/translation.rbs", + "sig/generated/prism/visitor.rbs", + "sig/generated/prism/parse_result/comments.rbs", + "sig/generated/prism/parse_result/errors.rbs", + "sig/generated/prism/parse_result/newlines.rbs", "src/diagnostic.c", "src/encoding.c", "src/node.c", "src/options.c", - "src/pack.c", "src/prettyprint.c", "src/prism.c", "src/regexp.c", "src/serialize.c", "src/static_literals.c", "src/token_type.c", + "src/util/pm_arena.c", "src/util/pm_buffer.c", "src/util/pm_char.c", "src/util/pm_constant_pool.c", "src/util/pm_integer.c", "src/util/pm_list.c", "src/util/pm_memchr.c", - "src/util/pm_newline_list.c", + "src/util/pm_line_offset_list.c", "src/util/pm_string.c", "src/util/pm_strncasecmp.c", "src/util/pm_strpbrk.c" diff --git a/rakelib/rdoc.rake b/rakelib/rdoc.rake index 340a5cd831..deb98b0730 100644 --- a/rakelib/rdoc.rake +++ b/rakelib/rdoc.rake @@ -7,33 +7,8 @@ rescue LoadError return end -if RDoc::VERSION <= "6.5.0" - # RDoc 6.5.0 and earlier did not create an rdoc:coverage task. This patches it - # in in the same way newer versions do. - RDoc::Task.prepend( - Module.new { - def define - super.tap do - namespace rdoc_task_name do - desc "Print RDoc coverage report" - task :coverage do - @before_running_rdoc.call if @before_running_rdoc - opts = option_list << "-C" - args = opts + @rdoc_files - - $stderr.puts "rdoc #{args.join(" ")}" if Rake.application.options.trace - RDoc::RDoc.new.document(args) - end - end - end - end - } - ) -end - RDoc::Task.new(:rdoc) do |rdoc| rdoc.main = "README.md" - rdoc.markup = "markdown" rdoc.rdoc_dir = "doc/rb" rdoc.options.push("--all", "-x", "lib/prism/translation/ripper/shim.rb") diff --git a/rakelib/serialization.rake b/rakelib/serialization.rake index a57a7ba700..499be443ce 100644 --- a/rakelib/serialization.rake +++ b/rakelib/serialization.rake @@ -26,7 +26,7 @@ task "test:java_loader:internal" => :compile do puts path serialized = Prism.dump_file(path) source_bytes = File.binread(path).unpack('c*') - parse_result = org.prism.Loader.load(serialized.unpack('c*'), source_bytes) + parse_result = org.ruby_lang.prism.Loader.load(serialized.unpack('c*'), source_bytes) puts parse_result.value end end diff --git a/rakelib/typecheck.rake b/rakelib/typecheck.rake index 5da23ac34f..69bd4a0078 100644 --- a/rakelib/typecheck.rake +++ b/rakelib/typecheck.rake @@ -1,35 +1,372 @@ # frozen_string_literal: true namespace :typecheck do + class RBICompiler + INODE = Set.new(%i[accept child_nodes comment_targets compact_child_nodes deconstruct each_child_node inspect type]) + + attr_reader :parent + + def initialize(parent, abstract: Set.new, override: Set.new) + @parent = parent + @abstract = abstract + @override = override + @visibility = RBI::Public.new + end + + def compile_comments(node) + comments = [] + + if (comment = node.comment) + index = 0 + lines = comment.string.lines(chomp: true) + + while index < lines.length + case (line = lines[index]) + when ":call-seq:" + # skip RDoc call-seq annotations + index += 1 until index >= lines.length || lines[index + 1].empty? + index += 1 + when "--" + # break when RDoc private starts + break + when /\A:/ + # skip RBS type annotations + else + comments << RBI::Comment.new(line) + end + + index += 1 + end + end + + comments + end + + def compile(node) + case node + when RBS::AST::Members::AttrReader + parent << + RBI::AttrReader.new( + node.name.name, + visibility: @visibility, + sigs: [RBI::Sig.new(return_type: compile_type(node.type).to_rbi)], + comments: compile_comments(node) + ) + when RBS::AST::Members::Include + parent << RBI::Include.new(compile_name(node.name)) + when RBS::AST::Members::Private + @visibility = RBI::Private.new + when RBS::AST::Declarations::Constant + parent << + RBI::Const.new( + compile_name(node.name), + "T.let(nil, #{compile_type(node.type).to_rbi})", + comments: compile_comments(node) + ) + when RBS::AST::Declarations::Class + parent << RBI::Class.new(compile_name(node.name), comments: compile_comments(node)) do |cls| + abstract = Set.new + override = Set.new + + if parent && parent.name.name == "Prism" && cls.name.name == "Node" + cls << RBI::Helper.new("abstract") + abstract = INODE + end + + if (super_class = node.super_class).is_a?(RBS::AST::Declarations::Class::Super) + cls.superclass_name = compile_name(super_class.name) + override = INODE if parent && parent.name.name == "Prism" && super_class.name.name.name == "Node" + end + + compiler = RBICompiler.new(cls, abstract: abstract, override: override) + node.members.each { |member| compiler.compile(member) } + end + when RBS::AST::Declarations::Module + parent << RBI::Module.new(compile_name(node.name), comments: compile_comments(node)) do |mod| + compiler = RBICompiler.new(mod) + node.members.each { |member| compiler.compile(member) } + end + when RBS::AST::Members::MethodDefinition + parent << + RBI::Method.new( + node.name.name, + visibility: @visibility, + is_singleton: node.kind == :singleton, + comments: compile_comments(node) + ) do |method| + params = Set.new + node.overloads.each_with_index do |overload, index| + method_type = overload.method_type + func = method_type.type + + sig = + RBI::Sig.new( + return_type: compile_type(func.return_type).to_rbi, + is_abstract: @abstract.include?(node.name), + is_override: @override.include?(node.name) + ) + + compile_function(func) do |kind, name, type| + if !params.include?(name) + case kind + when :param then method.add_param(name) + when :opt_param then method.add_opt_param(name, "T.unsafe(nil)") + when :rest_param then method.add_rest_param(name) + when :kw_opt_param then method.add_kw_opt_param(name, "T.unsafe(nil)") + when :kw_rest_param then method.add_kw_rest_param(name) + else raise + end + params.add(name) + end + + sig.params << RBI::SigParam.new(name, type) + end + + if (block = method_type.block) + if !params.include?("blk") + method.add_block_param("blk") + params.add("blk") + end + + proc = RBI::Type.proc + compile_function(block.type) { |kind, name, type| proc.proc_params[name] = type } + proc.returns(compile_type(block.type.return_type)) + + sig.params << RBI::SigParam.new("blk", proc) + end + + method.sigs << sig + end + end + when RBS::AST::Members::Alias + case [node.new_name, node.old_name] + when [:dispatch, :visit] + parent << + RBI::Method.new("dispatch", visibility: @visibility, comments: compile_comments(node)) do |method| + method.add_param("node") + method.sigs << + RBI::Sig.new( + params: [RBI::SigParam.new("node", RBI::Type.nilable(RBI::Type.simple("Node")))], + return_type: RBI::Type.untyped + ) + end + when [:script_lines, :source_lines], + [:find, :breadth_first_search], + [:find_all, :breadth_first_search_all], + [:deconstruct, :child_nodes] + found = parent.nodes.find { |child| child.is_a?(RBI::Method) && child.name == node.old_name.name } + parent << + found.dup.tap do |method| + method.name = node.new_name.name + method.comments = compile_comments(node) + end + else + raise + end + when RBS::AST::Members::InstanceVariable, RBS::AST::Declarations::Interface, RBS::AST::Declarations::TypeAlias + # skip + else + raise + end + end + + private + + def compile_name(name) + RBI::Type.simple(name.to_namespace.path.join("::")) + end + + def compile_function(func) + argidx = -1 + kwargidx = -1 + + func.required_positionals.each do |param| + yield :param, param.name&.name || "arg#{argidx += 1}", compile_type(param.type) + end + + func.optional_positionals.each do |param| + yield :opt_param, param.name&.name || "arg#{argidx += 1}", compile_type(param.type) + end + + if (rest_positionals = func.rest_positionals) + yield :rest_param, rest_positionals.name&.name || "args", compile_type(rest_positionals.type) + end + + func.trailing_positionals.each do |param| + raise + end + + func.required_keywords.each do |param| + raise + end + + func.optional_keywords.each do |name, param| + yield :kw_opt_param, name, compile_type(param.type) + end + + if (rest_keywords = func.rest_keywords) + yield :kw_rest_param, rest_keywords.name&.name || "kwargs", compile_type(rest_keywords.type) + end + end + + def compile_type(type) + case type + when RBS::Types::Literal + case type.literal + when FalseClass + RBI::Type.simple("FalseClass") + when Symbol + RBI::Type.simple("Symbol") + else + raise + end + when RBS::Types::Bases::Any + RBI::Type.untyped + when RBS::Types::Bases::Bool + RBI::Type.boolean + when RBS::Types::Bases::Bottom + RBI::Type.noreturn + when RBS::Types::Bases::Self + RBI::Type.self_type + when RBS::Types::Bases::Void + RBI::Type.void + when RBS::Types::Union + RBI::Type.any(*type.types.map { |child| compile_type(child) }) + when RBS::Types::Tuple + RBI::Type.tuple(*type.types.map { |child| compile_type(child) }) + when RBS::Types::ClassSingleton + RBI::Type.class_of(compile_name(type.name)) + when RBS::Types::Optional + RBI::Type.nilable(compile_type(type.type)) + when RBS::Types::ClassInstance + if (args = type.args).any? + case (name = type.name.name) + when :Array, :Hash + RBI::Type.generic("T::#{name.name}", *args.map { |arg| compile_type(arg) }) + when :Enumerator + RBI::Type.generic("T::Enumerator", compile_type(args.first)) + else + raise + end + else + compile_name(type.name) + end + when RBS::Types::Alias + case type.name.name + when :node + RBI::Type.simple("Node") + when :lex_compat_token + RBI::Type.tuple( + RBI::Type.tuple(RBI::Type.simple("Integer"), RBI::Type.simple("Integer")), + RBI::Type.simple("Symbol"), + RBI::Type.simple("String"), + RBI::Type.untyped + ) + when :entry_values + RBI::Type.generic("T::Hash", RBI::Type.simple("Symbol"), RBI::Type.untyped) + when :entry_value + RBI::Type.untyped + when :boolish + RBI::Type.nilable(RBI::Type.boolean) + else + raise + end + when RBS::Types::Interface + case type.name.name + when :_CodeUnitsCache, :_CommentTarget, :_Field, :_Repository, :_Stream, :_Value + RBI::Type.untyped + when :_Visitor + RBI::Type.simple("Visitor") + else + raise + end + else + raise + end + end + end + + def with_gemfile + Bundler.with_original_env do + ENV['BUNDLE_GEMFILE'] = "gemfiles/typecheck/Gemfile" + yield + end + end + + desc "Generate RBS with rbs-inline" + task rbs_inline: :templates do + with_gemfile do + sh "bundle", "exec", "rbs-inline", "lib", "--output", "lib" + end + end + + desc "Generate RBIs from RBSs" + task rbi: :templates do + with_gemfile do + require "fileutils" + require "rbs" + require "rbi" + require "set" + + rbs_base = File.expand_path("../sig/generated", __dir__) + rbi_base = File.expand_path("../rbi/generated", __dir__) + + Dir["**/*.rbs", base: rbs_base].each do |filepath| + RBI::File.new(strictness: "true") do |file| + compiler = RBICompiler.new(file) + + _, _, decls = RBS::Parser.parse_signature(File.read(File.join(rbs_base, filepath))) + decls.each { |decl| compiler.compile(decl) } + + mkdir_p((dirpath = File.join(rbi_base, File.dirname(filepath)))) + File.write(File.join(dirpath, "#{File.basename(filepath, ".rbs")}.rbi"), file.string) + end + end + end + end + + desc "Typecheck with Steep" + task steep: :templates do + with_gemfile do + sh "bundle", "exec", "steep", "check" + end + end + + desc "Generate RBIs with Tapioca" task tapioca: :templates do Rake::Task["compile:prism"].invoke - require "tapioca/internal" - Tapioca::Cli.start(["configure"]) - Tapioca::Cli.start(["gems", "--exclude", "prism"]) - Tapioca::Cli.start(["todo"]) + with_gemfile do + sh "bundle", "exec", "tapioca", "configure" + sh "bundle", "exec", "tapioca", "gems", "--exclude", "prism" + sh "bundle", "exec", "tapioca", "todo" + end end desc "Typecheck with Sorbet" task sorbet: :templates do + require "fileutils" + locals = { polyfills: Dir["lib/prism/polyfill/**/*.rb"], gem_rbis: Dir["sorbet/rbi/**/*.rbi"] } + FileUtils.mkdir_p("sorbet") File.write("sorbet/typed_overrides.yml", ERB.new(<<~YAML, trim_mode: "-").result_with_hash(locals)) false: - ./lib/prism/lex_compat.rb + - ./lib/prism/node.rb - ./lib/prism/node_ext.rb - ./lib/prism/parse_result.rb + - ./lib/prism/pattern.rb - ./lib/prism/visitor.rb - ./lib/prism/translation/parser/lexer.rb - ./lib/prism/translation/ripper.rb - - ./lib/prism/translation/ripper/filter.rb - - ./lib/prism/translation/ripper/lexer.rb - ./lib/prism/translation/ripper/sexp.rb - ./lib/prism/translation/ruby_parser.rb - ./lib/prism/inspect_visitor.rb + - ./lib/prism/serialize.rb - ./sample/prism/multiplex_constants.rb # We want to treat all polyfill files as "typed: false" <% polyfills.each do |file| -%> @@ -63,11 +400,8 @@ namespace :typecheck do --suppress-error-code=7001 CONFIG - exec "#{::Gem::Specification.find_by_name("sorbet-static").full_gem_path}/libexec/sorbet" - end - - desc "Typecheck with Steep" - task steep: :templates do - exec Gem.bin_path("steep", "steep"), "check" + with_gemfile do + sh "bundle", "exec", "srb" + end end end diff --git a/rbi/generated/prism.rbi b/rbi/generated/prism.rbi new file mode 100644 index 0000000000..037c50382c --- /dev/null +++ b/rbi/generated/prism.rbi @@ -0,0 +1,79 @@ +# typed: true + +# The Prism Ruby parser. +# +# "Parsing Ruby is suddenly manageable!" +# - You, hopefully +module Prism + # Raised when requested to parse as the currently running Ruby version but Prism has no support for it. + class CurrentVersionError < ArgumentError + # Initialize a new exception for the given ruby version string. + sig { params(version: String).void } + def initialize(version); end + end + + # Returns a parse result whose value is an array of tokens that closely + # resembles the return value of Ripper.lex. + # + # For supported options, see Prism.parse. + sig { params(source: String, options: ::T.untyped).returns(LexCompat::Result) } + def self.lex_compat(source, **options); end + + # Load the serialized AST using the source as a reference into a tree. + sig { params(source: String, serialized: String, freeze: T::Boolean).returns(ParseResult) } + def self.load(source, serialized, freeze = T.unsafe(nil)); end + + VERSION = T.let(nil, String) + BACKEND = T.let(nil, Symbol) + + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseResult) } + def self.parse(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).void } + def self.profile(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(LexResult) } + def self.lex(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseLexResult) } + def self.parse_lex(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(String) } + def self.dump(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Array[Comment]) } + def self.parse_comments(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } + def self.parse_success?(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } + def self.parse_failure?(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(stream: ::T.untyped, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseResult) } + def self.parse_stream(stream, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseResult) } + def self.parse_file(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).void } + def self.profile_file(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(LexResult) } + def self.lex_file(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseLexResult) } + def self.parse_lex_file(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(String) } + def self.dump_file(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Array[Comment]) } + def self.parse_file_comments(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } + def self.parse_file_success?(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } + def self.parse_file_failure?(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end +end diff --git a/rbi/generated/prism/compiler.rbi b/rbi/generated/prism/compiler.rbi new file mode 100644 index 0000000000..af86919953 --- /dev/null +++ b/rbi/generated/prism/compiler.rbi @@ -0,0 +1,489 @@ +# typed: true + +module Prism + # A compiler is a visitor that returns the value of each node as it visits. + # This is as opposed to a visitor which will only walk the tree. This can be + # useful when you are trying to compile a tree into a different format. + # + # For example, to build a representation of the tree as s-expressions, you + # could write: + # + # class SExpressions < Prism::Compiler + # def visit_arguments_node(node) = [:arguments, super] + # def visit_call_node(node) = [:call, super] + # def visit_integer_node(node) = [:integer] + # def visit_program_node(node) = [:program, super] + # end + # + # Prism.parse("1 + 2").value.accept(SExpressions.new) + # # => [:program, [[[:call, [[:integer], [:arguments, [[:integer]]]]]]]] + class Compiler < Visitor + # Visit an individual node. + sig { params(arg0: ::T.nilable(Node)).returns(::T.untyped) } + def visit(arg0); end + + # Visit a list of nodes. + sig { params(arg0: T::Array[::T.nilable(Node)]).returns(::T.untyped) } + def visit_all(arg0); end + + # Visit the child nodes of the given node. + sig { params(arg0: Node).returns(T::Array[::T.untyped]) } + def visit_child_nodes(arg0); end + + sig { params(arg0: AliasGlobalVariableNode).returns(T::Array[::T.untyped]) } + def visit_alias_global_variable_node(arg0); end + + sig { params(arg0: AliasMethodNode).returns(T::Array[::T.untyped]) } + def visit_alias_method_node(arg0); end + + sig { params(arg0: AlternationPatternNode).returns(T::Array[::T.untyped]) } + def visit_alternation_pattern_node(arg0); end + + sig { params(arg0: AndNode).returns(T::Array[::T.untyped]) } + def visit_and_node(arg0); end + + sig { params(arg0: ArgumentsNode).returns(T::Array[::T.untyped]) } + def visit_arguments_node(arg0); end + + sig { params(arg0: ArrayNode).returns(T::Array[::T.untyped]) } + def visit_array_node(arg0); end + + sig { params(arg0: ArrayPatternNode).returns(T::Array[::T.untyped]) } + def visit_array_pattern_node(arg0); end + + sig { params(arg0: AssocNode).returns(T::Array[::T.untyped]) } + def visit_assoc_node(arg0); end + + sig { params(arg0: AssocSplatNode).returns(T::Array[::T.untyped]) } + def visit_assoc_splat_node(arg0); end + + sig { params(arg0: BackReferenceReadNode).returns(T::Array[::T.untyped]) } + def visit_back_reference_read_node(arg0); end + + sig { params(arg0: BeginNode).returns(T::Array[::T.untyped]) } + def visit_begin_node(arg0); end + + sig { params(arg0: BlockArgumentNode).returns(T::Array[::T.untyped]) } + def visit_block_argument_node(arg0); end + + sig { params(arg0: BlockLocalVariableNode).returns(T::Array[::T.untyped]) } + def visit_block_local_variable_node(arg0); end + + sig { params(arg0: BlockNode).returns(T::Array[::T.untyped]) } + def visit_block_node(arg0); end + + sig { params(arg0: BlockParameterNode).returns(T::Array[::T.untyped]) } + def visit_block_parameter_node(arg0); end + + sig { params(arg0: BlockParametersNode).returns(T::Array[::T.untyped]) } + def visit_block_parameters_node(arg0); end + + sig { params(arg0: BreakNode).returns(T::Array[::T.untyped]) } + def visit_break_node(arg0); end + + sig { params(arg0: CallAndWriteNode).returns(T::Array[::T.untyped]) } + def visit_call_and_write_node(arg0); end + + sig { params(arg0: CallNode).returns(T::Array[::T.untyped]) } + def visit_call_node(arg0); end + + sig { params(arg0: CallOperatorWriteNode).returns(T::Array[::T.untyped]) } + def visit_call_operator_write_node(arg0); end + + sig { params(arg0: CallOrWriteNode).returns(T::Array[::T.untyped]) } + def visit_call_or_write_node(arg0); end + + sig { params(arg0: CallTargetNode).returns(T::Array[::T.untyped]) } + def visit_call_target_node(arg0); end + + sig { params(arg0: CapturePatternNode).returns(T::Array[::T.untyped]) } + def visit_capture_pattern_node(arg0); end + + sig { params(arg0: CaseMatchNode).returns(T::Array[::T.untyped]) } + def visit_case_match_node(arg0); end + + sig { params(arg0: CaseNode).returns(T::Array[::T.untyped]) } + def visit_case_node(arg0); end + + sig { params(arg0: ClassNode).returns(T::Array[::T.untyped]) } + def visit_class_node(arg0); end + + sig { params(arg0: ClassVariableAndWriteNode).returns(T::Array[::T.untyped]) } + def visit_class_variable_and_write_node(arg0); end + + sig { params(arg0: ClassVariableOperatorWriteNode).returns(T::Array[::T.untyped]) } + def visit_class_variable_operator_write_node(arg0); end + + sig { params(arg0: ClassVariableOrWriteNode).returns(T::Array[::T.untyped]) } + def visit_class_variable_or_write_node(arg0); end + + sig { params(arg0: ClassVariableReadNode).returns(T::Array[::T.untyped]) } + def visit_class_variable_read_node(arg0); end + + sig { params(arg0: ClassVariableTargetNode).returns(T::Array[::T.untyped]) } + def visit_class_variable_target_node(arg0); end + + sig { params(arg0: ClassVariableWriteNode).returns(T::Array[::T.untyped]) } + def visit_class_variable_write_node(arg0); end + + sig { params(arg0: ConstantAndWriteNode).returns(T::Array[::T.untyped]) } + def visit_constant_and_write_node(arg0); end + + sig { params(arg0: ConstantOperatorWriteNode).returns(T::Array[::T.untyped]) } + def visit_constant_operator_write_node(arg0); end + + sig { params(arg0: ConstantOrWriteNode).returns(T::Array[::T.untyped]) } + def visit_constant_or_write_node(arg0); end + + sig { params(arg0: ConstantPathAndWriteNode).returns(T::Array[::T.untyped]) } + def visit_constant_path_and_write_node(arg0); end + + sig { params(arg0: ConstantPathNode).returns(T::Array[::T.untyped]) } + def visit_constant_path_node(arg0); end + + sig { params(arg0: ConstantPathOperatorWriteNode).returns(T::Array[::T.untyped]) } + def visit_constant_path_operator_write_node(arg0); end + + sig { params(arg0: ConstantPathOrWriteNode).returns(T::Array[::T.untyped]) } + def visit_constant_path_or_write_node(arg0); end + + sig { params(arg0: ConstantPathTargetNode).returns(T::Array[::T.untyped]) } + def visit_constant_path_target_node(arg0); end + + sig { params(arg0: ConstantPathWriteNode).returns(T::Array[::T.untyped]) } + def visit_constant_path_write_node(arg0); end + + sig { params(arg0: ConstantReadNode).returns(T::Array[::T.untyped]) } + def visit_constant_read_node(arg0); end + + sig { params(arg0: ConstantTargetNode).returns(T::Array[::T.untyped]) } + def visit_constant_target_node(arg0); end + + sig { params(arg0: ConstantWriteNode).returns(T::Array[::T.untyped]) } + def visit_constant_write_node(arg0); end + + sig { params(arg0: DefNode).returns(T::Array[::T.untyped]) } + def visit_def_node(arg0); end + + sig { params(arg0: DefinedNode).returns(T::Array[::T.untyped]) } + def visit_defined_node(arg0); end + + sig { params(arg0: ElseNode).returns(T::Array[::T.untyped]) } + def visit_else_node(arg0); end + + sig { params(arg0: EmbeddedStatementsNode).returns(T::Array[::T.untyped]) } + def visit_embedded_statements_node(arg0); end + + sig { params(arg0: EmbeddedVariableNode).returns(T::Array[::T.untyped]) } + def visit_embedded_variable_node(arg0); end + + sig { params(arg0: EnsureNode).returns(T::Array[::T.untyped]) } + def visit_ensure_node(arg0); end + + sig { params(arg0: FalseNode).returns(T::Array[::T.untyped]) } + def visit_false_node(arg0); end + + sig { params(arg0: FindPatternNode).returns(T::Array[::T.untyped]) } + def visit_find_pattern_node(arg0); end + + sig { params(arg0: FlipFlopNode).returns(T::Array[::T.untyped]) } + def visit_flip_flop_node(arg0); end + + sig { params(arg0: FloatNode).returns(T::Array[::T.untyped]) } + def visit_float_node(arg0); end + + sig { params(arg0: ForNode).returns(T::Array[::T.untyped]) } + def visit_for_node(arg0); end + + sig { params(arg0: ForwardingArgumentsNode).returns(T::Array[::T.untyped]) } + def visit_forwarding_arguments_node(arg0); end + + sig { params(arg0: ForwardingParameterNode).returns(T::Array[::T.untyped]) } + def visit_forwarding_parameter_node(arg0); end + + sig { params(arg0: ForwardingSuperNode).returns(T::Array[::T.untyped]) } + def visit_forwarding_super_node(arg0); end + + sig { params(arg0: GlobalVariableAndWriteNode).returns(T::Array[::T.untyped]) } + def visit_global_variable_and_write_node(arg0); end + + sig { params(arg0: GlobalVariableOperatorWriteNode).returns(T::Array[::T.untyped]) } + def visit_global_variable_operator_write_node(arg0); end + + sig { params(arg0: GlobalVariableOrWriteNode).returns(T::Array[::T.untyped]) } + def visit_global_variable_or_write_node(arg0); end + + sig { params(arg0: GlobalVariableReadNode).returns(T::Array[::T.untyped]) } + def visit_global_variable_read_node(arg0); end + + sig { params(arg0: GlobalVariableTargetNode).returns(T::Array[::T.untyped]) } + def visit_global_variable_target_node(arg0); end + + sig { params(arg0: GlobalVariableWriteNode).returns(T::Array[::T.untyped]) } + def visit_global_variable_write_node(arg0); end + + sig { params(arg0: HashNode).returns(T::Array[::T.untyped]) } + def visit_hash_node(arg0); end + + sig { params(arg0: HashPatternNode).returns(T::Array[::T.untyped]) } + def visit_hash_pattern_node(arg0); end + + sig { params(arg0: IfNode).returns(T::Array[::T.untyped]) } + def visit_if_node(arg0); end + + sig { params(arg0: ImaginaryNode).returns(T::Array[::T.untyped]) } + def visit_imaginary_node(arg0); end + + sig { params(arg0: ImplicitNode).returns(T::Array[::T.untyped]) } + def visit_implicit_node(arg0); end + + sig { params(arg0: ImplicitRestNode).returns(T::Array[::T.untyped]) } + def visit_implicit_rest_node(arg0); end + + sig { params(arg0: InNode).returns(T::Array[::T.untyped]) } + def visit_in_node(arg0); end + + sig { params(arg0: IndexAndWriteNode).returns(T::Array[::T.untyped]) } + def visit_index_and_write_node(arg0); end + + sig { params(arg0: IndexOperatorWriteNode).returns(T::Array[::T.untyped]) } + def visit_index_operator_write_node(arg0); end + + sig { params(arg0: IndexOrWriteNode).returns(T::Array[::T.untyped]) } + def visit_index_or_write_node(arg0); end + + sig { params(arg0: IndexTargetNode).returns(T::Array[::T.untyped]) } + def visit_index_target_node(arg0); end + + sig { params(arg0: InstanceVariableAndWriteNode).returns(T::Array[::T.untyped]) } + def visit_instance_variable_and_write_node(arg0); end + + sig { params(arg0: InstanceVariableOperatorWriteNode).returns(T::Array[::T.untyped]) } + def visit_instance_variable_operator_write_node(arg0); end + + sig { params(arg0: InstanceVariableOrWriteNode).returns(T::Array[::T.untyped]) } + def visit_instance_variable_or_write_node(arg0); end + + sig { params(arg0: InstanceVariableReadNode).returns(T::Array[::T.untyped]) } + def visit_instance_variable_read_node(arg0); end + + sig { params(arg0: InstanceVariableTargetNode).returns(T::Array[::T.untyped]) } + def visit_instance_variable_target_node(arg0); end + + sig { params(arg0: InstanceVariableWriteNode).returns(T::Array[::T.untyped]) } + def visit_instance_variable_write_node(arg0); end + + sig { params(arg0: IntegerNode).returns(T::Array[::T.untyped]) } + def visit_integer_node(arg0); end + + sig { params(arg0: InterpolatedMatchLastLineNode).returns(T::Array[::T.untyped]) } + def visit_interpolated_match_last_line_node(arg0); end + + sig { params(arg0: InterpolatedRegularExpressionNode).returns(T::Array[::T.untyped]) } + def visit_interpolated_regular_expression_node(arg0); end + + sig { params(arg0: InterpolatedStringNode).returns(T::Array[::T.untyped]) } + def visit_interpolated_string_node(arg0); end + + sig { params(arg0: InterpolatedSymbolNode).returns(T::Array[::T.untyped]) } + def visit_interpolated_symbol_node(arg0); end + + sig { params(arg0: InterpolatedXStringNode).returns(T::Array[::T.untyped]) } + def visit_interpolated_x_string_node(arg0); end + + sig { params(arg0: ItLocalVariableReadNode).returns(T::Array[::T.untyped]) } + def visit_it_local_variable_read_node(arg0); end + + sig { params(arg0: ItParametersNode).returns(T::Array[::T.untyped]) } + def visit_it_parameters_node(arg0); end + + sig { params(arg0: KeywordHashNode).returns(T::Array[::T.untyped]) } + def visit_keyword_hash_node(arg0); end + + sig { params(arg0: KeywordRestParameterNode).returns(T::Array[::T.untyped]) } + def visit_keyword_rest_parameter_node(arg0); end + + sig { params(arg0: LambdaNode).returns(T::Array[::T.untyped]) } + def visit_lambda_node(arg0); end + + sig { params(arg0: LocalVariableAndWriteNode).returns(T::Array[::T.untyped]) } + def visit_local_variable_and_write_node(arg0); end + + sig { params(arg0: LocalVariableOperatorWriteNode).returns(T::Array[::T.untyped]) } + def visit_local_variable_operator_write_node(arg0); end + + sig { params(arg0: LocalVariableOrWriteNode).returns(T::Array[::T.untyped]) } + def visit_local_variable_or_write_node(arg0); end + + sig { params(arg0: LocalVariableReadNode).returns(T::Array[::T.untyped]) } + def visit_local_variable_read_node(arg0); end + + sig { params(arg0: LocalVariableTargetNode).returns(T::Array[::T.untyped]) } + def visit_local_variable_target_node(arg0); end + + sig { params(arg0: LocalVariableWriteNode).returns(T::Array[::T.untyped]) } + def visit_local_variable_write_node(arg0); end + + sig { params(arg0: MatchLastLineNode).returns(T::Array[::T.untyped]) } + def visit_match_last_line_node(arg0); end + + sig { params(arg0: MatchPredicateNode).returns(T::Array[::T.untyped]) } + def visit_match_predicate_node(arg0); end + + sig { params(arg0: MatchRequiredNode).returns(T::Array[::T.untyped]) } + def visit_match_required_node(arg0); end + + sig { params(arg0: MatchWriteNode).returns(T::Array[::T.untyped]) } + def visit_match_write_node(arg0); end + + sig { params(arg0: MissingNode).returns(T::Array[::T.untyped]) } + def visit_missing_node(arg0); end + + sig { params(arg0: ModuleNode).returns(T::Array[::T.untyped]) } + def visit_module_node(arg0); end + + sig { params(arg0: MultiTargetNode).returns(T::Array[::T.untyped]) } + def visit_multi_target_node(arg0); end + + sig { params(arg0: MultiWriteNode).returns(T::Array[::T.untyped]) } + def visit_multi_write_node(arg0); end + + sig { params(arg0: NextNode).returns(T::Array[::T.untyped]) } + def visit_next_node(arg0); end + + sig { params(arg0: NilNode).returns(T::Array[::T.untyped]) } + def visit_nil_node(arg0); end + + sig { params(arg0: NoBlockParameterNode).returns(T::Array[::T.untyped]) } + def visit_no_block_parameter_node(arg0); end + + sig { params(arg0: NoKeywordsParameterNode).returns(T::Array[::T.untyped]) } + def visit_no_keywords_parameter_node(arg0); end + + sig { params(arg0: NumberedParametersNode).returns(T::Array[::T.untyped]) } + def visit_numbered_parameters_node(arg0); end + + sig { params(arg0: NumberedReferenceReadNode).returns(T::Array[::T.untyped]) } + def visit_numbered_reference_read_node(arg0); end + + sig { params(arg0: OptionalKeywordParameterNode).returns(T::Array[::T.untyped]) } + def visit_optional_keyword_parameter_node(arg0); end + + sig { params(arg0: OptionalParameterNode).returns(T::Array[::T.untyped]) } + def visit_optional_parameter_node(arg0); end + + sig { params(arg0: OrNode).returns(T::Array[::T.untyped]) } + def visit_or_node(arg0); end + + sig { params(arg0: ParametersNode).returns(T::Array[::T.untyped]) } + def visit_parameters_node(arg0); end + + sig { params(arg0: ParenthesesNode).returns(T::Array[::T.untyped]) } + def visit_parentheses_node(arg0); end + + sig { params(arg0: PinnedExpressionNode).returns(T::Array[::T.untyped]) } + def visit_pinned_expression_node(arg0); end + + sig { params(arg0: PinnedVariableNode).returns(T::Array[::T.untyped]) } + def visit_pinned_variable_node(arg0); end + + sig { params(arg0: PostExecutionNode).returns(T::Array[::T.untyped]) } + def visit_post_execution_node(arg0); end + + sig { params(arg0: PreExecutionNode).returns(T::Array[::T.untyped]) } + def visit_pre_execution_node(arg0); end + + sig { params(arg0: ProgramNode).returns(T::Array[::T.untyped]) } + def visit_program_node(arg0); end + + sig { params(arg0: RangeNode).returns(T::Array[::T.untyped]) } + def visit_range_node(arg0); end + + sig { params(arg0: RationalNode).returns(T::Array[::T.untyped]) } + def visit_rational_node(arg0); end + + sig { params(arg0: RedoNode).returns(T::Array[::T.untyped]) } + def visit_redo_node(arg0); end + + sig { params(arg0: RegularExpressionNode).returns(T::Array[::T.untyped]) } + def visit_regular_expression_node(arg0); end + + sig { params(arg0: RequiredKeywordParameterNode).returns(T::Array[::T.untyped]) } + def visit_required_keyword_parameter_node(arg0); end + + sig { params(arg0: RequiredParameterNode).returns(T::Array[::T.untyped]) } + def visit_required_parameter_node(arg0); end + + sig { params(arg0: RescueModifierNode).returns(T::Array[::T.untyped]) } + def visit_rescue_modifier_node(arg0); end + + sig { params(arg0: RescueNode).returns(T::Array[::T.untyped]) } + def visit_rescue_node(arg0); end + + sig { params(arg0: RestParameterNode).returns(T::Array[::T.untyped]) } + def visit_rest_parameter_node(arg0); end + + sig { params(arg0: RetryNode).returns(T::Array[::T.untyped]) } + def visit_retry_node(arg0); end + + sig { params(arg0: ReturnNode).returns(T::Array[::T.untyped]) } + def visit_return_node(arg0); end + + sig { params(arg0: SelfNode).returns(T::Array[::T.untyped]) } + def visit_self_node(arg0); end + + sig { params(arg0: ShareableConstantNode).returns(T::Array[::T.untyped]) } + def visit_shareable_constant_node(arg0); end + + sig { params(arg0: SingletonClassNode).returns(T::Array[::T.untyped]) } + def visit_singleton_class_node(arg0); end + + sig { params(arg0: SourceEncodingNode).returns(T::Array[::T.untyped]) } + def visit_source_encoding_node(arg0); end + + sig { params(arg0: SourceFileNode).returns(T::Array[::T.untyped]) } + def visit_source_file_node(arg0); end + + sig { params(arg0: SourceLineNode).returns(T::Array[::T.untyped]) } + def visit_source_line_node(arg0); end + + sig { params(arg0: SplatNode).returns(T::Array[::T.untyped]) } + def visit_splat_node(arg0); end + + sig { params(arg0: StatementsNode).returns(T::Array[::T.untyped]) } + def visit_statements_node(arg0); end + + sig { params(arg0: StringNode).returns(T::Array[::T.untyped]) } + def visit_string_node(arg0); end + + sig { params(arg0: SuperNode).returns(T::Array[::T.untyped]) } + def visit_super_node(arg0); end + + sig { params(arg0: SymbolNode).returns(T::Array[::T.untyped]) } + def visit_symbol_node(arg0); end + + sig { params(arg0: TrueNode).returns(T::Array[::T.untyped]) } + def visit_true_node(arg0); end + + sig { params(arg0: UndefNode).returns(T::Array[::T.untyped]) } + def visit_undef_node(arg0); end + + sig { params(arg0: UnlessNode).returns(T::Array[::T.untyped]) } + def visit_unless_node(arg0); end + + sig { params(arg0: UntilNode).returns(T::Array[::T.untyped]) } + def visit_until_node(arg0); end + + sig { params(arg0: WhenNode).returns(T::Array[::T.untyped]) } + def visit_when_node(arg0); end + + sig { params(arg0: WhileNode).returns(T::Array[::T.untyped]) } + def visit_while_node(arg0); end + + sig { params(arg0: XStringNode).returns(T::Array[::T.untyped]) } + def visit_x_string_node(arg0); end + + sig { params(arg0: YieldNode).returns(T::Array[::T.untyped]) } + def visit_yield_node(arg0); end + end +end diff --git a/rbi/generated/prism/desugar_compiler.rbi b/rbi/generated/prism/desugar_compiler.rbi new file mode 100644 index 0000000000..167624b9b6 --- /dev/null +++ b/rbi/generated/prism/desugar_compiler.rbi @@ -0,0 +1,306 @@ +# typed: true + +module Prism + class DesugarAndWriteNode + include DSL + + sig { returns(::T.any(ClassVariableAndWriteNode, ConstantAndWriteNode, GlobalVariableAndWriteNode, InstanceVariableAndWriteNode, LocalVariableAndWriteNode)) } + attr_reader :node + + sig { returns(Source) } + attr_reader :default_source + + sig { returns(Symbol) } + attr_reader :read_class + + sig { returns(Symbol) } + attr_reader :write_class + + sig { returns(T::Hash[Symbol, ::T.untyped]) } + attr_reader :arguments + + sig { params(node: ::T.any(ClassVariableAndWriteNode, ConstantAndWriteNode, GlobalVariableAndWriteNode, InstanceVariableAndWriteNode, LocalVariableAndWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: ::T.untyped).void } + def initialize(node, default_source, read_class, write_class, **arguments); end + + # Desugar `x &&= y` to `x && x = y` + sig { returns(Node) } + def compile; end + end + + class DesugarOrWriteDefinedNode + include DSL + + sig { returns(::T.any(ClassVariableOrWriteNode, ConstantOrWriteNode, GlobalVariableOrWriteNode)) } + attr_reader :node + + sig { returns(Source) } + attr_reader :default_source + + sig { returns(Symbol) } + attr_reader :read_class + + sig { returns(Symbol) } + attr_reader :write_class + + sig { returns(T::Hash[Symbol, ::T.untyped]) } + attr_reader :arguments + + sig { params(node: ::T.any(ClassVariableOrWriteNode, ConstantOrWriteNode, GlobalVariableOrWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: ::T.untyped).void } + def initialize(node, default_source, read_class, write_class, **arguments); end + + # Desugar `x ||= y` to `defined?(x) ? x : x = y` + sig { returns(Node) } + def compile; end + end + + class DesugarOperatorWriteNode + include DSL + + sig { returns(::T.any(ClassVariableOperatorWriteNode, ConstantOperatorWriteNode, GlobalVariableOperatorWriteNode, InstanceVariableOperatorWriteNode, LocalVariableOperatorWriteNode)) } + attr_reader :node + + sig { returns(Source) } + attr_reader :default_source + + sig { returns(Symbol) } + attr_reader :read_class + + sig { returns(Symbol) } + attr_reader :write_class + + sig { returns(T::Hash[Symbol, ::T.untyped]) } + attr_reader :arguments + + sig { params(node: ::T.any(ClassVariableOperatorWriteNode, ConstantOperatorWriteNode, GlobalVariableOperatorWriteNode, InstanceVariableOperatorWriteNode, LocalVariableOperatorWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: ::T.untyped).void } + def initialize(node, default_source, read_class, write_class, **arguments); end + + # Desugar `x += y` to `x = x + y` + sig { returns(Node) } + def compile; end + end + + class DesugarOrWriteNode + include DSL + + sig { returns(::T.any(InstanceVariableOrWriteNode, LocalVariableOrWriteNode)) } + attr_reader :node + + sig { returns(Source) } + attr_reader :default_source + + sig { returns(Symbol) } + attr_reader :read_class + + sig { returns(Symbol) } + attr_reader :write_class + + sig { returns(T::Hash[Symbol, ::T.untyped]) } + attr_reader :arguments + + sig { params(node: ::T.any(InstanceVariableOrWriteNode, LocalVariableOrWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: ::T.untyped).void } + def initialize(node, default_source, read_class, write_class, **arguments); end + + # Desugar `x ||= y` to `x || x = y` + sig { returns(Node) } + def compile; end + end + + class ClassVariableAndWriteNode + sig { returns(Node) } + def desugar; end + end + + class ClassVariableOrWriteNode + sig { returns(Node) } + def desugar; end + end + + class ClassVariableOperatorWriteNode + sig { returns(Node) } + def desugar; end + end + + class ConstantAndWriteNode + sig { returns(Node) } + def desugar; end + end + + class ConstantOrWriteNode + sig { returns(Node) } + def desugar; end + end + + class ConstantOperatorWriteNode + sig { returns(Node) } + def desugar; end + end + + class GlobalVariableAndWriteNode + sig { returns(Node) } + def desugar; end + end + + class GlobalVariableOrWriteNode + sig { returns(Node) } + def desugar; end + end + + class GlobalVariableOperatorWriteNode + sig { returns(Node) } + def desugar; end + end + + class InstanceVariableAndWriteNode + sig { returns(Node) } + def desugar; end + end + + class InstanceVariableOrWriteNode + sig { returns(Node) } + def desugar; end + end + + class InstanceVariableOperatorWriteNode + sig { returns(Node) } + def desugar; end + end + + class LocalVariableAndWriteNode + sig { returns(Node) } + def desugar; end + end + + class LocalVariableOrWriteNode + sig { returns(Node) } + def desugar; end + end + + class LocalVariableOperatorWriteNode + sig { returns(Node) } + def desugar; end + end + + # DesugarCompiler is a compiler that desugars Ruby code into a more primitive + # form. This is useful for consumers that want to deal with fewer node types. + class DesugarCompiler < MutationCompiler + # `@@foo &&= bar` + # + # becomes + # + # `@@foo && @@foo = bar` + sig { params(node: ClassVariableAndWriteNode).returns(Node) } + def visit_class_variable_and_write_node(node); end + + # `@@foo ||= bar` + # + # becomes + # + # `defined?(@@foo) ? @@foo : @@foo = bar` + sig { params(node: ClassVariableOrWriteNode).returns(Node) } + def visit_class_variable_or_write_node(node); end + + # `@@foo += bar` + # + # becomes + # + # `@@foo = @@foo + bar` + sig { params(node: ClassVariableOperatorWriteNode).returns(Node) } + def visit_class_variable_operator_write_node(node); end + + # `Foo &&= bar` + # + # becomes + # + # `Foo && Foo = bar` + sig { params(node: ConstantAndWriteNode).returns(Node) } + def visit_constant_and_write_node(node); end + + # `Foo ||= bar` + # + # becomes + # + # `defined?(Foo) ? Foo : Foo = bar` + sig { params(node: ConstantOrWriteNode).returns(Node) } + def visit_constant_or_write_node(node); end + + # `Foo += bar` + # + # becomes + # + # `Foo = Foo + bar` + sig { params(node: ConstantOperatorWriteNode).returns(Node) } + def visit_constant_operator_write_node(node); end + + # `$foo &&= bar` + # + # becomes + # + # `$foo && $foo = bar` + sig { params(node: GlobalVariableAndWriteNode).returns(Node) } + def visit_global_variable_and_write_node(node); end + + # `$foo ||= bar` + # + # becomes + # + # `defined?($foo) ? $foo : $foo = bar` + sig { params(node: GlobalVariableOrWriteNode).returns(Node) } + def visit_global_variable_or_write_node(node); end + + # `$foo += bar` + # + # becomes + # + # `$foo = $foo + bar` + sig { params(node: GlobalVariableOperatorWriteNode).returns(Node) } + def visit_global_variable_operator_write_node(node); end + + # `@foo &&= bar` + # + # becomes + # + # `@foo && @foo = bar` + sig { params(node: InstanceVariableAndWriteNode).returns(Node) } + def visit_instance_variable_and_write_node(node); end + + # `@foo ||= bar` + # + # becomes + # + # `@foo || @foo = bar` + sig { params(node: InstanceVariableOrWriteNode).returns(Node) } + def visit_instance_variable_or_write_node(node); end + + # `@foo += bar` + # + # becomes + # + # `@foo = @foo + bar` + sig { params(node: InstanceVariableOperatorWriteNode).returns(Node) } + def visit_instance_variable_operator_write_node(node); end + + # `foo &&= bar` + # + # becomes + # + # `foo && foo = bar` + sig { params(node: LocalVariableAndWriteNode).returns(Node) } + def visit_local_variable_and_write_node(node); end + + # `foo ||= bar` + # + # becomes + # + # `foo || foo = bar` + sig { params(node: LocalVariableOrWriteNode).returns(Node) } + def visit_local_variable_or_write_node(node); end + + # `foo += bar` + # + # becomes + # + # `foo = foo + bar` + sig { params(node: LocalVariableOperatorWriteNode).returns(Node) } + def visit_local_variable_operator_write_node(node); end + end +end diff --git a/rbi/generated/prism/dispatcher.rbi b/rbi/generated/prism/dispatcher.rbi new file mode 100644 index 0000000000..2dfeedf26f --- /dev/null +++ b/rbi/generated/prism/dispatcher.rbi @@ -0,0 +1,1138 @@ +# typed: true + +module Prism + # The dispatcher class fires events for nodes that are found while walking an + # AST to all registered listeners. It's useful for performing different types + # of analysis on the AST while only having to walk the tree once. + # + # To use the dispatcher, you would first instantiate it and register listeners + # for the events you're interested in: + # + # class OctalListener + # def on_integer_node_enter(node) + # if node.octal? && !node.slice.start_with?("0o") + # warn("Octal integers should be written with the 0o prefix") + # end + # end + # end + # + # 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: + # + # result = Prism.parse("001 + 002 + 003") + # dispatcher.dispatch(result.value) + # + # Optionally, you can also use `#dispatch_once` to dispatch enter and leave + # events for a single node without recursing further down the tree. This can + # be useful in circumstances where you want to reuse the listeners you already + # have registers but want to stop walking the tree at a certain point. + # + # integer = result.value.statements.body.first.receiver.receiver + # dispatcher.dispatch_once(integer) + class Dispatcher < Visitor + # A hash mapping event names to arrays of listeners that should be notified + # when that event is fired. + sig { returns(T::Hash[Symbol, T::Array[::T.untyped]]) } + attr_reader :listeners + + # Initialize a new dispatcher. + sig { void } + def initialize; end + + # Register a listener for one or more events. + sig { params(arg0: ::T.untyped, args: Symbol).void } + def register(arg0, *args); end + + # Register all public methods of a listener that match the pattern + # `on__(enter|leave)`. + sig { params(arg0: ::T.untyped).void } + def register_public_methods(arg0); end + + # Register a listener for the given events. + sig { params(arg0: ::T.untyped, arg1: T::Array[Symbol]).void } + def register_events(arg0, arg1); end + + # Walks `root` dispatching events to all registered listeners. + sig { params(node: ::T.nilable(Node)).returns(::T.untyped) } + def dispatch(node); end + + # Dispatches a single event for `node` to all registered listeners. + sig { params(node: Node).void } + def dispatch_once(node); end + + sig { params(node: AliasGlobalVariableNode).void } + def visit_alias_global_variable_node(node); end + + sig { params(node: AliasMethodNode).void } + def visit_alias_method_node(node); end + + sig { params(node: AlternationPatternNode).void } + def visit_alternation_pattern_node(node); end + + sig { params(node: AndNode).void } + def visit_and_node(node); end + + sig { params(node: ArgumentsNode).void } + def visit_arguments_node(node); end + + sig { params(node: ArrayNode).void } + def visit_array_node(node); end + + sig { params(node: ArrayPatternNode).void } + def visit_array_pattern_node(node); end + + sig { params(node: AssocNode).void } + def visit_assoc_node(node); end + + sig { params(node: AssocSplatNode).void } + def visit_assoc_splat_node(node); end + + sig { params(node: BackReferenceReadNode).void } + def visit_back_reference_read_node(node); end + + sig { params(node: BeginNode).void } + def visit_begin_node(node); end + + sig { params(node: BlockArgumentNode).void } + def visit_block_argument_node(node); end + + sig { params(node: BlockLocalVariableNode).void } + def visit_block_local_variable_node(node); end + + sig { params(node: BlockNode).void } + def visit_block_node(node); end + + sig { params(node: BlockParameterNode).void } + def visit_block_parameter_node(node); end + + sig { params(node: BlockParametersNode).void } + def visit_block_parameters_node(node); end + + sig { params(node: BreakNode).void } + def visit_break_node(node); end + + sig { params(node: CallAndWriteNode).void } + def visit_call_and_write_node(node); end + + sig { params(node: CallNode).void } + def visit_call_node(node); end + + sig { params(node: CallOperatorWriteNode).void } + def visit_call_operator_write_node(node); end + + sig { params(node: CallOrWriteNode).void } + def visit_call_or_write_node(node); end + + sig { params(node: CallTargetNode).void } + def visit_call_target_node(node); end + + sig { params(node: CapturePatternNode).void } + def visit_capture_pattern_node(node); end + + sig { params(node: CaseMatchNode).void } + def visit_case_match_node(node); end + + sig { params(node: CaseNode).void } + def visit_case_node(node); end + + sig { params(node: ClassNode).void } + def visit_class_node(node); end + + sig { params(node: ClassVariableAndWriteNode).void } + def visit_class_variable_and_write_node(node); end + + sig { params(node: ClassVariableOperatorWriteNode).void } + def visit_class_variable_operator_write_node(node); end + + sig { params(node: ClassVariableOrWriteNode).void } + def visit_class_variable_or_write_node(node); end + + sig { params(node: ClassVariableReadNode).void } + def visit_class_variable_read_node(node); end + + sig { params(node: ClassVariableTargetNode).void } + def visit_class_variable_target_node(node); end + + sig { params(node: ClassVariableWriteNode).void } + def visit_class_variable_write_node(node); end + + sig { params(node: ConstantAndWriteNode).void } + def visit_constant_and_write_node(node); end + + sig { params(node: ConstantOperatorWriteNode).void } + def visit_constant_operator_write_node(node); end + + sig { params(node: ConstantOrWriteNode).void } + def visit_constant_or_write_node(node); end + + sig { params(node: ConstantPathAndWriteNode).void } + def visit_constant_path_and_write_node(node); end + + sig { params(node: ConstantPathNode).void } + def visit_constant_path_node(node); end + + sig { params(node: ConstantPathOperatorWriteNode).void } + def visit_constant_path_operator_write_node(node); end + + sig { params(node: ConstantPathOrWriteNode).void } + def visit_constant_path_or_write_node(node); end + + sig { params(node: ConstantPathTargetNode).void } + def visit_constant_path_target_node(node); end + + sig { params(node: ConstantPathWriteNode).void } + def visit_constant_path_write_node(node); end + + sig { params(node: ConstantReadNode).void } + def visit_constant_read_node(node); end + + sig { params(node: ConstantTargetNode).void } + def visit_constant_target_node(node); end + + sig { params(node: ConstantWriteNode).void } + def visit_constant_write_node(node); end + + sig { params(node: DefNode).void } + def visit_def_node(node); end + + sig { params(node: DefinedNode).void } + def visit_defined_node(node); end + + sig { params(node: ElseNode).void } + def visit_else_node(node); end + + sig { params(node: EmbeddedStatementsNode).void } + def visit_embedded_statements_node(node); end + + sig { params(node: EmbeddedVariableNode).void } + def visit_embedded_variable_node(node); end + + sig { params(node: EnsureNode).void } + def visit_ensure_node(node); end + + sig { params(node: FalseNode).void } + def visit_false_node(node); end + + sig { params(node: FindPatternNode).void } + def visit_find_pattern_node(node); end + + sig { params(node: FlipFlopNode).void } + def visit_flip_flop_node(node); end + + sig { params(node: FloatNode).void } + def visit_float_node(node); end + + sig { params(node: ForNode).void } + def visit_for_node(node); end + + sig { params(node: ForwardingArgumentsNode).void } + def visit_forwarding_arguments_node(node); end + + sig { params(node: ForwardingParameterNode).void } + def visit_forwarding_parameter_node(node); end + + sig { params(node: ForwardingSuperNode).void } + def visit_forwarding_super_node(node); end + + sig { params(node: GlobalVariableAndWriteNode).void } + def visit_global_variable_and_write_node(node); end + + sig { params(node: GlobalVariableOperatorWriteNode).void } + def visit_global_variable_operator_write_node(node); end + + sig { params(node: GlobalVariableOrWriteNode).void } + def visit_global_variable_or_write_node(node); end + + sig { params(node: GlobalVariableReadNode).void } + def visit_global_variable_read_node(node); end + + sig { params(node: GlobalVariableTargetNode).void } + def visit_global_variable_target_node(node); end + + sig { params(node: GlobalVariableWriteNode).void } + def visit_global_variable_write_node(node); end + + sig { params(node: HashNode).void } + def visit_hash_node(node); end + + sig { params(node: HashPatternNode).void } + def visit_hash_pattern_node(node); end + + sig { params(node: IfNode).void } + def visit_if_node(node); end + + sig { params(node: ImaginaryNode).void } + def visit_imaginary_node(node); end + + sig { params(node: ImplicitNode).void } + def visit_implicit_node(node); end + + sig { params(node: ImplicitRestNode).void } + def visit_implicit_rest_node(node); end + + sig { params(node: InNode).void } + def visit_in_node(node); end + + sig { params(node: IndexAndWriteNode).void } + def visit_index_and_write_node(node); end + + sig { params(node: IndexOperatorWriteNode).void } + def visit_index_operator_write_node(node); end + + sig { params(node: IndexOrWriteNode).void } + def visit_index_or_write_node(node); end + + sig { params(node: IndexTargetNode).void } + def visit_index_target_node(node); end + + sig { params(node: InstanceVariableAndWriteNode).void } + def visit_instance_variable_and_write_node(node); end + + sig { params(node: InstanceVariableOperatorWriteNode).void } + def visit_instance_variable_operator_write_node(node); end + + sig { params(node: InstanceVariableOrWriteNode).void } + def visit_instance_variable_or_write_node(node); end + + sig { params(node: InstanceVariableReadNode).void } + def visit_instance_variable_read_node(node); end + + sig { params(node: InstanceVariableTargetNode).void } + def visit_instance_variable_target_node(node); end + + sig { params(node: InstanceVariableWriteNode).void } + def visit_instance_variable_write_node(node); end + + sig { params(node: IntegerNode).void } + def visit_integer_node(node); end + + sig { params(node: InterpolatedMatchLastLineNode).void } + def visit_interpolated_match_last_line_node(node); end + + sig { params(node: InterpolatedRegularExpressionNode).void } + def visit_interpolated_regular_expression_node(node); end + + sig { params(node: InterpolatedStringNode).void } + def visit_interpolated_string_node(node); end + + sig { params(node: InterpolatedSymbolNode).void } + def visit_interpolated_symbol_node(node); end + + sig { params(node: InterpolatedXStringNode).void } + def visit_interpolated_x_string_node(node); end + + sig { params(node: ItLocalVariableReadNode).void } + def visit_it_local_variable_read_node(node); end + + sig { params(node: ItParametersNode).void } + def visit_it_parameters_node(node); end + + sig { params(node: KeywordHashNode).void } + def visit_keyword_hash_node(node); end + + sig { params(node: KeywordRestParameterNode).void } + def visit_keyword_rest_parameter_node(node); end + + sig { params(node: LambdaNode).void } + def visit_lambda_node(node); end + + sig { params(node: LocalVariableAndWriteNode).void } + def visit_local_variable_and_write_node(node); end + + sig { params(node: LocalVariableOperatorWriteNode).void } + def visit_local_variable_operator_write_node(node); end + + sig { params(node: LocalVariableOrWriteNode).void } + def visit_local_variable_or_write_node(node); end + + sig { params(node: LocalVariableReadNode).void } + def visit_local_variable_read_node(node); end + + sig { params(node: LocalVariableTargetNode).void } + def visit_local_variable_target_node(node); end + + sig { params(node: LocalVariableWriteNode).void } + def visit_local_variable_write_node(node); end + + sig { params(node: MatchLastLineNode).void } + def visit_match_last_line_node(node); end + + sig { params(node: MatchPredicateNode).void } + def visit_match_predicate_node(node); end + + sig { params(node: MatchRequiredNode).void } + def visit_match_required_node(node); end + + sig { params(node: MatchWriteNode).void } + def visit_match_write_node(node); end + + sig { params(node: MissingNode).void } + def visit_missing_node(node); end + + sig { params(node: ModuleNode).void } + def visit_module_node(node); end + + sig { params(node: MultiTargetNode).void } + def visit_multi_target_node(node); end + + sig { params(node: MultiWriteNode).void } + def visit_multi_write_node(node); end + + sig { params(node: NextNode).void } + def visit_next_node(node); end + + sig { params(node: NilNode).void } + def visit_nil_node(node); end + + sig { params(node: NoBlockParameterNode).void } + def visit_no_block_parameter_node(node); end + + sig { params(node: NoKeywordsParameterNode).void } + def visit_no_keywords_parameter_node(node); end + + sig { params(node: NumberedParametersNode).void } + def visit_numbered_parameters_node(node); end + + sig { params(node: NumberedReferenceReadNode).void } + def visit_numbered_reference_read_node(node); end + + sig { params(node: OptionalKeywordParameterNode).void } + def visit_optional_keyword_parameter_node(node); end + + sig { params(node: OptionalParameterNode).void } + def visit_optional_parameter_node(node); end + + sig { params(node: OrNode).void } + def visit_or_node(node); end + + sig { params(node: ParametersNode).void } + def visit_parameters_node(node); end + + sig { params(node: ParenthesesNode).void } + def visit_parentheses_node(node); end + + sig { params(node: PinnedExpressionNode).void } + def visit_pinned_expression_node(node); end + + sig { params(node: PinnedVariableNode).void } + def visit_pinned_variable_node(node); end + + sig { params(node: PostExecutionNode).void } + def visit_post_execution_node(node); end + + sig { params(node: PreExecutionNode).void } + def visit_pre_execution_node(node); end + + sig { params(node: ProgramNode).void } + def visit_program_node(node); end + + sig { params(node: RangeNode).void } + def visit_range_node(node); end + + sig { params(node: RationalNode).void } + def visit_rational_node(node); end + + sig { params(node: RedoNode).void } + def visit_redo_node(node); end + + sig { params(node: RegularExpressionNode).void } + def visit_regular_expression_node(node); end + + sig { params(node: RequiredKeywordParameterNode).void } + def visit_required_keyword_parameter_node(node); end + + sig { params(node: RequiredParameterNode).void } + def visit_required_parameter_node(node); end + + sig { params(node: RescueModifierNode).void } + def visit_rescue_modifier_node(node); end + + sig { params(node: RescueNode).void } + def visit_rescue_node(node); end + + sig { params(node: RestParameterNode).void } + def visit_rest_parameter_node(node); end + + sig { params(node: RetryNode).void } + def visit_retry_node(node); end + + sig { params(node: ReturnNode).void } + def visit_return_node(node); end + + sig { params(node: SelfNode).void } + def visit_self_node(node); end + + sig { params(node: ShareableConstantNode).void } + def visit_shareable_constant_node(node); end + + sig { params(node: SingletonClassNode).void } + def visit_singleton_class_node(node); end + + sig { params(node: SourceEncodingNode).void } + def visit_source_encoding_node(node); end + + sig { params(node: SourceFileNode).void } + def visit_source_file_node(node); end + + sig { params(node: SourceLineNode).void } + def visit_source_line_node(node); end + + sig { params(node: SplatNode).void } + def visit_splat_node(node); end + + sig { params(node: StatementsNode).void } + def visit_statements_node(node); end + + sig { params(node: StringNode).void } + def visit_string_node(node); end + + sig { params(node: SuperNode).void } + def visit_super_node(node); end + + sig { params(node: SymbolNode).void } + def visit_symbol_node(node); end + + sig { params(node: TrueNode).void } + def visit_true_node(node); end + + sig { params(node: UndefNode).void } + def visit_undef_node(node); end + + sig { params(node: UnlessNode).void } + def visit_unless_node(node); end + + sig { params(node: UntilNode).void } + def visit_until_node(node); end + + sig { params(node: WhenNode).void } + def visit_when_node(node); end + + sig { params(node: WhileNode).void } + def visit_while_node(node); end + + sig { params(node: XStringNode).void } + def visit_x_string_node(node); end + + sig { params(node: YieldNode).void } + def visit_yield_node(node); end + + class DispatchOnce < Visitor + sig { returns(T::Hash[Symbol, T::Array[::T.untyped]]) } + attr_reader :listeners + + sig { params(listeners: T::Hash[Symbol, T::Array[::T.untyped]]).void } + def initialize(listeners); end + + # Dispatch enter and leave events for AliasGlobalVariableNode nodes. + sig { params(node: AliasGlobalVariableNode).void } + def visit_alias_global_variable_node(node); end + + # Dispatch enter and leave events for AliasMethodNode nodes. + sig { params(node: AliasMethodNode).void } + def visit_alias_method_node(node); end + + # Dispatch enter and leave events for AlternationPatternNode nodes. + sig { params(node: AlternationPatternNode).void } + def visit_alternation_pattern_node(node); end + + # Dispatch enter and leave events for AndNode nodes. + sig { params(node: AndNode).void } + def visit_and_node(node); end + + # Dispatch enter and leave events for ArgumentsNode nodes. + sig { params(node: ArgumentsNode).void } + def visit_arguments_node(node); end + + # Dispatch enter and leave events for ArrayNode nodes. + sig { params(node: ArrayNode).void } + def visit_array_node(node); end + + # Dispatch enter and leave events for ArrayPatternNode nodes. + sig { params(node: ArrayPatternNode).void } + def visit_array_pattern_node(node); end + + # Dispatch enter and leave events for AssocNode nodes. + sig { params(node: AssocNode).void } + def visit_assoc_node(node); end + + # Dispatch enter and leave events for AssocSplatNode nodes. + sig { params(node: AssocSplatNode).void } + def visit_assoc_splat_node(node); end + + # Dispatch enter and leave events for BackReferenceReadNode nodes. + sig { params(node: BackReferenceReadNode).void } + def visit_back_reference_read_node(node); end + + # Dispatch enter and leave events for BeginNode nodes. + sig { params(node: BeginNode).void } + def visit_begin_node(node); end + + # Dispatch enter and leave events for BlockArgumentNode nodes. + sig { params(node: BlockArgumentNode).void } + def visit_block_argument_node(node); end + + # Dispatch enter and leave events for BlockLocalVariableNode nodes. + sig { params(node: BlockLocalVariableNode).void } + def visit_block_local_variable_node(node); end + + # Dispatch enter and leave events for BlockNode nodes. + sig { params(node: BlockNode).void } + def visit_block_node(node); end + + # Dispatch enter and leave events for BlockParameterNode nodes. + sig { params(node: BlockParameterNode).void } + def visit_block_parameter_node(node); end + + # Dispatch enter and leave events for BlockParametersNode nodes. + sig { params(node: BlockParametersNode).void } + def visit_block_parameters_node(node); end + + # Dispatch enter and leave events for BreakNode nodes. + sig { params(node: BreakNode).void } + def visit_break_node(node); end + + # Dispatch enter and leave events for CallAndWriteNode nodes. + sig { params(node: CallAndWriteNode).void } + def visit_call_and_write_node(node); end + + # Dispatch enter and leave events for CallNode nodes. + sig { params(node: CallNode).void } + def visit_call_node(node); end + + # Dispatch enter and leave events for CallOperatorWriteNode nodes. + sig { params(node: CallOperatorWriteNode).void } + def visit_call_operator_write_node(node); end + + # Dispatch enter and leave events for CallOrWriteNode nodes. + sig { params(node: CallOrWriteNode).void } + def visit_call_or_write_node(node); end + + # Dispatch enter and leave events for CallTargetNode nodes. + sig { params(node: CallTargetNode).void } + def visit_call_target_node(node); end + + # Dispatch enter and leave events for CapturePatternNode nodes. + sig { params(node: CapturePatternNode).void } + def visit_capture_pattern_node(node); end + + # Dispatch enter and leave events for CaseMatchNode nodes. + sig { params(node: CaseMatchNode).void } + def visit_case_match_node(node); end + + # Dispatch enter and leave events for CaseNode nodes. + sig { params(node: CaseNode).void } + def visit_case_node(node); end + + # Dispatch enter and leave events for ClassNode nodes. + sig { params(node: ClassNode).void } + def visit_class_node(node); end + + # Dispatch enter and leave events for ClassVariableAndWriteNode nodes. + sig { params(node: ClassVariableAndWriteNode).void } + def visit_class_variable_and_write_node(node); end + + # Dispatch enter and leave events for ClassVariableOperatorWriteNode nodes. + sig { params(node: ClassVariableOperatorWriteNode).void } + def visit_class_variable_operator_write_node(node); end + + # Dispatch enter and leave events for ClassVariableOrWriteNode nodes. + sig { params(node: ClassVariableOrWriteNode).void } + def visit_class_variable_or_write_node(node); end + + # Dispatch enter and leave events for ClassVariableReadNode nodes. + sig { params(node: ClassVariableReadNode).void } + def visit_class_variable_read_node(node); end + + # Dispatch enter and leave events for ClassVariableTargetNode nodes. + sig { params(node: ClassVariableTargetNode).void } + def visit_class_variable_target_node(node); end + + # Dispatch enter and leave events for ClassVariableWriteNode nodes. + sig { params(node: ClassVariableWriteNode).void } + def visit_class_variable_write_node(node); end + + # Dispatch enter and leave events for ConstantAndWriteNode nodes. + sig { params(node: ConstantAndWriteNode).void } + def visit_constant_and_write_node(node); end + + # Dispatch enter and leave events for ConstantOperatorWriteNode nodes. + sig { params(node: ConstantOperatorWriteNode).void } + def visit_constant_operator_write_node(node); end + + # Dispatch enter and leave events for ConstantOrWriteNode nodes. + sig { params(node: ConstantOrWriteNode).void } + def visit_constant_or_write_node(node); end + + # Dispatch enter and leave events for ConstantPathAndWriteNode nodes. + sig { params(node: ConstantPathAndWriteNode).void } + def visit_constant_path_and_write_node(node); end + + # Dispatch enter and leave events for ConstantPathNode nodes. + sig { params(node: ConstantPathNode).void } + def visit_constant_path_node(node); end + + # Dispatch enter and leave events for ConstantPathOperatorWriteNode nodes. + sig { params(node: ConstantPathOperatorWriteNode).void } + def visit_constant_path_operator_write_node(node); end + + # Dispatch enter and leave events for ConstantPathOrWriteNode nodes. + sig { params(node: ConstantPathOrWriteNode).void } + def visit_constant_path_or_write_node(node); end + + # Dispatch enter and leave events for ConstantPathTargetNode nodes. + sig { params(node: ConstantPathTargetNode).void } + def visit_constant_path_target_node(node); end + + # Dispatch enter and leave events for ConstantPathWriteNode nodes. + sig { params(node: ConstantPathWriteNode).void } + def visit_constant_path_write_node(node); end + + # Dispatch enter and leave events for ConstantReadNode nodes. + sig { params(node: ConstantReadNode).void } + def visit_constant_read_node(node); end + + # Dispatch enter and leave events for ConstantTargetNode nodes. + sig { params(node: ConstantTargetNode).void } + def visit_constant_target_node(node); end + + # Dispatch enter and leave events for ConstantWriteNode nodes. + sig { params(node: ConstantWriteNode).void } + def visit_constant_write_node(node); end + + # Dispatch enter and leave events for DefNode nodes. + sig { params(node: DefNode).void } + def visit_def_node(node); end + + # Dispatch enter and leave events for DefinedNode nodes. + sig { params(node: DefinedNode).void } + def visit_defined_node(node); end + + # Dispatch enter and leave events for ElseNode nodes. + sig { params(node: ElseNode).void } + def visit_else_node(node); end + + # Dispatch enter and leave events for EmbeddedStatementsNode nodes. + sig { params(node: EmbeddedStatementsNode).void } + def visit_embedded_statements_node(node); end + + # Dispatch enter and leave events for EmbeddedVariableNode nodes. + sig { params(node: EmbeddedVariableNode).void } + def visit_embedded_variable_node(node); end + + # Dispatch enter and leave events for EnsureNode nodes. + sig { params(node: EnsureNode).void } + def visit_ensure_node(node); end + + # Dispatch enter and leave events for FalseNode nodes. + sig { params(node: FalseNode).void } + def visit_false_node(node); end + + # Dispatch enter and leave events for FindPatternNode nodes. + sig { params(node: FindPatternNode).void } + def visit_find_pattern_node(node); end + + # Dispatch enter and leave events for FlipFlopNode nodes. + sig { params(node: FlipFlopNode).void } + def visit_flip_flop_node(node); end + + # Dispatch enter and leave events for FloatNode nodes. + sig { params(node: FloatNode).void } + def visit_float_node(node); end + + # Dispatch enter and leave events for ForNode nodes. + sig { params(node: ForNode).void } + def visit_for_node(node); end + + # Dispatch enter and leave events for ForwardingArgumentsNode nodes. + sig { params(node: ForwardingArgumentsNode).void } + def visit_forwarding_arguments_node(node); end + + # Dispatch enter and leave events for ForwardingParameterNode nodes. + sig { params(node: ForwardingParameterNode).void } + def visit_forwarding_parameter_node(node); end + + # Dispatch enter and leave events for ForwardingSuperNode nodes. + sig { params(node: ForwardingSuperNode).void } + def visit_forwarding_super_node(node); end + + # Dispatch enter and leave events for GlobalVariableAndWriteNode nodes. + sig { params(node: GlobalVariableAndWriteNode).void } + def visit_global_variable_and_write_node(node); end + + # Dispatch enter and leave events for GlobalVariableOperatorWriteNode nodes. + sig { params(node: GlobalVariableOperatorWriteNode).void } + def visit_global_variable_operator_write_node(node); end + + # Dispatch enter and leave events for GlobalVariableOrWriteNode nodes. + sig { params(node: GlobalVariableOrWriteNode).void } + def visit_global_variable_or_write_node(node); end + + # Dispatch enter and leave events for GlobalVariableReadNode nodes. + sig { params(node: GlobalVariableReadNode).void } + def visit_global_variable_read_node(node); end + + # Dispatch enter and leave events for GlobalVariableTargetNode nodes. + sig { params(node: GlobalVariableTargetNode).void } + def visit_global_variable_target_node(node); end + + # Dispatch enter and leave events for GlobalVariableWriteNode nodes. + sig { params(node: GlobalVariableWriteNode).void } + def visit_global_variable_write_node(node); end + + # Dispatch enter and leave events for HashNode nodes. + sig { params(node: HashNode).void } + def visit_hash_node(node); end + + # Dispatch enter and leave events for HashPatternNode nodes. + sig { params(node: HashPatternNode).void } + def visit_hash_pattern_node(node); end + + # Dispatch enter and leave events for IfNode nodes. + sig { params(node: IfNode).void } + def visit_if_node(node); end + + # Dispatch enter and leave events for ImaginaryNode nodes. + sig { params(node: ImaginaryNode).void } + def visit_imaginary_node(node); end + + # Dispatch enter and leave events for ImplicitNode nodes. + sig { params(node: ImplicitNode).void } + def visit_implicit_node(node); end + + # Dispatch enter and leave events for ImplicitRestNode nodes. + sig { params(node: ImplicitRestNode).void } + def visit_implicit_rest_node(node); end + + # Dispatch enter and leave events for InNode nodes. + sig { params(node: InNode).void } + def visit_in_node(node); end + + # Dispatch enter and leave events for IndexAndWriteNode nodes. + sig { params(node: IndexAndWriteNode).void } + def visit_index_and_write_node(node); end + + # Dispatch enter and leave events for IndexOperatorWriteNode nodes. + sig { params(node: IndexOperatorWriteNode).void } + def visit_index_operator_write_node(node); end + + # Dispatch enter and leave events for IndexOrWriteNode nodes. + sig { params(node: IndexOrWriteNode).void } + def visit_index_or_write_node(node); end + + # Dispatch enter and leave events for IndexTargetNode nodes. + sig { params(node: IndexTargetNode).void } + def visit_index_target_node(node); end + + # Dispatch enter and leave events for InstanceVariableAndWriteNode nodes. + sig { params(node: InstanceVariableAndWriteNode).void } + def visit_instance_variable_and_write_node(node); end + + # Dispatch enter and leave events for InstanceVariableOperatorWriteNode nodes. + sig { params(node: InstanceVariableOperatorWriteNode).void } + def visit_instance_variable_operator_write_node(node); end + + # Dispatch enter and leave events for InstanceVariableOrWriteNode nodes. + sig { params(node: InstanceVariableOrWriteNode).void } + def visit_instance_variable_or_write_node(node); end + + # Dispatch enter and leave events for InstanceVariableReadNode nodes. + sig { params(node: InstanceVariableReadNode).void } + def visit_instance_variable_read_node(node); end + + # Dispatch enter and leave events for InstanceVariableTargetNode nodes. + sig { params(node: InstanceVariableTargetNode).void } + def visit_instance_variable_target_node(node); end + + # Dispatch enter and leave events for InstanceVariableWriteNode nodes. + sig { params(node: InstanceVariableWriteNode).void } + def visit_instance_variable_write_node(node); end + + # Dispatch enter and leave events for IntegerNode nodes. + sig { params(node: IntegerNode).void } + def visit_integer_node(node); end + + # Dispatch enter and leave events for InterpolatedMatchLastLineNode nodes. + sig { params(node: InterpolatedMatchLastLineNode).void } + def visit_interpolated_match_last_line_node(node); end + + # Dispatch enter and leave events for InterpolatedRegularExpressionNode nodes. + sig { params(node: InterpolatedRegularExpressionNode).void } + def visit_interpolated_regular_expression_node(node); end + + # Dispatch enter and leave events for InterpolatedStringNode nodes. + sig { params(node: InterpolatedStringNode).void } + def visit_interpolated_string_node(node); end + + # Dispatch enter and leave events for InterpolatedSymbolNode nodes. + sig { params(node: InterpolatedSymbolNode).void } + def visit_interpolated_symbol_node(node); end + + # Dispatch enter and leave events for InterpolatedXStringNode nodes. + sig { params(node: InterpolatedXStringNode).void } + def visit_interpolated_x_string_node(node); end + + # Dispatch enter and leave events for ItLocalVariableReadNode nodes. + sig { params(node: ItLocalVariableReadNode).void } + def visit_it_local_variable_read_node(node); end + + # Dispatch enter and leave events for ItParametersNode nodes. + sig { params(node: ItParametersNode).void } + def visit_it_parameters_node(node); end + + # Dispatch enter and leave events for KeywordHashNode nodes. + sig { params(node: KeywordHashNode).void } + def visit_keyword_hash_node(node); end + + # Dispatch enter and leave events for KeywordRestParameterNode nodes. + sig { params(node: KeywordRestParameterNode).void } + def visit_keyword_rest_parameter_node(node); end + + # Dispatch enter and leave events for LambdaNode nodes. + sig { params(node: LambdaNode).void } + def visit_lambda_node(node); end + + # Dispatch enter and leave events for LocalVariableAndWriteNode nodes. + sig { params(node: LocalVariableAndWriteNode).void } + def visit_local_variable_and_write_node(node); end + + # Dispatch enter and leave events for LocalVariableOperatorWriteNode nodes. + sig { params(node: LocalVariableOperatorWriteNode).void } + def visit_local_variable_operator_write_node(node); end + + # Dispatch enter and leave events for LocalVariableOrWriteNode nodes. + sig { params(node: LocalVariableOrWriteNode).void } + def visit_local_variable_or_write_node(node); end + + # Dispatch enter and leave events for LocalVariableReadNode nodes. + sig { params(node: LocalVariableReadNode).void } + def visit_local_variable_read_node(node); end + + # Dispatch enter and leave events for LocalVariableTargetNode nodes. + sig { params(node: LocalVariableTargetNode).void } + def visit_local_variable_target_node(node); end + + # Dispatch enter and leave events for LocalVariableWriteNode nodes. + sig { params(node: LocalVariableWriteNode).void } + def visit_local_variable_write_node(node); end + + # Dispatch enter and leave events for MatchLastLineNode nodes. + sig { params(node: MatchLastLineNode).void } + def visit_match_last_line_node(node); end + + # Dispatch enter and leave events for MatchPredicateNode nodes. + sig { params(node: MatchPredicateNode).void } + def visit_match_predicate_node(node); end + + # Dispatch enter and leave events for MatchRequiredNode nodes. + sig { params(node: MatchRequiredNode).void } + def visit_match_required_node(node); end + + # Dispatch enter and leave events for MatchWriteNode nodes. + sig { params(node: MatchWriteNode).void } + def visit_match_write_node(node); end + + # Dispatch enter and leave events for MissingNode nodes. + sig { params(node: MissingNode).void } + def visit_missing_node(node); end + + # Dispatch enter and leave events for ModuleNode nodes. + sig { params(node: ModuleNode).void } + def visit_module_node(node); end + + # Dispatch enter and leave events for MultiTargetNode nodes. + sig { params(node: MultiTargetNode).void } + def visit_multi_target_node(node); end + + # Dispatch enter and leave events for MultiWriteNode nodes. + sig { params(node: MultiWriteNode).void } + def visit_multi_write_node(node); end + + # Dispatch enter and leave events for NextNode nodes. + sig { params(node: NextNode).void } + def visit_next_node(node); end + + # Dispatch enter and leave events for NilNode nodes. + sig { params(node: NilNode).void } + def visit_nil_node(node); end + + # Dispatch enter and leave events for NoBlockParameterNode nodes. + sig { params(node: NoBlockParameterNode).void } + def visit_no_block_parameter_node(node); end + + # Dispatch enter and leave events for NoKeywordsParameterNode nodes. + sig { params(node: NoKeywordsParameterNode).void } + def visit_no_keywords_parameter_node(node); end + + # Dispatch enter and leave events for NumberedParametersNode nodes. + sig { params(node: NumberedParametersNode).void } + def visit_numbered_parameters_node(node); end + + # Dispatch enter and leave events for NumberedReferenceReadNode nodes. + sig { params(node: NumberedReferenceReadNode).void } + def visit_numbered_reference_read_node(node); end + + # Dispatch enter and leave events for OptionalKeywordParameterNode nodes. + sig { params(node: OptionalKeywordParameterNode).void } + def visit_optional_keyword_parameter_node(node); end + + # Dispatch enter and leave events for OptionalParameterNode nodes. + sig { params(node: OptionalParameterNode).void } + def visit_optional_parameter_node(node); end + + # Dispatch enter and leave events for OrNode nodes. + sig { params(node: OrNode).void } + def visit_or_node(node); end + + # Dispatch enter and leave events for ParametersNode nodes. + sig { params(node: ParametersNode).void } + def visit_parameters_node(node); end + + # Dispatch enter and leave events for ParenthesesNode nodes. + sig { params(node: ParenthesesNode).void } + def visit_parentheses_node(node); end + + # Dispatch enter and leave events for PinnedExpressionNode nodes. + sig { params(node: PinnedExpressionNode).void } + def visit_pinned_expression_node(node); end + + # Dispatch enter and leave events for PinnedVariableNode nodes. + sig { params(node: PinnedVariableNode).void } + def visit_pinned_variable_node(node); end + + # Dispatch enter and leave events for PostExecutionNode nodes. + sig { params(node: PostExecutionNode).void } + def visit_post_execution_node(node); end + + # Dispatch enter and leave events for PreExecutionNode nodes. + sig { params(node: PreExecutionNode).void } + def visit_pre_execution_node(node); end + + # Dispatch enter and leave events for ProgramNode nodes. + sig { params(node: ProgramNode).void } + def visit_program_node(node); end + + # Dispatch enter and leave events for RangeNode nodes. + sig { params(node: RangeNode).void } + def visit_range_node(node); end + + # Dispatch enter and leave events for RationalNode nodes. + sig { params(node: RationalNode).void } + def visit_rational_node(node); end + + # Dispatch enter and leave events for RedoNode nodes. + sig { params(node: RedoNode).void } + def visit_redo_node(node); end + + # Dispatch enter and leave events for RegularExpressionNode nodes. + sig { params(node: RegularExpressionNode).void } + def visit_regular_expression_node(node); end + + # Dispatch enter and leave events for RequiredKeywordParameterNode nodes. + sig { params(node: RequiredKeywordParameterNode).void } + def visit_required_keyword_parameter_node(node); end + + # Dispatch enter and leave events for RequiredParameterNode nodes. + sig { params(node: RequiredParameterNode).void } + def visit_required_parameter_node(node); end + + # Dispatch enter and leave events for RescueModifierNode nodes. + sig { params(node: RescueModifierNode).void } + def visit_rescue_modifier_node(node); end + + # Dispatch enter and leave events for RescueNode nodes. + sig { params(node: RescueNode).void } + def visit_rescue_node(node); end + + # Dispatch enter and leave events for RestParameterNode nodes. + sig { params(node: RestParameterNode).void } + def visit_rest_parameter_node(node); end + + # Dispatch enter and leave events for RetryNode nodes. + sig { params(node: RetryNode).void } + def visit_retry_node(node); end + + # Dispatch enter and leave events for ReturnNode nodes. + sig { params(node: ReturnNode).void } + def visit_return_node(node); end + + # Dispatch enter and leave events for SelfNode nodes. + sig { params(node: SelfNode).void } + def visit_self_node(node); end + + # Dispatch enter and leave events for ShareableConstantNode nodes. + sig { params(node: ShareableConstantNode).void } + def visit_shareable_constant_node(node); end + + # Dispatch enter and leave events for SingletonClassNode nodes. + sig { params(node: SingletonClassNode).void } + def visit_singleton_class_node(node); end + + # Dispatch enter and leave events for SourceEncodingNode nodes. + sig { params(node: SourceEncodingNode).void } + def visit_source_encoding_node(node); end + + # Dispatch enter and leave events for SourceFileNode nodes. + sig { params(node: SourceFileNode).void } + def visit_source_file_node(node); end + + # Dispatch enter and leave events for SourceLineNode nodes. + sig { params(node: SourceLineNode).void } + def visit_source_line_node(node); end + + # Dispatch enter and leave events for SplatNode nodes. + sig { params(node: SplatNode).void } + def visit_splat_node(node); end + + # Dispatch enter and leave events for StatementsNode nodes. + sig { params(node: StatementsNode).void } + def visit_statements_node(node); end + + # Dispatch enter and leave events for StringNode nodes. + sig { params(node: StringNode).void } + def visit_string_node(node); end + + # Dispatch enter and leave events for SuperNode nodes. + sig { params(node: SuperNode).void } + def visit_super_node(node); end + + # Dispatch enter and leave events for SymbolNode nodes. + sig { params(node: SymbolNode).void } + def visit_symbol_node(node); end + + # Dispatch enter and leave events for TrueNode nodes. + sig { params(node: TrueNode).void } + def visit_true_node(node); end + + # Dispatch enter and leave events for UndefNode nodes. + sig { params(node: UndefNode).void } + def visit_undef_node(node); end + + # Dispatch enter and leave events for UnlessNode nodes. + sig { params(node: UnlessNode).void } + def visit_unless_node(node); end + + # Dispatch enter and leave events for UntilNode nodes. + sig { params(node: UntilNode).void } + def visit_until_node(node); end + + # Dispatch enter and leave events for WhenNode nodes. + sig { params(node: WhenNode).void } + def visit_when_node(node); end + + # Dispatch enter and leave events for WhileNode nodes. + sig { params(node: WhileNode).void } + def visit_while_node(node); end + + # Dispatch enter and leave events for XStringNode nodes. + sig { params(node: XStringNode).void } + def visit_x_string_node(node); end + + # Dispatch enter and leave events for YieldNode nodes. + sig { params(node: YieldNode).void } + def visit_yield_node(node); end + end + end +end diff --git a/rbi/generated/prism/dot_visitor.rbi b/rbi/generated/prism/dot_visitor.rbi new file mode 100644 index 0000000000..d707be5a1a --- /dev/null +++ b/rbi/generated/prism/dot_visitor.rbi @@ -0,0 +1,618 @@ +# typed: true + +module Prism + # This visitor provides the ability to call Node#to_dot, which converts a + # subtree into a graphviz dot graph. + class DotVisitor < Visitor + class Field + sig { returns(String) } + attr_reader :name + + sig { returns(::T.nilable(String)) } + attr_reader :value + + sig { returns(T::Boolean) } + attr_reader :port + + sig { params(name: String, value: ::T.nilable(String), port: T::Boolean).void } + def initialize(name, value, port); end + + sig { returns(String) } + def to_dot; end + end + + class Table + sig { returns(String) } + attr_reader :name + + sig { returns(T::Array[Field]) } + attr_reader :fields + + sig { params(name: String).void } + def initialize(name); end + + sig { params(name: String, value: ::T.nilable(String), port: T::Boolean).void } + def field(name, value = T.unsafe(nil), port: T.unsafe(nil)); end + + sig { returns(String) } + def to_dot; end + end + + class Digraph + sig { returns(T::Array[String]) } + attr_reader :nodes + + sig { returns(T::Array[String]) } + attr_reader :waypoints + + sig { returns(T::Array[String]) } + attr_reader :edges + + sig { void } + def initialize; end + + sig { params(value: String).void } + def node(value); end + + sig { params(value: String).void } + def waypoint(value); end + + sig { params(value: String).void } + def edge(value); end + + sig { returns(String) } + def to_dot; end + end + + # The digraph that is being built. + sig { returns(Digraph) } + attr_reader :digraph + + # Initialize a new dot visitor. + sig { void } + def initialize; end + + # Convert this visitor into a graphviz dot graph string. + sig { returns(String) } + def to_dot; end + + sig { params(arg0: AliasGlobalVariableNode).void } + def visit_alias_global_variable_node(arg0); end + + sig { params(arg0: AliasMethodNode).void } + def visit_alias_method_node(arg0); end + + sig { params(arg0: AlternationPatternNode).void } + def visit_alternation_pattern_node(arg0); end + + sig { params(arg0: AndNode).void } + def visit_and_node(arg0); end + + sig { params(arg0: ArgumentsNode).void } + def visit_arguments_node(arg0); end + + sig { params(arg0: ArrayNode).void } + def visit_array_node(arg0); end + + sig { params(arg0: ArrayPatternNode).void } + def visit_array_pattern_node(arg0); end + + sig { params(arg0: AssocNode).void } + def visit_assoc_node(arg0); end + + sig { params(arg0: AssocSplatNode).void } + def visit_assoc_splat_node(arg0); end + + sig { params(arg0: BackReferenceReadNode).void } + def visit_back_reference_read_node(arg0); end + + sig { params(arg0: BeginNode).void } + def visit_begin_node(arg0); end + + sig { params(arg0: BlockArgumentNode).void } + def visit_block_argument_node(arg0); end + + sig { params(arg0: BlockLocalVariableNode).void } + def visit_block_local_variable_node(arg0); end + + sig { params(arg0: BlockNode).void } + def visit_block_node(arg0); end + + sig { params(arg0: BlockParameterNode).void } + def visit_block_parameter_node(arg0); end + + sig { params(arg0: BlockParametersNode).void } + def visit_block_parameters_node(arg0); end + + sig { params(arg0: BreakNode).void } + def visit_break_node(arg0); end + + sig { params(arg0: CallAndWriteNode).void } + def visit_call_and_write_node(arg0); end + + sig { params(arg0: CallNode).void } + def visit_call_node(arg0); end + + sig { params(arg0: CallOperatorWriteNode).void } + def visit_call_operator_write_node(arg0); end + + sig { params(arg0: CallOrWriteNode).void } + def visit_call_or_write_node(arg0); end + + sig { params(arg0: CallTargetNode).void } + def visit_call_target_node(arg0); end + + sig { params(arg0: CapturePatternNode).void } + def visit_capture_pattern_node(arg0); end + + sig { params(arg0: CaseMatchNode).void } + def visit_case_match_node(arg0); end + + sig { params(arg0: CaseNode).void } + def visit_case_node(arg0); end + + sig { params(arg0: ClassNode).void } + def visit_class_node(arg0); end + + sig { params(arg0: ClassVariableAndWriteNode).void } + def visit_class_variable_and_write_node(arg0); end + + sig { params(arg0: ClassVariableOperatorWriteNode).void } + def visit_class_variable_operator_write_node(arg0); end + + sig { params(arg0: ClassVariableOrWriteNode).void } + def visit_class_variable_or_write_node(arg0); end + + sig { params(arg0: ClassVariableReadNode).void } + def visit_class_variable_read_node(arg0); end + + sig { params(arg0: ClassVariableTargetNode).void } + def visit_class_variable_target_node(arg0); end + + sig { params(arg0: ClassVariableWriteNode).void } + def visit_class_variable_write_node(arg0); end + + sig { params(arg0: ConstantAndWriteNode).void } + def visit_constant_and_write_node(arg0); end + + sig { params(arg0: ConstantOperatorWriteNode).void } + def visit_constant_operator_write_node(arg0); end + + sig { params(arg0: ConstantOrWriteNode).void } + def visit_constant_or_write_node(arg0); end + + sig { params(arg0: ConstantPathAndWriteNode).void } + def visit_constant_path_and_write_node(arg0); end + + sig { params(arg0: ConstantPathNode).void } + def visit_constant_path_node(arg0); end + + sig { params(arg0: ConstantPathOperatorWriteNode).void } + def visit_constant_path_operator_write_node(arg0); end + + sig { params(arg0: ConstantPathOrWriteNode).void } + def visit_constant_path_or_write_node(arg0); end + + sig { params(arg0: ConstantPathTargetNode).void } + def visit_constant_path_target_node(arg0); end + + sig { params(arg0: ConstantPathWriteNode).void } + def visit_constant_path_write_node(arg0); end + + sig { params(arg0: ConstantReadNode).void } + def visit_constant_read_node(arg0); end + + sig { params(arg0: ConstantTargetNode).void } + def visit_constant_target_node(arg0); end + + sig { params(arg0: ConstantWriteNode).void } + def visit_constant_write_node(arg0); end + + sig { params(arg0: DefNode).void } + def visit_def_node(arg0); end + + sig { params(arg0: DefinedNode).void } + def visit_defined_node(arg0); end + + sig { params(arg0: ElseNode).void } + def visit_else_node(arg0); end + + sig { params(arg0: EmbeddedStatementsNode).void } + def visit_embedded_statements_node(arg0); end + + sig { params(arg0: EmbeddedVariableNode).void } + def visit_embedded_variable_node(arg0); end + + sig { params(arg0: EnsureNode).void } + def visit_ensure_node(arg0); end + + sig { params(arg0: FalseNode).void } + def visit_false_node(arg0); end + + sig { params(arg0: FindPatternNode).void } + def visit_find_pattern_node(arg0); end + + sig { params(arg0: FlipFlopNode).void } + def visit_flip_flop_node(arg0); end + + sig { params(arg0: FloatNode).void } + def visit_float_node(arg0); end + + sig { params(arg0: ForNode).void } + def visit_for_node(arg0); end + + sig { params(arg0: ForwardingArgumentsNode).void } + def visit_forwarding_arguments_node(arg0); end + + sig { params(arg0: ForwardingParameterNode).void } + def visit_forwarding_parameter_node(arg0); end + + sig { params(arg0: ForwardingSuperNode).void } + def visit_forwarding_super_node(arg0); end + + sig { params(arg0: GlobalVariableAndWriteNode).void } + def visit_global_variable_and_write_node(arg0); end + + sig { params(arg0: GlobalVariableOperatorWriteNode).void } + def visit_global_variable_operator_write_node(arg0); end + + sig { params(arg0: GlobalVariableOrWriteNode).void } + def visit_global_variable_or_write_node(arg0); end + + sig { params(arg0: GlobalVariableReadNode).void } + def visit_global_variable_read_node(arg0); end + + sig { params(arg0: GlobalVariableTargetNode).void } + def visit_global_variable_target_node(arg0); end + + sig { params(arg0: GlobalVariableWriteNode).void } + def visit_global_variable_write_node(arg0); end + + sig { params(arg0: HashNode).void } + def visit_hash_node(arg0); end + + sig { params(arg0: HashPatternNode).void } + def visit_hash_pattern_node(arg0); end + + sig { params(arg0: IfNode).void } + def visit_if_node(arg0); end + + sig { params(arg0: ImaginaryNode).void } + def visit_imaginary_node(arg0); end + + sig { params(arg0: ImplicitNode).void } + def visit_implicit_node(arg0); end + + sig { params(arg0: ImplicitRestNode).void } + def visit_implicit_rest_node(arg0); end + + sig { params(arg0: InNode).void } + def visit_in_node(arg0); end + + sig { params(arg0: IndexAndWriteNode).void } + def visit_index_and_write_node(arg0); end + + sig { params(arg0: IndexOperatorWriteNode).void } + def visit_index_operator_write_node(arg0); end + + sig { params(arg0: IndexOrWriteNode).void } + def visit_index_or_write_node(arg0); end + + sig { params(arg0: IndexTargetNode).void } + def visit_index_target_node(arg0); end + + sig { params(arg0: InstanceVariableAndWriteNode).void } + def visit_instance_variable_and_write_node(arg0); end + + sig { params(arg0: InstanceVariableOperatorWriteNode).void } + def visit_instance_variable_operator_write_node(arg0); end + + sig { params(arg0: InstanceVariableOrWriteNode).void } + def visit_instance_variable_or_write_node(arg0); end + + sig { params(arg0: InstanceVariableReadNode).void } + def visit_instance_variable_read_node(arg0); end + + sig { params(arg0: InstanceVariableTargetNode).void } + def visit_instance_variable_target_node(arg0); end + + sig { params(arg0: InstanceVariableWriteNode).void } + def visit_instance_variable_write_node(arg0); end + + sig { params(arg0: IntegerNode).void } + def visit_integer_node(arg0); end + + sig { params(arg0: InterpolatedMatchLastLineNode).void } + def visit_interpolated_match_last_line_node(arg0); end + + sig { params(arg0: InterpolatedRegularExpressionNode).void } + def visit_interpolated_regular_expression_node(arg0); end + + sig { params(arg0: InterpolatedStringNode).void } + def visit_interpolated_string_node(arg0); end + + sig { params(arg0: InterpolatedSymbolNode).void } + def visit_interpolated_symbol_node(arg0); end + + sig { params(arg0: InterpolatedXStringNode).void } + def visit_interpolated_x_string_node(arg0); end + + sig { params(arg0: ItLocalVariableReadNode).void } + def visit_it_local_variable_read_node(arg0); end + + sig { params(arg0: ItParametersNode).void } + def visit_it_parameters_node(arg0); end + + sig { params(arg0: KeywordHashNode).void } + def visit_keyword_hash_node(arg0); end + + sig { params(arg0: KeywordRestParameterNode).void } + def visit_keyword_rest_parameter_node(arg0); end + + sig { params(arg0: LambdaNode).void } + def visit_lambda_node(arg0); end + + sig { params(arg0: LocalVariableAndWriteNode).void } + def visit_local_variable_and_write_node(arg0); end + + sig { params(arg0: LocalVariableOperatorWriteNode).void } + def visit_local_variable_operator_write_node(arg0); end + + sig { params(arg0: LocalVariableOrWriteNode).void } + def visit_local_variable_or_write_node(arg0); end + + sig { params(arg0: LocalVariableReadNode).void } + def visit_local_variable_read_node(arg0); end + + sig { params(arg0: LocalVariableTargetNode).void } + def visit_local_variable_target_node(arg0); end + + sig { params(arg0: LocalVariableWriteNode).void } + def visit_local_variable_write_node(arg0); end + + sig { params(arg0: MatchLastLineNode).void } + def visit_match_last_line_node(arg0); end + + sig { params(arg0: MatchPredicateNode).void } + def visit_match_predicate_node(arg0); end + + sig { params(arg0: MatchRequiredNode).void } + def visit_match_required_node(arg0); end + + sig { params(arg0: MatchWriteNode).void } + def visit_match_write_node(arg0); end + + sig { params(arg0: MissingNode).void } + def visit_missing_node(arg0); end + + sig { params(arg0: ModuleNode).void } + def visit_module_node(arg0); end + + sig { params(arg0: MultiTargetNode).void } + def visit_multi_target_node(arg0); end + + sig { params(arg0: MultiWriteNode).void } + def visit_multi_write_node(arg0); end + + sig { params(arg0: NextNode).void } + def visit_next_node(arg0); end + + sig { params(arg0: NilNode).void } + def visit_nil_node(arg0); end + + sig { params(arg0: NoBlockParameterNode).void } + def visit_no_block_parameter_node(arg0); end + + sig { params(arg0: NoKeywordsParameterNode).void } + def visit_no_keywords_parameter_node(arg0); end + + sig { params(arg0: NumberedParametersNode).void } + def visit_numbered_parameters_node(arg0); end + + sig { params(arg0: NumberedReferenceReadNode).void } + def visit_numbered_reference_read_node(arg0); end + + sig { params(arg0: OptionalKeywordParameterNode).void } + def visit_optional_keyword_parameter_node(arg0); end + + sig { params(arg0: OptionalParameterNode).void } + def visit_optional_parameter_node(arg0); end + + sig { params(arg0: OrNode).void } + def visit_or_node(arg0); end + + sig { params(arg0: ParametersNode).void } + def visit_parameters_node(arg0); end + + sig { params(arg0: ParenthesesNode).void } + def visit_parentheses_node(arg0); end + + sig { params(arg0: PinnedExpressionNode).void } + def visit_pinned_expression_node(arg0); end + + sig { params(arg0: PinnedVariableNode).void } + def visit_pinned_variable_node(arg0); end + + sig { params(arg0: PostExecutionNode).void } + def visit_post_execution_node(arg0); end + + sig { params(arg0: PreExecutionNode).void } + def visit_pre_execution_node(arg0); end + + sig { params(arg0: ProgramNode).void } + def visit_program_node(arg0); end + + sig { params(arg0: RangeNode).void } + def visit_range_node(arg0); end + + sig { params(arg0: RationalNode).void } + def visit_rational_node(arg0); end + + sig { params(arg0: RedoNode).void } + def visit_redo_node(arg0); end + + sig { params(arg0: RegularExpressionNode).void } + def visit_regular_expression_node(arg0); end + + sig { params(arg0: RequiredKeywordParameterNode).void } + def visit_required_keyword_parameter_node(arg0); end + + sig { params(arg0: RequiredParameterNode).void } + def visit_required_parameter_node(arg0); end + + sig { params(arg0: RescueModifierNode).void } + def visit_rescue_modifier_node(arg0); end + + sig { params(arg0: RescueNode).void } + def visit_rescue_node(arg0); end + + sig { params(arg0: RestParameterNode).void } + def visit_rest_parameter_node(arg0); end + + sig { params(arg0: RetryNode).void } + def visit_retry_node(arg0); end + + sig { params(arg0: ReturnNode).void } + def visit_return_node(arg0); end + + sig { params(arg0: SelfNode).void } + def visit_self_node(arg0); end + + sig { params(arg0: ShareableConstantNode).void } + def visit_shareable_constant_node(arg0); end + + sig { params(arg0: SingletonClassNode).void } + def visit_singleton_class_node(arg0); end + + sig { params(arg0: SourceEncodingNode).void } + def visit_source_encoding_node(arg0); end + + sig { params(arg0: SourceFileNode).void } + def visit_source_file_node(arg0); end + + sig { params(arg0: SourceLineNode).void } + def visit_source_line_node(arg0); end + + sig { params(arg0: SplatNode).void } + def visit_splat_node(arg0); end + + sig { params(arg0: StatementsNode).void } + def visit_statements_node(arg0); end + + sig { params(arg0: StringNode).void } + def visit_string_node(arg0); end + + sig { params(arg0: SuperNode).void } + def visit_super_node(arg0); end + + sig { params(arg0: SymbolNode).void } + def visit_symbol_node(arg0); end + + sig { params(arg0: TrueNode).void } + def visit_true_node(arg0); end + + sig { params(arg0: UndefNode).void } + def visit_undef_node(arg0); end + + sig { params(arg0: UnlessNode).void } + def visit_unless_node(arg0); end + + sig { params(arg0: UntilNode).void } + def visit_until_node(arg0); end + + sig { params(arg0: WhenNode).void } + def visit_when_node(arg0); end + + sig { params(arg0: WhileNode).void } + def visit_while_node(arg0); end + + sig { params(arg0: XStringNode).void } + def visit_x_string_node(arg0); end + + sig { params(arg0: YieldNode).void } + def visit_yield_node(arg0); end + + # Generate a unique node ID for a node throughout the digraph. + sig { params(arg0: Node).returns(String) } + private def node_id(arg0); end + + # Inspect a location to display the start and end line and columns in bytes. + sig { params(arg0: Location).returns(String) } + private def location_inspect(arg0); end + + # Inspect a node that has arguments_node_flags flags to display the flags as a + # comma-separated list. + sig { params(node: ArgumentsNode).returns(String) } + private def arguments_node_flags_inspect(node); end + + # Inspect a node that has array_node_flags flags to display the flags as a + # comma-separated list. + sig { params(node: ArrayNode).returns(String) } + private def array_node_flags_inspect(node); end + + # Inspect a node that has call_node_flags flags to display the flags as a + # comma-separated list. + sig { params(node: ::T.any(CallAndWriteNode, CallNode, CallOperatorWriteNode, CallOrWriteNode, CallTargetNode, IndexAndWriteNode, IndexOperatorWriteNode, IndexOrWriteNode, IndexTargetNode)).returns(String) } + private def call_node_flags_inspect(node); end + + # Inspect a node that has encoding_flags flags to display the flags as a + # comma-separated list. + sig { params(node: XStringNode).returns(String) } + private def encoding_flags_inspect(node); end + + # Inspect a node that has integer_base_flags flags to display the flags as a + # comma-separated list. + sig { params(node: ::T.any(IntegerNode, RationalNode)).returns(String) } + private def integer_base_flags_inspect(node); end + + # Inspect a node that has interpolated_string_node_flags flags to display the flags as a + # comma-separated list. + sig { params(node: InterpolatedStringNode).returns(String) } + private def interpolated_string_node_flags_inspect(node); end + + # Inspect a node that has keyword_hash_node_flags flags to display the flags as a + # comma-separated list. + sig { params(node: KeywordHashNode).returns(String) } + private def keyword_hash_node_flags_inspect(node); end + + # Inspect a node that has loop_flags flags to display the flags as a + # comma-separated list. + sig { params(node: ::T.any(UntilNode, WhileNode)).returns(String) } + private def loop_flags_inspect(node); end + + # Inspect a node that has parameter_flags flags to display the flags as a + # comma-separated list. + sig { params(node: ::T.any(BlockLocalVariableNode, BlockParameterNode, KeywordRestParameterNode, OptionalKeywordParameterNode, OptionalParameterNode, RequiredKeywordParameterNode, RequiredParameterNode, RestParameterNode)).returns(String) } + private def parameter_flags_inspect(node); end + + # Inspect a node that has parentheses_node_flags flags to display the flags as a + # comma-separated list. + sig { params(node: ParenthesesNode).returns(String) } + private def parentheses_node_flags_inspect(node); end + + # Inspect a node that has range_flags flags to display the flags as a + # comma-separated list. + sig { params(node: ::T.any(FlipFlopNode, RangeNode)).returns(String) } + private def range_flags_inspect(node); end + + # Inspect a node that has regular_expression_flags flags to display the flags as a + # comma-separated list. + sig { params(node: ::T.any(InterpolatedMatchLastLineNode, InterpolatedRegularExpressionNode, MatchLastLineNode, RegularExpressionNode)).returns(String) } + private def regular_expression_flags_inspect(node); end + + # Inspect a node that has shareable_constant_node_flags flags to display the flags as a + # comma-separated list. + sig { params(node: ShareableConstantNode).returns(String) } + private def shareable_constant_node_flags_inspect(node); end + + # Inspect a node that has string_flags flags to display the flags as a + # comma-separated list. + sig { params(node: ::T.any(SourceFileNode, StringNode)).returns(String) } + private def string_flags_inspect(node); end + + # Inspect a node that has symbol_flags flags to display the flags as a + # comma-separated list. + sig { params(node: SymbolNode).returns(String) } + private def symbol_flags_inspect(node); end + end +end diff --git a/rbi/generated/prism/dsl.rbi b/rbi/generated/prism/dsl.rbi new file mode 100644 index 0000000000..ac4e68bfa7 --- /dev/null +++ b/rbi/generated/prism/dsl.rbi @@ -0,0 +1,747 @@ +# typed: true + +module Prism + # The DSL module provides a set of methods that can be used to create prism + # nodes in a more concise manner. For example, instead of writing: + # + # source = Prism::Source.for("[1]", 1, []) + # + # Prism::ArrayNode.new( + # source, + # 0, + # Prism::Location.new(source, 0, 3), + # 0, + # [ + # Prism::IntegerNode.new( + # source, + # 0, + # Prism::Location.new(source, 1, 1), + # Prism::IntegerBaseFlags::DECIMAL, + # 1 + # ) + # ], + # Prism::Location.new(source, 0, 1), + # Prism::Location.new(source, 2, 1) + # ) + # + # you could instead write: + # + # class Builder + # include Prism::DSL + # + # attr_reader :default_source + # + # def initialize + # @default_source = source("[1]") + # end + # + # 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 + # Create a new Source object. + sig { params(string: String).returns(Source) } + def source(string); end + + # Create a new Location object. + sig { params(source: Source, start_offset: Integer, length: Integer).returns(Location) } + def location(source: T.unsafe(nil), start_offset: T.unsafe(nil), length: T.unsafe(nil)); end + + # Create a new AliasGlobalVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: ::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode), old_name: ::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode), keyword_loc: Location).returns(AliasGlobalVariableNode) } + def alias_global_variable_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), new_name: T.unsafe(nil), old_name: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new AliasMethodNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: ::T.any(SymbolNode, InterpolatedSymbolNode), old_name: ::T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode), keyword_loc: Location).returns(AliasMethodNode) } + def alias_method_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), new_name: T.unsafe(nil), old_name: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new AlternationPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(AlternationPatternNode) } + def alternation_pattern_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new AndNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(AndNode) } + def and_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new ArgumentsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: T::Array[Node]).returns(ArgumentsNode) } + def arguments_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil)); end + + # Create a new ArrayNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[Node], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(ArrayNode) } + def array_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), elements: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new ArrayPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), requireds: T::Array[Node], rest: ::T.nilable(Node), posts: T::Array[Node], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(ArrayPatternNode) } + def array_pattern_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), requireds: T.unsafe(nil), rest: T.unsafe(nil), posts: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new AssocNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, key: Node, value: Node, operator_loc: ::T.nilable(Location)).returns(AssocNode) } + def assoc_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), key: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new AssocSplatNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: ::T.nilable(Node), operator_loc: Location).returns(AssocSplatNode) } + def assoc_splat_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new BackReferenceReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(BackReferenceReadNode) } + def back_reference_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new BeginNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, begin_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), rescue_clause: ::T.nilable(RescueNode), else_clause: ::T.nilable(ElseNode), ensure_clause: ::T.nilable(EnsureNode), end_keyword_loc: ::T.nilable(Location)).returns(BeginNode) } + def begin_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), begin_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), rescue_clause: T.unsafe(nil), else_clause: T.unsafe(nil), ensure_clause: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new BlockArgumentNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: ::T.nilable(Node), operator_loc: Location).returns(BlockArgumentNode) } + def block_argument_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new BlockLocalVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(BlockLocalVariableNode) } + def block_local_variable_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new BlockNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], parameters: ::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), opening_loc: Location, closing_loc: Location).returns(BlockNode) } + def block_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new BlockParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).returns(BlockParameterNode) } + def block_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new BlockParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parameters: ::T.nilable(ParametersNode), locals: T::Array[BlockLocalVariableNode], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(BlockParametersNode) } + def block_parameters_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parameters: T.unsafe(nil), locals: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new BreakNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: ::T.nilable(ArgumentsNode), keyword_loc: Location).returns(BreakNode) } + def break_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new CallAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallAndWriteNode) } + def call_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new CallNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), name: Symbol, message_loc: ::T.nilable(Location), opening_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), closing_loc: ::T.nilable(Location), equal_loc: ::T.nilable(Location), block: ::T.nilable(::T.any(BlockNode, BlockArgumentNode))).returns(CallNode) } + def call_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), name: T.unsafe(nil), message_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), equal_loc: T.unsafe(nil), block: T.unsafe(nil)); end + + # Create a new CallOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(CallOperatorWriteNode) } + def call_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), binary_operator: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new CallOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallOrWriteNode) } + def call_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new CallTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: Node, call_operator_loc: Location, name: Symbol, message_loc: Location).returns(CallTargetNode) } + def call_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), name: T.unsafe(nil), message_loc: T.unsafe(nil)); end + + # Create a new CapturePatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Node, target: LocalVariableTargetNode, operator_loc: Location).returns(CapturePatternNode) } + def capture_pattern_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new CaseMatchNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: ::T.nilable(Node), conditions: T::Array[InNode], else_clause: ::T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseMatchNode) } + def case_match_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), predicate: T.unsafe(nil), conditions: T.unsafe(nil), else_clause: T.unsafe(nil), case_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new CaseNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: ::T.nilable(Node), conditions: T::Array[WhenNode], else_clause: ::T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseNode) } + def case_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), predicate: T.unsafe(nil), conditions: T.unsafe(nil), else_clause: T.unsafe(nil), case_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new ClassNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, constant_path: ::T.any(ConstantReadNode, ConstantPathNode, CallNode), inheritance_operator_loc: ::T.nilable(Location), superclass: ::T.nilable(Node), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ClassNode) } + def class_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), class_keyword_loc: T.unsafe(nil), constant_path: T.unsafe(nil), inheritance_operator_loc: T.unsafe(nil), superclass: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new ClassVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ClassVariableAndWriteNode) } + def class_variable_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ClassVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ClassVariableOperatorWriteNode) } + def class_variable_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + # Create a new ClassVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ClassVariableOrWriteNode) } + def class_variable_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ClassVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ClassVariableReadNode) } + def class_variable_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new ClassVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ClassVariableTargetNode) } + def class_variable_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new ClassVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(ClassVariableWriteNode) } + def class_variable_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new ConstantAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ConstantAndWriteNode) } + def constant_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ConstantOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ConstantOperatorWriteNode) } + def constant_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + # Create a new ConstantOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ConstantOrWriteNode) } + def constant_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ConstantPathAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathAndWriteNode) } + def constant_path_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ConstantPathNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: ::T.nilable(Node), name: ::T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathNode) } + def constant_path_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parent: T.unsafe(nil), name: T.unsafe(nil), delimiter_loc: T.unsafe(nil), name_loc: T.unsafe(nil)); end + + # Create a new ConstantPathOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ConstantPathOperatorWriteNode) } + def constant_path_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + # Create a new ConstantPathOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathOrWriteNode) } + def constant_path_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ConstantPathTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: ::T.nilable(Node), name: ::T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathTargetNode) } + def constant_path_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parent: T.unsafe(nil), name: T.unsafe(nil), delimiter_loc: T.unsafe(nil), name_loc: T.unsafe(nil)); end + + # Create a new ConstantPathWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathWriteNode) } + def constant_path_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ConstantReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ConstantReadNode) } + def constant_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new ConstantTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ConstantTargetNode) } + def constant_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new ConstantWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(ConstantWriteNode) } + def constant_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new DefNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, receiver: ::T.nilable(Node), parameters: ::T.nilable(ParametersNode), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), locals: T::Array[Symbol], def_keyword_loc: Location, operator_loc: ::T.nilable(Location), lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location), equal_loc: ::T.nilable(Location), end_keyword_loc: ::T.nilable(Location)).returns(DefNode) } + def def_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), receiver: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil), locals: T.unsafe(nil), def_keyword_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil), equal_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new DefinedNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lparen_loc: ::T.nilable(Location), value: Node, rparen_loc: ::T.nilable(Location), keyword_loc: Location).returns(DefinedNode) } + def defined_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lparen_loc: T.unsafe(nil), value: T.unsafe(nil), rparen_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new ElseNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, else_keyword_loc: Location, statements: ::T.nilable(StatementsNode), end_keyword_loc: ::T.nilable(Location)).returns(ElseNode) } + def else_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), else_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new EmbeddedStatementsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, statements: ::T.nilable(StatementsNode), closing_loc: Location).returns(EmbeddedStatementsNode) } + def embedded_statements_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), statements: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new EmbeddedVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, variable: ::T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)).returns(EmbeddedVariableNode) } + def embedded_variable_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), variable: T.unsafe(nil)); end + + # Create a new EnsureNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, ensure_keyword_loc: Location, statements: ::T.nilable(StatementsNode), end_keyword_loc: Location).returns(EnsureNode) } + def ensure_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), ensure_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new FalseNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(FalseNode) } + def false_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new FindPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), left: SplatNode, requireds: T::Array[Node], right: ::T.any(SplatNode, MissingNode), opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(FindPatternNode) } + def find_pattern_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), left: T.unsafe(nil), requireds: T.unsafe(nil), right: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new FlipFlopNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: ::T.nilable(Node), right: ::T.nilable(Node), operator_loc: Location).returns(FlipFlopNode) } + def flip_flop_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new FloatNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Float).returns(FloatNode) } + def float_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ForNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, index: ::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode), collection: Node, statements: ::T.nilable(StatementsNode), for_keyword_loc: Location, in_keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), end_keyword_loc: Location).returns(ForNode) } + def for_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), index: T.unsafe(nil), collection: T.unsafe(nil), statements: T.unsafe(nil), for_keyword_loc: T.unsafe(nil), in_keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new ForwardingArgumentsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(ForwardingArgumentsNode) } + def forwarding_arguments_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new ForwardingParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(ForwardingParameterNode) } + def forwarding_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new ForwardingSuperNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, block: ::T.nilable(BlockNode)).returns(ForwardingSuperNode) } + def forwarding_super_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), block: T.unsafe(nil)); end + + # Create a new GlobalVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(GlobalVariableAndWriteNode) } + def global_variable_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new GlobalVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(GlobalVariableOperatorWriteNode) } + def global_variable_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + # Create a new GlobalVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(GlobalVariableOrWriteNode) } + def global_variable_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new GlobalVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(GlobalVariableReadNode) } + def global_variable_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new GlobalVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(GlobalVariableTargetNode) } + def global_variable_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new GlobalVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(GlobalVariableWriteNode) } + def global_variable_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new HashNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, elements: T::Array[::T.any(AssocNode, AssocSplatNode)], closing_loc: Location).returns(HashNode) } + def hash_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), elements: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new HashPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), elements: T::Array[AssocNode], rest: ::T.nilable(::T.any(AssocSplatNode, NoKeywordsParameterNode)), opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(HashPatternNode) } + def hash_pattern_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), elements: T.unsafe(nil), rest: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new IfNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, if_keyword_loc: ::T.nilable(Location), predicate: Node, then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), subsequent: ::T.nilable(::T.any(ElseNode, IfNode)), end_keyword_loc: ::T.nilable(Location)).returns(IfNode) } + def if_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), if_keyword_loc: T.unsafe(nil), predicate: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), subsequent: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new ImaginaryNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, numeric: ::T.any(FloatNode, IntegerNode, RationalNode)).returns(ImaginaryNode) } + def imaginary_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), numeric: T.unsafe(nil)); end + + # Create a new ImplicitNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: ::T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)).returns(ImplicitNode) } + def implicit_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ImplicitRestNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(ImplicitRestNode) } + def implicit_rest_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new InNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, pattern: Node, statements: ::T.nilable(StatementsNode), in_loc: Location, then_loc: ::T.nilable(Location)).returns(InNode) } + def in_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), pattern: T.unsafe(nil), statements: T.unsafe(nil), in_loc: T.unsafe(nil), then_loc: T.unsafe(nil)); end + + # Create a new IndexAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexAndWriteNode) } + def index_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new IndexOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(IndexOperatorWriteNode) } + def index_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), binary_operator: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new IndexOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexOrWriteNode) } + def index_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new IndexTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: Node, opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode)).returns(IndexTargetNode) } + def index_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil)); end + + # Create a new InstanceVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(InstanceVariableAndWriteNode) } + def instance_variable_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new InstanceVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(InstanceVariableOperatorWriteNode) } + def instance_variable_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + # Create a new InstanceVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(InstanceVariableOrWriteNode) } + def instance_variable_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new InstanceVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(InstanceVariableReadNode) } + def instance_variable_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new InstanceVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(InstanceVariableTargetNode) } + def instance_variable_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new InstanceVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(InstanceVariableWriteNode) } + def instance_variable_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new IntegerNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Integer).returns(IntegerNode) } + def integer_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new InterpolatedMatchLastLineNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedMatchLastLineNode) } + def interpolated_match_last_line_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new InterpolatedRegularExpressionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedRegularExpressionNode) } + def interpolated_regular_expression_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new InterpolatedStringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)], closing_loc: ::T.nilable(Location)).returns(InterpolatedStringNode) } + def interpolated_string_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new InterpolatedSymbolNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: ::T.nilable(Location)).returns(InterpolatedSymbolNode) } + def interpolated_symbol_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new InterpolatedXStringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedXStringNode) } + def interpolated_x_string_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new ItLocalVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(ItLocalVariableReadNode) } + def it_local_variable_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new ItParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(ItParametersNode) } + def it_parameters_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new KeywordHashNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[::T.any(AssocNode, AssocSplatNode)]).returns(KeywordHashNode) } + def keyword_hash_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), elements: T.unsafe(nil)); end + + # Create a new KeywordRestParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).returns(KeywordRestParameterNode) } + def keyword_rest_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new LambdaNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], operator_loc: Location, opening_loc: Location, closing_loc: Location, parameters: ::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: ::T.nilable(::T.any(StatementsNode, BeginNode))).returns(LambdaNode) } + def lambda_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil)); end + + # Create a new LocalVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).returns(LocalVariableAndWriteNode) } + def local_variable_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + # Create a new LocalVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name_loc: Location, binary_operator_loc: Location, value: Node, name: Symbol, binary_operator: Symbol, depth: Integer).returns(LocalVariableOperatorWriteNode) } + def local_variable_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), binary_operator: T.unsafe(nil), depth: T.unsafe(nil)); end + + # Create a new LocalVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).returns(LocalVariableOrWriteNode) } + def local_variable_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + # Create a new LocalVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).returns(LocalVariableReadNode) } + def local_variable_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + # Create a new LocalVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).returns(LocalVariableTargetNode) } + def local_variable_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + # Create a new LocalVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer, name_loc: Location, value: Node, operator_loc: Location).returns(LocalVariableWriteNode) } + def local_variable_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new MatchLastLineNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(MatchLastLineNode) } + def match_last_line_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + # Create a new MatchPredicateNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).returns(MatchPredicateNode) } + def match_predicate_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), pattern: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new MatchRequiredNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).returns(MatchRequiredNode) } + def match_required_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), pattern: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new MatchWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, call: CallNode, targets: T::Array[LocalVariableTargetNode]).returns(MatchWriteNode) } + def match_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), call: T.unsafe(nil), targets: T.unsafe(nil)); end + + # Create a new MissingNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(MissingNode) } + def missing_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new ModuleNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], module_keyword_loc: Location, constant_path: ::T.any(ConstantReadNode, ConstantPathNode, MissingNode), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ModuleNode) } + def module_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), module_keyword_loc: T.unsafe(nil), constant_path: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new MultiTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: ::T.nilable(::T.any(ImplicitRestNode, SplatNode)), rights: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location)).returns(MultiTargetNode) } + def multi_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lefts: T.unsafe(nil), rest: T.unsafe(nil), rights: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end + + # Create a new MultiWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: ::T.nilable(::T.any(ImplicitRestNode, SplatNode)), rights: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location), operator_loc: Location, value: Node).returns(MultiWriteNode) } + def multi_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lefts: T.unsafe(nil), rest: T.unsafe(nil), rights: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new NextNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: ::T.nilable(ArgumentsNode), keyword_loc: Location).returns(NextNode) } + def next_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new NilNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(NilNode) } + def nil_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new NoBlockParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).returns(NoBlockParameterNode) } + def no_block_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new NoKeywordsParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).returns(NoKeywordsParameterNode) } + def no_keywords_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new NumberedParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, maximum: Integer).returns(NumberedParametersNode) } + def numbered_parameters_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), maximum: T.unsafe(nil)); end + + # Create a new NumberedReferenceReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, number: Integer).returns(NumberedReferenceReadNode) } + def numbered_reference_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), number: T.unsafe(nil)); end + + # Create a new OptionalKeywordParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node).returns(OptionalKeywordParameterNode) } + def optional_keyword_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new OptionalParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(OptionalParameterNode) } + def optional_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new OrNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(OrNode) } + def or_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new ParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, requireds: T::Array[::T.any(RequiredParameterNode, MultiTargetNode)], optionals: T::Array[OptionalParameterNode], rest: ::T.nilable(::T.any(RestParameterNode, ImplicitRestNode)), posts: T::Array[::T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)], keywords: T::Array[::T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)], keyword_rest: ::T.nilable(::T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode)), block: ::T.nilable(::T.any(BlockParameterNode, NoBlockParameterNode))).returns(ParametersNode) } + def parameters_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), requireds: T.unsafe(nil), optionals: T.unsafe(nil), rest: T.unsafe(nil), posts: T.unsafe(nil), keywords: T.unsafe(nil), keyword_rest: T.unsafe(nil), block: T.unsafe(nil)); end + + # Create a new ParenthesesNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, body: ::T.nilable(Node), opening_loc: Location, closing_loc: Location).returns(ParenthesesNode) } + def parentheses_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), body: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new PinnedExpressionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: Node, operator_loc: Location, lparen_loc: Location, rparen_loc: Location).returns(PinnedExpressionNode) } + def pinned_expression_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), operator_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end + + # Create a new PinnedVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, variable: ::T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode), operator_loc: Location).returns(PinnedVariableNode) } + def pinned_variable_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), variable: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new PostExecutionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: ::T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PostExecutionNode) } + def post_execution_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), statements: T.unsafe(nil), keyword_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new PreExecutionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: ::T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PreExecutionNode) } + def pre_execution_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), statements: T.unsafe(nil), keyword_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new ProgramNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], statements: StatementsNode).returns(ProgramNode) } + def program_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), statements: T.unsafe(nil)); end + + # Create a new RangeNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: ::T.nilable(Node), right: ::T.nilable(Node), operator_loc: Location).returns(RangeNode) } + def range_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new RationalNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, numerator: Integer, denominator: Integer).returns(RationalNode) } + def rational_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), numerator: T.unsafe(nil), denominator: T.unsafe(nil)); end + + # Create a new RedoNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(RedoNode) } + def redo_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new RegularExpressionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(RegularExpressionNode) } + def regular_expression_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + # Create a new RequiredKeywordParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location).returns(RequiredKeywordParameterNode) } + def required_keyword_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil)); end + + # Create a new RequiredParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(RequiredParameterNode) } + def required_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new RescueModifierNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: Node, keyword_loc: Location, rescue_expression: Node).returns(RescueModifierNode) } + def rescue_modifier_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), keyword_loc: T.unsafe(nil), rescue_expression: T.unsafe(nil)); end + + # Create a new RescueNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, exceptions: T::Array[Node], operator_loc: ::T.nilable(Location), reference: ::T.nilable(::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)), then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), subsequent: ::T.nilable(RescueNode)).returns(RescueNode) } + def rescue_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), exceptions: T.unsafe(nil), operator_loc: T.unsafe(nil), reference: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), subsequent: T.unsafe(nil)); end + + # Create a new RestParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).returns(RestParameterNode) } + def rest_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new RetryNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(RetryNode) } + def retry_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new ReturnNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, arguments: ::T.nilable(ArgumentsNode)).returns(ReturnNode) } + def return_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), arguments: T.unsafe(nil)); end + + # Create a new SelfNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(SelfNode) } + def self_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new ShareableConstantNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, write: ::T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)).returns(ShareableConstantNode) } + def shareable_constant_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), write: T.unsafe(nil)); end + + # Create a new SingletonClassNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, operator_loc: Location, expression: Node, body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location).returns(SingletonClassNode) } + def singleton_class_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), class_keyword_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), expression: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new SourceEncodingNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(SourceEncodingNode) } + def source_encoding_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new SourceFileNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, filepath: String).returns(SourceFileNode) } + def source_file_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), filepath: T.unsafe(nil)); end + + # Create a new SourceLineNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(SourceLineNode) } + def source_line_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new SplatNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, expression: ::T.nilable(Node)).returns(SplatNode) } + def splat_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), expression: T.unsafe(nil)); end + + # Create a new StatementsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, body: T::Array[Node]).returns(StatementsNode) } + def statements_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), body: T.unsafe(nil)); end + + # Create a new StringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), content_loc: Location, closing_loc: ::T.nilable(Location), unescaped: String).returns(StringNode) } + def string_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + # Create a new SuperNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), rparen_loc: ::T.nilable(Location), block: ::T.nilable(::T.any(BlockNode, BlockArgumentNode))).returns(SuperNode) } + def super_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), arguments: T.unsafe(nil), rparen_loc: T.unsafe(nil), block: T.unsafe(nil)); end + + # Create a new SymbolNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), value_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), unescaped: String).returns(SymbolNode) } + def symbol_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), value_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + # Create a new TrueNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(TrueNode) } + def true_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new UndefNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, names: T::Array[::T.any(SymbolNode, InterpolatedSymbolNode)], keyword_loc: Location).returns(UndefNode) } + def undef_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), names: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new UnlessNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, predicate: Node, then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), else_clause: ::T.nilable(ElseNode), end_keyword_loc: ::T.nilable(Location)).returns(UnlessNode) } + def unless_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), predicate: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), else_clause: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new UntilNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), predicate: Node, statements: ::T.nilable(StatementsNode)).returns(UntilNode) } + def until_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), predicate: T.unsafe(nil), statements: T.unsafe(nil)); end + + # Create a new WhenNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, conditions: T::Array[Node], then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode)).returns(WhenNode) } + def when_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), conditions: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil)); end + + # Create a new WhileNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), predicate: Node, statements: ::T.nilable(StatementsNode)).returns(WhileNode) } + def while_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), predicate: T.unsafe(nil), statements: T.unsafe(nil)); end + + # Create a new XStringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(XStringNode) } + def x_string_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + # Create a new YieldNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), rparen_loc: ::T.nilable(Location)).returns(YieldNode) } + def yield_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), arguments: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end + + # Retrieve the value of one of the ArgumentsNodeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def arguments_node_flag(name); end + + # Retrieve the value of one of the ArrayNodeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def array_node_flag(name); end + + # Retrieve the value of one of the CallNodeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def call_node_flag(name); end + + # Retrieve the value of one of the EncodingFlags flags. + sig { params(name: Symbol).returns(Integer) } + def encoding_flag(name); end + + # Retrieve the value of one of the IntegerBaseFlags flags. + sig { params(name: Symbol).returns(Integer) } + def integer_base_flag(name); end + + # Retrieve the value of one of the InterpolatedStringNodeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def interpolated_string_node_flag(name); end + + # Retrieve the value of one of the KeywordHashNodeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def keyword_hash_node_flag(name); end + + # Retrieve the value of one of the LoopFlags flags. + sig { params(name: Symbol).returns(Integer) } + def loop_flag(name); end + + # Retrieve the value of one of the ParameterFlags flags. + sig { params(name: Symbol).returns(Integer) } + def parameter_flag(name); end + + # Retrieve the value of one of the ParenthesesNodeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def parentheses_node_flag(name); end + + # Retrieve the value of one of the RangeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def range_flag(name); end + + # Retrieve the value of one of the RegularExpressionFlags flags. + sig { params(name: Symbol).returns(Integer) } + def regular_expression_flag(name); end + + # Retrieve the value of one of the ShareableConstantNodeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def shareable_constant_node_flag(name); end + + # Retrieve the value of one of the StringFlags flags. + sig { params(name: Symbol).returns(Integer) } + def string_flag(name); end + + # Retrieve the value of one of the SymbolFlags flags. + sig { params(name: Symbol).returns(Integer) } + def symbol_flag(name); end + + # The default source object that gets attached to nodes and locations if no + # source is specified. + sig { returns(Source) } + private def default_source; end + + # The default location object that gets attached to nodes if no location is + # specified, which uses the given source. + sig { returns(Location) } + private def default_location; end + + # The default node that gets attached to nodes if no node is specified for a + # required node field. + sig { params(source: Source, location: Location).returns(Node) } + private def default_node(source, location); end + end +end diff --git a/rbi/generated/prism/inspect_visitor.rbi b/rbi/generated/prism/inspect_visitor.rbi new file mode 100644 index 0000000000..449a531c38 --- /dev/null +++ b/rbi/generated/prism/inspect_visitor.rbi @@ -0,0 +1,503 @@ +# typed: true + +module Prism + # This visitor is responsible for composing the strings that get returned by + # the various #inspect methods defined on each of the nodes. + class InspectVisitor < Visitor + # Most of the time, we can simply pass down the indent to the next node. + # However, when we are inside a list we want some extra special formatting + # when we hit an element in that list. In this case, we have a special + # command that replaces the subsequent indent with the given value. + class Replace + sig { returns(String) } + attr_reader :value + + sig { params(value: String).void } + def initialize(value); end + end + + # The current prefix string. + sig { returns(String) } + attr_reader :indent + + # The list of commands that we need to execute in order to compose the + # final string. + sig { returns(T::Array[[::T.any(String, Node, Replace), String]]) } + attr_reader :commands + + sig { params(indent: String).void } + def initialize(indent = T.unsafe(nil)); end + + # Compose an inspect string for the given node. + sig { params(node: Node).returns(String) } + def self.compose(node); end + + # Compose the final string. + sig { returns(String) } + def compose; end + + sig { params(node: AliasGlobalVariableNode).void } + def visit_alias_global_variable_node(node); end + + sig { params(node: AliasMethodNode).void } + def visit_alias_method_node(node); end + + sig { params(node: AlternationPatternNode).void } + def visit_alternation_pattern_node(node); end + + sig { params(node: AndNode).void } + def visit_and_node(node); end + + sig { params(node: ArgumentsNode).void } + def visit_arguments_node(node); end + + sig { params(node: ArrayNode).void } + def visit_array_node(node); end + + sig { params(node: ArrayPatternNode).void } + def visit_array_pattern_node(node); end + + sig { params(node: AssocNode).void } + def visit_assoc_node(node); end + + sig { params(node: AssocSplatNode).void } + def visit_assoc_splat_node(node); end + + sig { params(node: BackReferenceReadNode).void } + def visit_back_reference_read_node(node); end + + sig { params(node: BeginNode).void } + def visit_begin_node(node); end + + sig { params(node: BlockArgumentNode).void } + def visit_block_argument_node(node); end + + sig { params(node: BlockLocalVariableNode).void } + def visit_block_local_variable_node(node); end + + sig { params(node: BlockNode).void } + def visit_block_node(node); end + + sig { params(node: BlockParameterNode).void } + def visit_block_parameter_node(node); end + + sig { params(node: BlockParametersNode).void } + def visit_block_parameters_node(node); end + + sig { params(node: BreakNode).void } + def visit_break_node(node); end + + sig { params(node: CallAndWriteNode).void } + def visit_call_and_write_node(node); end + + sig { params(node: CallNode).void } + def visit_call_node(node); end + + sig { params(node: CallOperatorWriteNode).void } + def visit_call_operator_write_node(node); end + + sig { params(node: CallOrWriteNode).void } + def visit_call_or_write_node(node); end + + sig { params(node: CallTargetNode).void } + def visit_call_target_node(node); end + + sig { params(node: CapturePatternNode).void } + def visit_capture_pattern_node(node); end + + sig { params(node: CaseMatchNode).void } + def visit_case_match_node(node); end + + sig { params(node: CaseNode).void } + def visit_case_node(node); end + + sig { params(node: ClassNode).void } + def visit_class_node(node); end + + sig { params(node: ClassVariableAndWriteNode).void } + def visit_class_variable_and_write_node(node); end + + sig { params(node: ClassVariableOperatorWriteNode).void } + def visit_class_variable_operator_write_node(node); end + + sig { params(node: ClassVariableOrWriteNode).void } + def visit_class_variable_or_write_node(node); end + + sig { params(node: ClassVariableReadNode).void } + def visit_class_variable_read_node(node); end + + sig { params(node: ClassVariableTargetNode).void } + def visit_class_variable_target_node(node); end + + sig { params(node: ClassVariableWriteNode).void } + def visit_class_variable_write_node(node); end + + sig { params(node: ConstantAndWriteNode).void } + def visit_constant_and_write_node(node); end + + sig { params(node: ConstantOperatorWriteNode).void } + def visit_constant_operator_write_node(node); end + + sig { params(node: ConstantOrWriteNode).void } + def visit_constant_or_write_node(node); end + + sig { params(node: ConstantPathAndWriteNode).void } + def visit_constant_path_and_write_node(node); end + + sig { params(node: ConstantPathNode).void } + def visit_constant_path_node(node); end + + sig { params(node: ConstantPathOperatorWriteNode).void } + def visit_constant_path_operator_write_node(node); end + + sig { params(node: ConstantPathOrWriteNode).void } + def visit_constant_path_or_write_node(node); end + + sig { params(node: ConstantPathTargetNode).void } + def visit_constant_path_target_node(node); end + + sig { params(node: ConstantPathWriteNode).void } + def visit_constant_path_write_node(node); end + + sig { params(node: ConstantReadNode).void } + def visit_constant_read_node(node); end + + sig { params(node: ConstantTargetNode).void } + def visit_constant_target_node(node); end + + sig { params(node: ConstantWriteNode).void } + def visit_constant_write_node(node); end + + sig { params(node: DefNode).void } + def visit_def_node(node); end + + sig { params(node: DefinedNode).void } + def visit_defined_node(node); end + + sig { params(node: ElseNode).void } + def visit_else_node(node); end + + sig { params(node: EmbeddedStatementsNode).void } + def visit_embedded_statements_node(node); end + + sig { params(node: EmbeddedVariableNode).void } + def visit_embedded_variable_node(node); end + + sig { params(node: EnsureNode).void } + def visit_ensure_node(node); end + + sig { params(node: FalseNode).void } + def visit_false_node(node); end + + sig { params(node: FindPatternNode).void } + def visit_find_pattern_node(node); end + + sig { params(node: FlipFlopNode).void } + def visit_flip_flop_node(node); end + + sig { params(node: FloatNode).void } + def visit_float_node(node); end + + sig { params(node: ForNode).void } + def visit_for_node(node); end + + sig { params(node: ForwardingArgumentsNode).void } + def visit_forwarding_arguments_node(node); end + + sig { params(node: ForwardingParameterNode).void } + def visit_forwarding_parameter_node(node); end + + sig { params(node: ForwardingSuperNode).void } + def visit_forwarding_super_node(node); end + + sig { params(node: GlobalVariableAndWriteNode).void } + def visit_global_variable_and_write_node(node); end + + sig { params(node: GlobalVariableOperatorWriteNode).void } + def visit_global_variable_operator_write_node(node); end + + sig { params(node: GlobalVariableOrWriteNode).void } + def visit_global_variable_or_write_node(node); end + + sig { params(node: GlobalVariableReadNode).void } + def visit_global_variable_read_node(node); end + + sig { params(node: GlobalVariableTargetNode).void } + def visit_global_variable_target_node(node); end + + sig { params(node: GlobalVariableWriteNode).void } + def visit_global_variable_write_node(node); end + + sig { params(node: HashNode).void } + def visit_hash_node(node); end + + sig { params(node: HashPatternNode).void } + def visit_hash_pattern_node(node); end + + sig { params(node: IfNode).void } + def visit_if_node(node); end + + sig { params(node: ImaginaryNode).void } + def visit_imaginary_node(node); end + + sig { params(node: ImplicitNode).void } + def visit_implicit_node(node); end + + sig { params(node: ImplicitRestNode).void } + def visit_implicit_rest_node(node); end + + sig { params(node: InNode).void } + def visit_in_node(node); end + + sig { params(node: IndexAndWriteNode).void } + def visit_index_and_write_node(node); end + + sig { params(node: IndexOperatorWriteNode).void } + def visit_index_operator_write_node(node); end + + sig { params(node: IndexOrWriteNode).void } + def visit_index_or_write_node(node); end + + sig { params(node: IndexTargetNode).void } + def visit_index_target_node(node); end + + sig { params(node: InstanceVariableAndWriteNode).void } + def visit_instance_variable_and_write_node(node); end + + sig { params(node: InstanceVariableOperatorWriteNode).void } + def visit_instance_variable_operator_write_node(node); end + + sig { params(node: InstanceVariableOrWriteNode).void } + def visit_instance_variable_or_write_node(node); end + + sig { params(node: InstanceVariableReadNode).void } + def visit_instance_variable_read_node(node); end + + sig { params(node: InstanceVariableTargetNode).void } + def visit_instance_variable_target_node(node); end + + sig { params(node: InstanceVariableWriteNode).void } + def visit_instance_variable_write_node(node); end + + sig { params(node: IntegerNode).void } + def visit_integer_node(node); end + + sig { params(node: InterpolatedMatchLastLineNode).void } + def visit_interpolated_match_last_line_node(node); end + + sig { params(node: InterpolatedRegularExpressionNode).void } + def visit_interpolated_regular_expression_node(node); end + + sig { params(node: InterpolatedStringNode).void } + def visit_interpolated_string_node(node); end + + sig { params(node: InterpolatedSymbolNode).void } + def visit_interpolated_symbol_node(node); end + + sig { params(node: InterpolatedXStringNode).void } + def visit_interpolated_x_string_node(node); end + + sig { params(node: ItLocalVariableReadNode).void } + def visit_it_local_variable_read_node(node); end + + sig { params(node: ItParametersNode).void } + def visit_it_parameters_node(node); end + + sig { params(node: KeywordHashNode).void } + def visit_keyword_hash_node(node); end + + sig { params(node: KeywordRestParameterNode).void } + def visit_keyword_rest_parameter_node(node); end + + sig { params(node: LambdaNode).void } + def visit_lambda_node(node); end + + sig { params(node: LocalVariableAndWriteNode).void } + def visit_local_variable_and_write_node(node); end + + sig { params(node: LocalVariableOperatorWriteNode).void } + def visit_local_variable_operator_write_node(node); end + + sig { params(node: LocalVariableOrWriteNode).void } + def visit_local_variable_or_write_node(node); end + + sig { params(node: LocalVariableReadNode).void } + def visit_local_variable_read_node(node); end + + sig { params(node: LocalVariableTargetNode).void } + def visit_local_variable_target_node(node); end + + sig { params(node: LocalVariableWriteNode).void } + def visit_local_variable_write_node(node); end + + sig { params(node: MatchLastLineNode).void } + def visit_match_last_line_node(node); end + + sig { params(node: MatchPredicateNode).void } + def visit_match_predicate_node(node); end + + sig { params(node: MatchRequiredNode).void } + def visit_match_required_node(node); end + + sig { params(node: MatchWriteNode).void } + def visit_match_write_node(node); end + + sig { params(node: MissingNode).void } + def visit_missing_node(node); end + + sig { params(node: ModuleNode).void } + def visit_module_node(node); end + + sig { params(node: MultiTargetNode).void } + def visit_multi_target_node(node); end + + sig { params(node: MultiWriteNode).void } + def visit_multi_write_node(node); end + + sig { params(node: NextNode).void } + def visit_next_node(node); end + + sig { params(node: NilNode).void } + def visit_nil_node(node); end + + sig { params(node: NoBlockParameterNode).void } + def visit_no_block_parameter_node(node); end + + sig { params(node: NoKeywordsParameterNode).void } + def visit_no_keywords_parameter_node(node); end + + sig { params(node: NumberedParametersNode).void } + def visit_numbered_parameters_node(node); end + + sig { params(node: NumberedReferenceReadNode).void } + def visit_numbered_reference_read_node(node); end + + sig { params(node: OptionalKeywordParameterNode).void } + def visit_optional_keyword_parameter_node(node); end + + sig { params(node: OptionalParameterNode).void } + def visit_optional_parameter_node(node); end + + sig { params(node: OrNode).void } + def visit_or_node(node); end + + sig { params(node: ParametersNode).void } + def visit_parameters_node(node); end + + sig { params(node: ParenthesesNode).void } + def visit_parentheses_node(node); end + + sig { params(node: PinnedExpressionNode).void } + def visit_pinned_expression_node(node); end + + sig { params(node: PinnedVariableNode).void } + def visit_pinned_variable_node(node); end + + sig { params(node: PostExecutionNode).void } + def visit_post_execution_node(node); end + + sig { params(node: PreExecutionNode).void } + def visit_pre_execution_node(node); end + + sig { params(node: ProgramNode).void } + def visit_program_node(node); end + + sig { params(node: RangeNode).void } + def visit_range_node(node); end + + sig { params(node: RationalNode).void } + def visit_rational_node(node); end + + sig { params(node: RedoNode).void } + def visit_redo_node(node); end + + sig { params(node: RegularExpressionNode).void } + def visit_regular_expression_node(node); end + + sig { params(node: RequiredKeywordParameterNode).void } + def visit_required_keyword_parameter_node(node); end + + sig { params(node: RequiredParameterNode).void } + def visit_required_parameter_node(node); end + + sig { params(node: RescueModifierNode).void } + def visit_rescue_modifier_node(node); end + + sig { params(node: RescueNode).void } + def visit_rescue_node(node); end + + sig { params(node: RestParameterNode).void } + def visit_rest_parameter_node(node); end + + sig { params(node: RetryNode).void } + def visit_retry_node(node); end + + sig { params(node: ReturnNode).void } + def visit_return_node(node); end + + sig { params(node: SelfNode).void } + def visit_self_node(node); end + + sig { params(node: ShareableConstantNode).void } + def visit_shareable_constant_node(node); end + + sig { params(node: SingletonClassNode).void } + def visit_singleton_class_node(node); end + + sig { params(node: SourceEncodingNode).void } + def visit_source_encoding_node(node); end + + sig { params(node: SourceFileNode).void } + def visit_source_file_node(node); end + + sig { params(node: SourceLineNode).void } + def visit_source_line_node(node); end + + sig { params(node: SplatNode).void } + def visit_splat_node(node); end + + sig { params(node: StatementsNode).void } + def visit_statements_node(node); end + + sig { params(node: StringNode).void } + def visit_string_node(node); end + + sig { params(node: SuperNode).void } + def visit_super_node(node); end + + sig { params(node: SymbolNode).void } + def visit_symbol_node(node); end + + sig { params(node: TrueNode).void } + def visit_true_node(node); end + + sig { params(node: UndefNode).void } + def visit_undef_node(node); end + + sig { params(node: UnlessNode).void } + def visit_unless_node(node); end + + sig { params(node: UntilNode).void } + def visit_until_node(node); end + + sig { params(node: WhenNode).void } + def visit_when_node(node); end + + sig { params(node: WhileNode).void } + def visit_while_node(node); end + + sig { params(node: XStringNode).void } + def visit_x_string_node(node); end + + sig { params(node: YieldNode).void } + def visit_yield_node(node); end + + # Compose a header for the given node. + sig { params(name: String, node: Node).returns(String) } + private def inspect_node(name, node); end + + # Compose a string representing the given inner location field. + sig { params(location: ::T.nilable(Location)).returns(String) } + private def inspect_location(location); end + end +end diff --git a/rbi/generated/prism/lex_compat.rbi b/rbi/generated/prism/lex_compat.rbi new file mode 100644 index 0000000000..ca479b7225 --- /dev/null +++ b/rbi/generated/prism/lex_compat.rbi @@ -0,0 +1,155 @@ +# typed: true + +module Prism + module Translation + class Ripper + EXPR_NONE = T.let(nil, Integer) + EXPR_BEG = T.let(nil, Integer) + EXPR_MID = T.let(nil, Integer) + EXPR_END = T.let(nil, Integer) + EXPR_CLASS = T.let(nil, Integer) + EXPR_VALUE = T.let(nil, Integer) + EXPR_ARG = T.let(nil, Integer) + EXPR_CMDARG = T.let(nil, Integer) + EXPR_ENDARG = T.let(nil, Integer) + EXPR_ENDFN = T.let(nil, Integer) + + class Lexer < Ripper + class State + sig { params(value: Integer).returns(State) } + def self.[](value); end + end + end + end + end + + # This class is responsible for lexing the source using prism and then + # converting those tokens to be compatible with Ripper. In the vast majority + # of cases, this is a one-to-one mapping of the token type. Everything else + # generally lines up. However, there are a few cases that require special + # handling. + class LexCompat + # A result class specialized for holding tokens produced by the lexer. + class Result < Prism::Result + # The list of tokens that were produced by the lexer. + sig { returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } + attr_reader :value + + # Create a new lex compat result object with the given values. + sig { params(value: T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], continuable: T::Boolean, source: Source).void } + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source); end + + # Implement the hash pattern matching interface for Result. + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + end + + # This is a mapping of prism token types to Ripper token types. This is a + # many-to-one mapping because we split up our token types, whereas Ripper + # tends to group them. + RIPPER = T.let(nil, ::T.untyped) + + # A heredoc in this case is a list of tokens that belong to the body of the + # heredoc that should be appended onto the list of tokens when the heredoc + # closes. + module Heredoc + # Heredocs that are no dash or tilde heredocs are just a list of tokens. + # We need to keep them around so that we can insert them in the correct + # order back into the token stream and set the state of the last token to + # the state that the heredoc was opened in. + class PlainHeredoc + sig { returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } + attr_reader :tokens + + sig { void } + def initialize; end + + sig { params(token: [[Integer, Integer], Symbol, String, ::T.untyped]).void } + def <<(token); end + + sig { returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } + def to_a; end + end + + # Dash heredocs are a little more complicated. They are a list of tokens + # that need to be split on "\\\n" to mimic Ripper's behavior. We also need + # to keep track of the state that the heredoc was opened in. + class DashHeredoc + sig { returns(T::Boolean) } + attr_reader :split + + sig { returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } + attr_reader :tokens + + sig { params(split: T::Boolean).void } + def initialize(split); end + + sig { params(token: [[Integer, Integer], Symbol, String, ::T.untyped]).void } + def <<(token); end + + sig { returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } + def to_a; end + end + + # Heredocs that are dedenting heredocs are a little more complicated. + # Ripper outputs on_ignored_sp tokens for the whitespace that is being + # removed from the output. prism only modifies the node itself and keeps + # the token the same. This simplifies prism, but makes comparing against + # Ripper much harder because there is a length mismatch. + # + # Fortunately, we already have to pull out the heredoc tokens in order to + # insert them into the stream in the correct order. As such, we can do + # some extra manipulation on the tokens to make them match Ripper's + # output by mirroring the dedent logic that Ripper uses. + class DedentingHeredoc + TAB_WIDTH = T.let(nil, Integer) + + sig { returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } + attr_reader :tokens + + sig { returns(T::Boolean) } + attr_reader :dedent_next + + sig { returns(::T.nilable(Integer)) } + attr_reader :dedent + + sig { returns(Integer) } + attr_reader :embexpr_balance + + sig { void } + def initialize; end + + # As tokens are coming in, we track the minimum amount of common leading + # whitespace on plain string content tokens. This allows us to later + # remove that amount of whitespace from the beginning of each line. + # + sig { params(token: [[Integer, Integer], Symbol, String, ::T.untyped]).void } + def <<(token); end + + sig { returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } + def to_a; end + end + + # Here we will split between the two types of heredocs and return the + # object that will store their tokens. + sig { params(opening: [[Integer, Integer], Symbol, String, ::T.untyped]).returns(::T.any(PlainHeredoc, DashHeredoc, DedentingHeredoc)) } + def self.build(opening); end + end + + # In previous versions of Ruby, Ripper wouldn't flush the bom before the + # first token, so we had to have a hack in place to account for that. + BOM_FLUSHED = T.let(nil, ::T.untyped) + + sig { returns(T::Hash[Symbol, ::T.untyped]) } + attr_reader :options + + sig { params(source: String, options: ::T.untyped).void } + def initialize(source, **options); end + + sig { returns(Result) } + def result; end + + sig { params(tokens: T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]], source: Source, data_loc: ::T.nilable(Location), bom: T::Boolean, eof_token: ::T.nilable(Token)).returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } + private def post_process_tokens(tokens, source, data_loc, bom, eof_token); end + end +end diff --git a/rbi/generated/prism/mutation_compiler.rbi b/rbi/generated/prism/mutation_compiler.rbi new file mode 100644 index 0000000000..21be124fed --- /dev/null +++ b/rbi/generated/prism/mutation_compiler.rbi @@ -0,0 +1,464 @@ +# typed: true + +module Prism + # This visitor walks through the tree and copies each node as it is being + # visited. This is useful for consumers that want to mutate the tree, as you + # can change subtrees in place without effecting the rest of the tree. + class MutationCompiler < Compiler + sig { params(arg0: AliasGlobalVariableNode).returns(::T.nilable(Node)) } + def visit_alias_global_variable_node(arg0); end + + sig { params(arg0: AliasMethodNode).returns(::T.nilable(Node)) } + def visit_alias_method_node(arg0); end + + sig { params(arg0: AlternationPatternNode).returns(::T.nilable(Node)) } + def visit_alternation_pattern_node(arg0); end + + sig { params(arg0: AndNode).returns(::T.nilable(Node)) } + def visit_and_node(arg0); end + + sig { params(arg0: ArgumentsNode).returns(::T.nilable(Node)) } + def visit_arguments_node(arg0); end + + sig { params(arg0: ArrayNode).returns(::T.nilable(Node)) } + def visit_array_node(arg0); end + + sig { params(arg0: ArrayPatternNode).returns(::T.nilable(Node)) } + def visit_array_pattern_node(arg0); end + + sig { params(arg0: AssocNode).returns(::T.nilable(Node)) } + def visit_assoc_node(arg0); end + + sig { params(arg0: AssocSplatNode).returns(::T.nilable(Node)) } + def visit_assoc_splat_node(arg0); end + + sig { params(arg0: BackReferenceReadNode).returns(::T.nilable(Node)) } + def visit_back_reference_read_node(arg0); end + + sig { params(arg0: BeginNode).returns(::T.nilable(Node)) } + def visit_begin_node(arg0); end + + sig { params(arg0: BlockArgumentNode).returns(::T.nilable(Node)) } + def visit_block_argument_node(arg0); end + + sig { params(arg0: BlockLocalVariableNode).returns(::T.nilable(Node)) } + def visit_block_local_variable_node(arg0); end + + sig { params(arg0: BlockNode).returns(::T.nilable(Node)) } + def visit_block_node(arg0); end + + sig { params(arg0: BlockParameterNode).returns(::T.nilable(Node)) } + def visit_block_parameter_node(arg0); end + + sig { params(arg0: BlockParametersNode).returns(::T.nilable(Node)) } + def visit_block_parameters_node(arg0); end + + sig { params(arg0: BreakNode).returns(::T.nilable(Node)) } + def visit_break_node(arg0); end + + sig { params(arg0: CallAndWriteNode).returns(::T.nilable(Node)) } + def visit_call_and_write_node(arg0); end + + sig { params(arg0: CallNode).returns(::T.nilable(Node)) } + def visit_call_node(arg0); end + + sig { params(arg0: CallOperatorWriteNode).returns(::T.nilable(Node)) } + def visit_call_operator_write_node(arg0); end + + sig { params(arg0: CallOrWriteNode).returns(::T.nilable(Node)) } + def visit_call_or_write_node(arg0); end + + sig { params(arg0: CallTargetNode).returns(::T.nilable(Node)) } + def visit_call_target_node(arg0); end + + sig { params(arg0: CapturePatternNode).returns(::T.nilable(Node)) } + def visit_capture_pattern_node(arg0); end + + sig { params(arg0: CaseMatchNode).returns(::T.nilable(Node)) } + def visit_case_match_node(arg0); end + + sig { params(arg0: CaseNode).returns(::T.nilable(Node)) } + def visit_case_node(arg0); end + + sig { params(arg0: ClassNode).returns(::T.nilable(Node)) } + def visit_class_node(arg0); end + + sig { params(arg0: ClassVariableAndWriteNode).returns(::T.nilable(Node)) } + def visit_class_variable_and_write_node(arg0); end + + sig { params(arg0: ClassVariableOperatorWriteNode).returns(::T.nilable(Node)) } + def visit_class_variable_operator_write_node(arg0); end + + sig { params(arg0: ClassVariableOrWriteNode).returns(::T.nilable(Node)) } + def visit_class_variable_or_write_node(arg0); end + + sig { params(arg0: ClassVariableReadNode).returns(::T.nilable(Node)) } + def visit_class_variable_read_node(arg0); end + + sig { params(arg0: ClassVariableTargetNode).returns(::T.nilable(Node)) } + def visit_class_variable_target_node(arg0); end + + sig { params(arg0: ClassVariableWriteNode).returns(::T.nilable(Node)) } + def visit_class_variable_write_node(arg0); end + + sig { params(arg0: ConstantAndWriteNode).returns(::T.nilable(Node)) } + def visit_constant_and_write_node(arg0); end + + sig { params(arg0: ConstantOperatorWriteNode).returns(::T.nilable(Node)) } + def visit_constant_operator_write_node(arg0); end + + sig { params(arg0: ConstantOrWriteNode).returns(::T.nilable(Node)) } + def visit_constant_or_write_node(arg0); end + + sig { params(arg0: ConstantPathAndWriteNode).returns(::T.nilable(Node)) } + def visit_constant_path_and_write_node(arg0); end + + sig { params(arg0: ConstantPathNode).returns(::T.nilable(Node)) } + def visit_constant_path_node(arg0); end + + sig { params(arg0: ConstantPathOperatorWriteNode).returns(::T.nilable(Node)) } + def visit_constant_path_operator_write_node(arg0); end + + sig { params(arg0: ConstantPathOrWriteNode).returns(::T.nilable(Node)) } + def visit_constant_path_or_write_node(arg0); end + + sig { params(arg0: ConstantPathTargetNode).returns(::T.nilable(Node)) } + def visit_constant_path_target_node(arg0); end + + sig { params(arg0: ConstantPathWriteNode).returns(::T.nilable(Node)) } + def visit_constant_path_write_node(arg0); end + + sig { params(arg0: ConstantReadNode).returns(::T.nilable(Node)) } + def visit_constant_read_node(arg0); end + + sig { params(arg0: ConstantTargetNode).returns(::T.nilable(Node)) } + def visit_constant_target_node(arg0); end + + sig { params(arg0: ConstantWriteNode).returns(::T.nilable(Node)) } + def visit_constant_write_node(arg0); end + + sig { params(arg0: DefNode).returns(::T.nilable(Node)) } + def visit_def_node(arg0); end + + sig { params(arg0: DefinedNode).returns(::T.nilable(Node)) } + def visit_defined_node(arg0); end + + sig { params(arg0: ElseNode).returns(::T.nilable(Node)) } + def visit_else_node(arg0); end + + sig { params(arg0: EmbeddedStatementsNode).returns(::T.nilable(Node)) } + def visit_embedded_statements_node(arg0); end + + sig { params(arg0: EmbeddedVariableNode).returns(::T.nilable(Node)) } + def visit_embedded_variable_node(arg0); end + + sig { params(arg0: EnsureNode).returns(::T.nilable(Node)) } + def visit_ensure_node(arg0); end + + sig { params(arg0: FalseNode).returns(::T.nilable(Node)) } + def visit_false_node(arg0); end + + sig { params(arg0: FindPatternNode).returns(::T.nilable(Node)) } + def visit_find_pattern_node(arg0); end + + sig { params(arg0: FlipFlopNode).returns(::T.nilable(Node)) } + def visit_flip_flop_node(arg0); end + + sig { params(arg0: FloatNode).returns(::T.nilable(Node)) } + def visit_float_node(arg0); end + + sig { params(arg0: ForNode).returns(::T.nilable(Node)) } + def visit_for_node(arg0); end + + sig { params(arg0: ForwardingArgumentsNode).returns(::T.nilable(Node)) } + def visit_forwarding_arguments_node(arg0); end + + sig { params(arg0: ForwardingParameterNode).returns(::T.nilable(Node)) } + def visit_forwarding_parameter_node(arg0); end + + sig { params(arg0: ForwardingSuperNode).returns(::T.nilable(Node)) } + def visit_forwarding_super_node(arg0); end + + sig { params(arg0: GlobalVariableAndWriteNode).returns(::T.nilable(Node)) } + def visit_global_variable_and_write_node(arg0); end + + sig { params(arg0: GlobalVariableOperatorWriteNode).returns(::T.nilable(Node)) } + def visit_global_variable_operator_write_node(arg0); end + + sig { params(arg0: GlobalVariableOrWriteNode).returns(::T.nilable(Node)) } + def visit_global_variable_or_write_node(arg0); end + + sig { params(arg0: GlobalVariableReadNode).returns(::T.nilable(Node)) } + def visit_global_variable_read_node(arg0); end + + sig { params(arg0: GlobalVariableTargetNode).returns(::T.nilable(Node)) } + def visit_global_variable_target_node(arg0); end + + sig { params(arg0: GlobalVariableWriteNode).returns(::T.nilable(Node)) } + def visit_global_variable_write_node(arg0); end + + sig { params(arg0: HashNode).returns(::T.nilable(Node)) } + def visit_hash_node(arg0); end + + sig { params(arg0: HashPatternNode).returns(::T.nilable(Node)) } + def visit_hash_pattern_node(arg0); end + + sig { params(arg0: IfNode).returns(::T.nilable(Node)) } + def visit_if_node(arg0); end + + sig { params(arg0: ImaginaryNode).returns(::T.nilable(Node)) } + def visit_imaginary_node(arg0); end + + sig { params(arg0: ImplicitNode).returns(::T.nilable(Node)) } + def visit_implicit_node(arg0); end + + sig { params(arg0: ImplicitRestNode).returns(::T.nilable(Node)) } + def visit_implicit_rest_node(arg0); end + + sig { params(arg0: InNode).returns(::T.nilable(Node)) } + def visit_in_node(arg0); end + + sig { params(arg0: IndexAndWriteNode).returns(::T.nilable(Node)) } + def visit_index_and_write_node(arg0); end + + sig { params(arg0: IndexOperatorWriteNode).returns(::T.nilable(Node)) } + def visit_index_operator_write_node(arg0); end + + sig { params(arg0: IndexOrWriteNode).returns(::T.nilable(Node)) } + def visit_index_or_write_node(arg0); end + + sig { params(arg0: IndexTargetNode).returns(::T.nilable(Node)) } + def visit_index_target_node(arg0); end + + sig { params(arg0: InstanceVariableAndWriteNode).returns(::T.nilable(Node)) } + def visit_instance_variable_and_write_node(arg0); end + + sig { params(arg0: InstanceVariableOperatorWriteNode).returns(::T.nilable(Node)) } + def visit_instance_variable_operator_write_node(arg0); end + + sig { params(arg0: InstanceVariableOrWriteNode).returns(::T.nilable(Node)) } + def visit_instance_variable_or_write_node(arg0); end + + sig { params(arg0: InstanceVariableReadNode).returns(::T.nilable(Node)) } + def visit_instance_variable_read_node(arg0); end + + sig { params(arg0: InstanceVariableTargetNode).returns(::T.nilable(Node)) } + def visit_instance_variable_target_node(arg0); end + + sig { params(arg0: InstanceVariableWriteNode).returns(::T.nilable(Node)) } + def visit_instance_variable_write_node(arg0); end + + sig { params(arg0: IntegerNode).returns(::T.nilable(Node)) } + def visit_integer_node(arg0); end + + sig { params(arg0: InterpolatedMatchLastLineNode).returns(::T.nilable(Node)) } + def visit_interpolated_match_last_line_node(arg0); end + + sig { params(arg0: InterpolatedRegularExpressionNode).returns(::T.nilable(Node)) } + def visit_interpolated_regular_expression_node(arg0); end + + sig { params(arg0: InterpolatedStringNode).returns(::T.nilable(Node)) } + def visit_interpolated_string_node(arg0); end + + sig { params(arg0: InterpolatedSymbolNode).returns(::T.nilable(Node)) } + def visit_interpolated_symbol_node(arg0); end + + sig { params(arg0: InterpolatedXStringNode).returns(::T.nilable(Node)) } + def visit_interpolated_x_string_node(arg0); end + + sig { params(arg0: ItLocalVariableReadNode).returns(::T.nilable(Node)) } + def visit_it_local_variable_read_node(arg0); end + + sig { params(arg0: ItParametersNode).returns(::T.nilable(Node)) } + def visit_it_parameters_node(arg0); end + + sig { params(arg0: KeywordHashNode).returns(::T.nilable(Node)) } + def visit_keyword_hash_node(arg0); end + + sig { params(arg0: KeywordRestParameterNode).returns(::T.nilable(Node)) } + def visit_keyword_rest_parameter_node(arg0); end + + sig { params(arg0: LambdaNode).returns(::T.nilable(Node)) } + def visit_lambda_node(arg0); end + + sig { params(arg0: LocalVariableAndWriteNode).returns(::T.nilable(Node)) } + def visit_local_variable_and_write_node(arg0); end + + sig { params(arg0: LocalVariableOperatorWriteNode).returns(::T.nilable(Node)) } + def visit_local_variable_operator_write_node(arg0); end + + sig { params(arg0: LocalVariableOrWriteNode).returns(::T.nilable(Node)) } + def visit_local_variable_or_write_node(arg0); end + + sig { params(arg0: LocalVariableReadNode).returns(::T.nilable(Node)) } + def visit_local_variable_read_node(arg0); end + + sig { params(arg0: LocalVariableTargetNode).returns(::T.nilable(Node)) } + def visit_local_variable_target_node(arg0); end + + sig { params(arg0: LocalVariableWriteNode).returns(::T.nilable(Node)) } + def visit_local_variable_write_node(arg0); end + + sig { params(arg0: MatchLastLineNode).returns(::T.nilable(Node)) } + def visit_match_last_line_node(arg0); end + + sig { params(arg0: MatchPredicateNode).returns(::T.nilable(Node)) } + def visit_match_predicate_node(arg0); end + + sig { params(arg0: MatchRequiredNode).returns(::T.nilable(Node)) } + def visit_match_required_node(arg0); end + + sig { params(arg0: MatchWriteNode).returns(::T.nilable(Node)) } + def visit_match_write_node(arg0); end + + sig { params(arg0: MissingNode).returns(::T.nilable(Node)) } + def visit_missing_node(arg0); end + + sig { params(arg0: ModuleNode).returns(::T.nilable(Node)) } + def visit_module_node(arg0); end + + sig { params(arg0: MultiTargetNode).returns(::T.nilable(Node)) } + def visit_multi_target_node(arg0); end + + sig { params(arg0: MultiWriteNode).returns(::T.nilable(Node)) } + def visit_multi_write_node(arg0); end + + sig { params(arg0: NextNode).returns(::T.nilable(Node)) } + def visit_next_node(arg0); end + + sig { params(arg0: NilNode).returns(::T.nilable(Node)) } + def visit_nil_node(arg0); end + + sig { params(arg0: NoBlockParameterNode).returns(::T.nilable(Node)) } + def visit_no_block_parameter_node(arg0); end + + sig { params(arg0: NoKeywordsParameterNode).returns(::T.nilable(Node)) } + def visit_no_keywords_parameter_node(arg0); end + + sig { params(arg0: NumberedParametersNode).returns(::T.nilable(Node)) } + def visit_numbered_parameters_node(arg0); end + + sig { params(arg0: NumberedReferenceReadNode).returns(::T.nilable(Node)) } + def visit_numbered_reference_read_node(arg0); end + + sig { params(arg0: OptionalKeywordParameterNode).returns(::T.nilable(Node)) } + def visit_optional_keyword_parameter_node(arg0); end + + sig { params(arg0: OptionalParameterNode).returns(::T.nilable(Node)) } + def visit_optional_parameter_node(arg0); end + + sig { params(arg0: OrNode).returns(::T.nilable(Node)) } + def visit_or_node(arg0); end + + sig { params(arg0: ParametersNode).returns(::T.nilable(Node)) } + def visit_parameters_node(arg0); end + + sig { params(arg0: ParenthesesNode).returns(::T.nilable(Node)) } + def visit_parentheses_node(arg0); end + + sig { params(arg0: PinnedExpressionNode).returns(::T.nilable(Node)) } + def visit_pinned_expression_node(arg0); end + + sig { params(arg0: PinnedVariableNode).returns(::T.nilable(Node)) } + def visit_pinned_variable_node(arg0); end + + sig { params(arg0: PostExecutionNode).returns(::T.nilable(Node)) } + def visit_post_execution_node(arg0); end + + sig { params(arg0: PreExecutionNode).returns(::T.nilable(Node)) } + def visit_pre_execution_node(arg0); end + + sig { params(arg0: ProgramNode).returns(::T.nilable(Node)) } + def visit_program_node(arg0); end + + sig { params(arg0: RangeNode).returns(::T.nilable(Node)) } + def visit_range_node(arg0); end + + sig { params(arg0: RationalNode).returns(::T.nilable(Node)) } + def visit_rational_node(arg0); end + + sig { params(arg0: RedoNode).returns(::T.nilable(Node)) } + def visit_redo_node(arg0); end + + sig { params(arg0: RegularExpressionNode).returns(::T.nilable(Node)) } + def visit_regular_expression_node(arg0); end + + sig { params(arg0: RequiredKeywordParameterNode).returns(::T.nilable(Node)) } + def visit_required_keyword_parameter_node(arg0); end + + sig { params(arg0: RequiredParameterNode).returns(::T.nilable(Node)) } + def visit_required_parameter_node(arg0); end + + sig { params(arg0: RescueModifierNode).returns(::T.nilable(Node)) } + def visit_rescue_modifier_node(arg0); end + + sig { params(arg0: RescueNode).returns(::T.nilable(Node)) } + def visit_rescue_node(arg0); end + + sig { params(arg0: RestParameterNode).returns(::T.nilable(Node)) } + def visit_rest_parameter_node(arg0); end + + sig { params(arg0: RetryNode).returns(::T.nilable(Node)) } + def visit_retry_node(arg0); end + + sig { params(arg0: ReturnNode).returns(::T.nilable(Node)) } + def visit_return_node(arg0); end + + sig { params(arg0: SelfNode).returns(::T.nilable(Node)) } + def visit_self_node(arg0); end + + sig { params(arg0: ShareableConstantNode).returns(::T.nilable(Node)) } + def visit_shareable_constant_node(arg0); end + + sig { params(arg0: SingletonClassNode).returns(::T.nilable(Node)) } + def visit_singleton_class_node(arg0); end + + sig { params(arg0: SourceEncodingNode).returns(::T.nilable(Node)) } + def visit_source_encoding_node(arg0); end + + sig { params(arg0: SourceFileNode).returns(::T.nilable(Node)) } + def visit_source_file_node(arg0); end + + sig { params(arg0: SourceLineNode).returns(::T.nilable(Node)) } + def visit_source_line_node(arg0); end + + sig { params(arg0: SplatNode).returns(::T.nilable(Node)) } + def visit_splat_node(arg0); end + + sig { params(arg0: StatementsNode).returns(::T.nilable(Node)) } + def visit_statements_node(arg0); end + + sig { params(arg0: StringNode).returns(::T.nilable(Node)) } + def visit_string_node(arg0); end + + sig { params(arg0: SuperNode).returns(::T.nilable(Node)) } + def visit_super_node(arg0); end + + sig { params(arg0: SymbolNode).returns(::T.nilable(Node)) } + def visit_symbol_node(arg0); end + + sig { params(arg0: TrueNode).returns(::T.nilable(Node)) } + def visit_true_node(arg0); end + + sig { params(arg0: UndefNode).returns(::T.nilable(Node)) } + def visit_undef_node(arg0); end + + sig { params(arg0: UnlessNode).returns(::T.nilable(Node)) } + def visit_unless_node(arg0); end + + sig { params(arg0: UntilNode).returns(::T.nilable(Node)) } + def visit_until_node(arg0); end + + sig { params(arg0: WhenNode).returns(::T.nilable(Node)) } + def visit_when_node(arg0); end + + sig { params(arg0: WhileNode).returns(::T.nilable(Node)) } + def visit_while_node(arg0); end + + sig { params(arg0: XStringNode).returns(::T.nilable(Node)) } + def visit_x_string_node(arg0); end + + sig { params(arg0: YieldNode).returns(::T.nilable(Node)) } + def visit_yield_node(arg0); end + end +end diff --git a/rbi/generated/prism/node.rbi b/rbi/generated/prism/node.rbi new file mode 100644 index 0000000000..3b62926afb --- /dev/null +++ b/rbi/generated/prism/node.rbi @@ -0,0 +1,14280 @@ +# typed: true + +module Prism + # This represents a node in the tree. It is the parent class of all of the + # various node types. + class Node + abstract! + + # A pointer to the source that this node was created from. + sig { returns(Source) } + attr_reader :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. + sig { returns(Integer) } + attr_reader :node_id + + # Save this node using a saved source so that it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save(repository); end + + # A Location instance that represents the location of this node in the + # source. + sig { returns(Location) } + def location; end + + # Save the location using a saved source so that it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_location(repository); end + + # Delegates to [`start_line`](rdoc-ref:Location#start_line) of the associated location object. + sig { returns(Integer) } + def start_line; end + + # Delegates to [`end_line`](rdoc-ref:Location#end_line) of the associated location object. + sig { returns(Integer) } + def end_line; end + + # Delegates to [`start_offset`](rdoc-ref:Location#start_offset) of the associated location object. + sig { returns(Integer) } + def start_offset; end + + # Delegates to [`end_offset`](rdoc-ref:Location#end_offset) of the associated location object. + sig { returns(Integer) } + def end_offset; end + + # Delegates to [`start_character_offset`](rdoc-ref:Location#start_character_offset) + # of the associated location object. + sig { returns(Integer) } + def start_character_offset; end + + # Delegates to [`end_character_offset`](rdoc-ref:Location#end_character_offset) + # of the associated location object. + sig { returns(Integer) } + def end_character_offset; end + + # Delegates to [`cached_start_code_units_offset`](rdoc-ref:Location#cached_start_code_units_offset) + # of the associated location object. + sig { params(cache: ::T.untyped).returns(Integer) } + def cached_start_code_units_offset(cache); end + + # Delegates to [`cached_end_code_units_offset`](rdoc-ref:Location#cached_end_code_units_offset) + # of the associated location object. + sig { params(cache: ::T.untyped).returns(Integer) } + def cached_end_code_units_offset(cache); end + + # Delegates to [`start_column`](rdoc-ref:Location#start_column) of the associated location object. + sig { returns(Integer) } + def start_column; end + + # Delegates to [`end_column`](rdoc-ref:Location#end_column) of the associated location object. + sig { returns(Integer) } + def end_column; end + + # Delegates to [`start_character_column`](rdoc-ref:Location#start_character_column) + # of the associated location object. + sig { returns(Integer) } + def start_character_column; end + + # Delegates to [`end_character_column`](rdoc-ref:Location#end_character_column) + # of the associated location object. + sig { returns(Integer) } + def end_character_column; end + + # Delegates to [`cached_start_code_units_column`](rdoc-ref:Location#cached_start_code_units_column) + # of the associated location object. + sig { params(cache: ::T.untyped).returns(Integer) } + def cached_start_code_units_column(cache); end + + # Delegates to [`cached_end_code_units_column`](rdoc-ref:Location#cached_end_code_units_column) + # of the associated location object. + sig { params(cache: ::T.untyped).returns(Integer) } + def cached_end_code_units_column(cache); end + + # Delegates to [`leading_comments`](rdoc-ref:Location#leading_comments) of the associated location object. + sig { returns(T::Array[Comment]) } + def leading_comments; end + + # Delegates to [`trailing_comments`](rdoc-ref:Location#trailing_comments) of the associated location object. + sig { returns(T::Array[Comment]) } + def trailing_comments; end + + # Delegates to [`comments`](rdoc-ref:Location#comments) of the associated location object. + sig { returns(T::Array[Comment]) } + def comments; end + + # Returns all of the lines of the source code associated with this node. + sig { returns(T::Array[String]) } + def source_lines; end + + # An alias for source_lines, used to mimic the API from + # RubyVM::AbstractSyntaxTree to make it easier to migrate. + sig { returns(T::Array[String]) } + def script_lines; end + + # Slice the location of the node from the source. + sig { returns(String) } + def slice; end + + # Slice the location of the node from the source, starting at the beginning + # of the line that the location starts on, ending at the end of the line + # that the location ends on. + sig { returns(String) } + def 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. + sig { returns(Integer) } + attr_reader :flags + + # Returns true if the node has the newline flag set. + sig { returns(T::Boolean) } + def newline?; end + + # Returns true if the node has the static literal flag set. + sig { returns(T::Boolean) } + def static_literal?; end + + # Similar to inspect, but respects the current level of indentation given by + # the pretty print object. + sig { params(q: PP).void } + def pretty_print(q); end + + # Convert this node into a graphviz dot graph string. + sig { returns(String) } + def to_dot; end + + # Returns a list of nodes that are descendants of this node that contain the + # given line and column. This is useful for locating a node that is selected + # based on the line and column of the source code. + # + # Important to note is that the column given to this method should be in + # bytes, as opposed to characters or code units. + sig { params(line: Integer, column: Integer).returns(T::Array[Node]) } + def tunnel(line, column); end + + # Returns the first node that matches the given block when visited in a + # breadth-first search. This is useful for finding a node that matches a + # particular condition. + # + # node.breadth_first_search { |node| node.node_id == node_id } + sig { params(blk: ::T.proc.params(arg0: Node).returns(T::Boolean)).returns(::T.nilable(Node)) } + def breadth_first_search(&blk); end + + sig { params(blk: ::T.proc.params(arg0: Node).returns(T::Boolean)).returns(::T.nilable(Node)) } + def find(&blk); end + + # Returns all of the nodes that match the given block when visited in a + # breadth-first search. This is useful for finding all nodes that match a + # particular condition. + # + # node.breadth_first_search_all { |node| node.is_a?(Prism::CallNode) } + sig { params(blk: ::T.proc.params(arg0: Node).returns(T::Boolean)).returns(T::Array[Node]) } + def breadth_first_search_all(&blk); end + + sig { params(blk: ::T.proc.params(arg0: Node).returns(T::Boolean)).returns(T::Array[Node]) } + def find_all(&blk); 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. + sig { returns(T::Array[Reflection::Field]) } + def self.fields; end + + # Accepts a visitor and calls back into the specialized visit function. + sig { abstract.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # Returns an array of child nodes, including `nil`s in the place of optional + # nodes that were not present. + sig { abstract.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + sig { abstract.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + # With a block given, yields each child node. Without a block, returns + # an enumerator that contains each child node. Excludes any `nil`s in + # the place of optional nodes that were not present. + sig { abstract.returns(T::Enumerator[Node]) } + sig { abstract.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # Returns an array of child nodes, excluding any `nil`s in the place of + # optional nodes that were not present. + sig { abstract.returns(T::Array[Node]) } + def compact_child_nodes; end + + # Returns an array of child nodes and locations that could potentially have + # comments attached to them. + sig { abstract.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Returns a string representation of the node. + sig { abstract.returns(String) } + def inspect; 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. + sig { abstract.returns(Symbol) } + def type; 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. + sig { abstract.returns(Symbol) } + def self.type; end + end + + # Represents the use of the `alias` keyword to alias a global variable. + # + # alias $foo $bar + # ^^^^^^^^^^^^^^^ + class AliasGlobalVariableNode < Node + # Initialize a new AliasGlobalVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: ::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode), old_name: ::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode), keyword_loc: Location).void } + def initialize(source, node_id, location, flags, new_name, old_name, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, new_name: ::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode), old_name: ::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode), keyword_loc: Location).returns(AliasGlobalVariableNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), new_name: T.unsafe(nil), old_name: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the new name of the global variable that can be used after aliasing. + # + # alias $foo $bar + # ^^^^ + sig { returns(::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)) } + def new_name; end + + # Represents the old name of the global variable that can be used before aliasing. + # + # alias $foo $bar + # ^^^^ + sig { returns(::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode)) } + def old_name; end + + # The Location of the `alias` keyword. + # + # alias $foo $bar + # ^^^^^ + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `alias` keyword to alias a method. + # + # alias foo bar + # ^^^^^^^^^^^^^ + class AliasMethodNode < Node + # Initialize a new AliasMethodNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: ::T.any(SymbolNode, InterpolatedSymbolNode), old_name: ::T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode), keyword_loc: Location).void } + def initialize(source, node_id, location, flags, new_name, old_name, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, new_name: ::T.any(SymbolNode, InterpolatedSymbolNode), old_name: ::T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode), keyword_loc: Location).returns(AliasMethodNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), new_name: T.unsafe(nil), old_name: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the new name of the method that will be aliased. + # + # alias foo bar + # ^^^ + # + # alias :foo :bar + # ^^^^ + # + # alias :"#{foo}" :"#{bar}" + # ^^^^^^^^^ + sig { returns(::T.any(SymbolNode, InterpolatedSymbolNode)) } + def new_name; end + + # Represents the old name of the method that will be aliased. + # + # alias foo bar + # ^^^ + # + # alias :foo :bar + # ^^^^ + # + # alias :"#{foo}" :"#{bar}" + # ^^^^^^^^^ + sig { returns(::T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode)) } + def old_name; end + + # Represents the Location of the `alias` keyword. + # + # alias foo bar + # ^^^^^ + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an alternation pattern in pattern matching. + # + # foo => bar | baz + # ^^^^^^^^^ + class AlternationPatternNode < Node + # Initialize a new AlternationPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, left, right, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(AlternationPatternNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the left side of the expression. + # + # foo => bar | baz + # ^^^ + sig { returns(Node) } + def left; end + + # Represents the right side of the expression. + # + # foo => bar | baz + # ^^^ + sig { returns(Node) } + def right; end + + # Represents the alternation operator Location. + # + # foo => bar | baz + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&` operator or the `and` keyword. + # + # left and right + # ^^^^^^^^^^^^^^ + class AndNode < Node + # Initialize a new AndNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, left, right, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(AndNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # 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). + # + # left and right + # ^^^^ + # + # 1 && 2 + # ^ + sig { returns(Node) } + def left; end + + # Represents the right side of the expression. + # + # left && right + # ^^^^^ + # + # 1 and 2 + # ^ + sig { returns(Node) } + def right; end + + # The Location of the `and` keyword or the `&&` operator. + # + # left and right + # ^^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a set of arguments to a method or a keyword. + # + # return foo, bar, baz + # ^^^^^^^^^^^^^ + class ArgumentsNode < Node + # Initialize a new ArgumentsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: T::Array[Node]).void } + def initialize(source, node_id, location, flags, arguments); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, arguments: T::Array[Node]).returns(ArgumentsNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # if the arguments contain forwarding + sig { returns(T::Boolean) } + def contains_forwarding?; end + + # if the arguments contain keywords + sig { returns(T::Boolean) } + def contains_keywords?; end + + # if the arguments contain a keyword splat + sig { returns(T::Boolean) } + def contains_keyword_splat?; end + + # if the arguments contain a splat + sig { returns(T::Boolean) } + def contains_splat?; end + + # if the arguments contain multiple splats + sig { returns(T::Boolean) } + def contains_multiple_splats?; end + + # The list of arguments, if present. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo(bar, baz) + # ^^^^^^^^ + sig { returns(T::Array[Node]) } + def arguments; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an array literal. This can be a regular array using brackets or a special array using % like %w or %i. + # + # [1, 2, 3] + # ^^^^^^^^^ + class ArrayNode < Node + # Initialize a new ArrayNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[Node], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, elements, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, elements: T::Array[Node], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(ArrayNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), elements: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # if array contains splat nodes + sig { returns(T::Boolean) } + def contains_splat?; end + + # 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. + sig { returns(T::Array[Node]) } + def elements; end + + # Represents the optional source Location for the opening token. + # + # [1,2,3] # "[" + # %w[foo bar baz] # "%w[" + # %I(apple orange banana) # "%I(" + # foo = 1, 2, 3 # nil + sig { returns(::T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Represents the optional source Location for the closing token. + # + # [1,2,3] # "]" + # %w[foo bar baz] # "]" + # %I(apple orange banana) # ")" + # foo = 1, 2, 3 # nil + sig { returns(::T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(::T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(::T.nilable(String)) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an array pattern in pattern matching. + # + # foo in 1, 2 + # ^^^^ + # + # foo in [1, 2] + # ^^^^^^ + # + # foo in *bar + # ^^^^ + # + # foo in Bar[] + # ^^^^^ + # + # foo in Bar[1, 2, 3] + # ^^^^^^^^^^^^ + class ArrayPatternNode < Node + # Initialize a new ArrayPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), requireds: T::Array[Node], rest: ::T.nilable(Node), posts: T::Array[Node], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, constant, requireds, rest, posts, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), requireds: T::Array[Node], rest: ::T.nilable(Node), posts: T::Array[Node], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(ArrayPatternNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), requireds: T.unsafe(nil), rest: T.unsafe(nil), posts: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the optional constant preceding the Array + # + # foo in Bar[] + # ^^^ + # + # foo in Bar[1, 2, 3] + # ^^^ + # + # foo in Bar::Baz[1, 2, 3] + # ^^^^^^^^ + sig { returns(::T.nilable(::T.any(ConstantPathNode, ConstantReadNode))) } + def constant; end + + # Represents the required elements of the array pattern. + # + # foo in [1, 2] + # ^ ^ + sig { returns(T::Array[Node]) } + def requireds; end + + # Represents the rest element of the array pattern. + # + # foo in *bar + # ^^^^ + sig { returns(::T.nilable(Node)) } + def rest; end + + # Represents the elements after the rest element of the array pattern. + # + # foo in *bar, baz + # ^^^ + sig { returns(T::Array[Node]) } + def posts; end + + # Represents the opening Location of the array pattern. + # + # foo in [1, 2] + # ^ + sig { returns(::T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Represents the closing Location of the array pattern. + # + # foo in [1, 2] + # ^ + sig { returns(::T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(::T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(::T.nilable(String)) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a hash key/value pair. + # + # { a => b } + # ^^^^^^ + class AssocNode < Node + # Initialize a new AssocNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, key: Node, value: Node, operator_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, key, value, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, key: Node, value: Node, operator_loc: ::T.nilable(Location)).returns(AssocNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), key: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # 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). + # + # { a: b } + # ^ + # + # { foo => bar } + # ^^^ + # + # { def a; end => 1 } + # ^^^^^^^^^^ + sig { returns(Node) } + def key; end + + # 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). + # + # { foo => bar } + # ^^^ + # + # { x: 1 } + # ^ + sig { returns(Node) } + def value; end + + # The Location of the `=>` operator, if present. + # + # { foo => bar } + # ^^ + sig { returns(::T.nilable(Location)) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(::T.nilable(String)) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a splat in a hash literal. + # + # { **foo } + # ^^^^^ + class AssocSplatNode < Node + # Initialize a new AssocSplatNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: ::T.nilable(Node), operator_loc: Location).void } + def initialize(source, node_id, location, flags, value, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, value: ::T.nilable(Node), operator_loc: Location).returns(AssocSplatNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The value to be splatted, if present. Will be missing when keyword rest argument forwarding is used. + # + # { **foo } + # ^^^ + sig { returns(::T.nilable(Node)) } + def value; end + + # The Location of the `**` operator. + # + # { **x } + # ^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents reading a reference to a field in the previous match. + # + # $' + # ^^ + class BackReferenceReadNode < Node + # Initialize a new BackReferenceReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(BackReferenceReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the back-reference variable, including the leading `$`. + # + # $& # name `:$&` + # + # $+ # name `:$+` + sig { returns(Symbol) } + def name; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a begin statement. + # + # begin + # foo + # end + # ^^^^^ + class BeginNode < Node + # Initialize a new BeginNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, begin_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), rescue_clause: ::T.nilable(RescueNode), else_clause: ::T.nilable(ElseNode), ensure_clause: ::T.nilable(EnsureNode), end_keyword_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, begin_keyword_loc, statements, rescue_clause, else_clause, ensure_clause, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, begin_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), rescue_clause: ::T.nilable(RescueNode), else_clause: ::T.nilable(ElseNode), ensure_clause: ::T.nilable(EnsureNode), end_keyword_loc: ::T.nilable(Location)).returns(BeginNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), begin_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), rescue_clause: T.unsafe(nil), else_clause: T.unsafe(nil), ensure_clause: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the Location of the `begin` keyword. + # + # begin x end + # ^^^^^ + sig { returns(::T.nilable(Location)) } + def begin_keyword_loc; end + + # Save the begin_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_begin_keyword_loc(repository); end + + # Represents the statements within the begin block. + # + # begin x end + # ^ + sig { returns(::T.nilable(StatementsNode)) } + def statements; end + + # Represents the rescue clause within the begin block. + # + # begin x; rescue y; end + # ^^^^^^^^ + sig { returns(::T.nilable(RescueNode)) } + def rescue_clause; end + + # Represents the else clause within the begin block. + # + # begin x; rescue y; else z; end + # ^^^^^^^^^^^ + sig { returns(::T.nilable(ElseNode)) } + def else_clause; end + + # Represents the ensure clause within the begin block. + # + # begin x; ensure y; end + # ^^^^^^^^ + sig { returns(::T.nilable(EnsureNode)) } + def ensure_clause; end + + # Represents the Location of the `end` keyword. + # + # begin x end + # ^^^ + sig { returns(::T.nilable(Location)) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_end_keyword_loc(repository); end + + # Slice the location of begin_keyword_loc from the source. + sig { returns(::T.nilable(String)) } + def begin_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(::T.nilable(String)) } + def end_keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a block argument using `&`. + # + # bar(&args) + # ^^^^^ + class BlockArgumentNode < Node + # Initialize a new BlockArgumentNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: ::T.nilable(Node), operator_loc: Location).void } + def initialize(source, node_id, location, flags, expression, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, expression: ::T.nilable(Node), operator_loc: Location).returns(BlockArgumentNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The expression that is being passed as a block argument. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo(&args) + # ^^^^ + sig { returns(::T.nilable(Node)) } + def expression; end + + # Represents the Location of the `&` operator. + # + # foo(&args) + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a block local variable. + # + # a { |; b| } + # ^ + class BlockLocalVariableNode < Node + # Initialize a new BlockLocalVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(BlockLocalVariableNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # The name of the block local variable. + # + # a { |; b| } # name `:b` + # ^ + sig { returns(Symbol) } + def name; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a block of ruby code. + # + # [1, 2, 3].each { |i| puts x } + # ^^^^^^^^^^^^^^ + class BlockNode < Node + # Initialize a new BlockNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], parameters: ::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), opening_loc: Location, closing_loc: Location).void } + def initialize(source, node_id, location, flags, locals, parameters, body, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], parameters: ::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), opening_loc: Location, closing_loc: Location).returns(BlockNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The local variables declared in the block. + # + # [1, 2, 3].each { |i| puts x } # locals: [:i] + # ^ + sig { returns(T::Array[Symbol]) } + def locals; end + + # The parameters of the block. + # + # [1, 2, 3].each { |i| puts x } + # ^^^ + # [1, 2, 3].each { puts _1 } + # ^^^^^^^^^^^ + # [1, 2, 3].each { puts it } + # ^^^^^^^^^^^ + sig { returns(::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode))) } + def parameters; end + + # The body of the block. + # + # [1, 2, 3].each { |i| puts x } + # ^^^^^^ + sig { returns(::T.nilable(::T.any(StatementsNode, BeginNode))) } + def body; end + + # Represents the Location of the opening `{` or `do`. + # + # [1, 2, 3].each { |i| puts x } + # ^ + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Represents the Location of the closing `}` or `end`. + # + # [1, 2, 3].each { |i| puts x } + # ^ + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a block parameter of a method, block, or lambda definition. + # + # def a(&b) + # ^^ + # end + class BlockParameterNode < Node + # Initialize a new BlockParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).returns(BlockParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # The name of the block parameter. + # + # def a(&b) # name `:b` + # ^ + # end + sig { returns(::T.nilable(Symbol)) } + def name; end + + # Represents the Location of the block parameter name. + # + # def a(&b) + # ^ + sig { returns(::T.nilable(Location)) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_name_loc(repository); end + + # Represents the Location of the `&` operator. + # + # def a(&b) + # ^ + # end + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a block's parameters declaration. + # + # -> (a, b = 1; local) { } + # ^^^^^^^^^^^^^^^^^ + # + # foo do |a, b = 1; local| + # ^^^^^^^^^^^^^^^^^ + # end + class BlockParametersNode < Node + # Initialize a new BlockParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parameters: ::T.nilable(ParametersNode), locals: T::Array[BlockLocalVariableNode], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, parameters, locals, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, parameters: ::T.nilable(ParametersNode), locals: T::Array[BlockLocalVariableNode], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(BlockParametersNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parameters: T.unsafe(nil), locals: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the parameters of the block. + # + # -> (a, b = 1; local) { } + # ^^^^^^^^ + # + # foo do |a, b = 1; local| + # ^^^^^^^^ + # end + sig { returns(::T.nilable(ParametersNode)) } + def parameters; end + + # Represents the local variables of the block. + # + # -> (a, b = 1; local) { } + # ^^^^^ + # + # foo do |a, b = 1; local| + # ^^^^^ + # end + sig { returns(T::Array[BlockLocalVariableNode]) } + def locals; end + + # Represents the opening Location of the block parameters. + # + # -> (a, b = 1; local) { } + # ^ + # + # foo do |a, b = 1; local| + # ^ + # end + sig { returns(::T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Represents the closing Location of the block parameters. + # + # -> (a, b = 1; local) { } + # ^ + # + # foo do |a, b = 1; local| + # ^ + # end + sig { returns(::T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(::T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(::T.nilable(String)) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `break` keyword. + # + # break foo + # ^^^^^^^^^ + class BreakNode < Node + # Initialize a new BreakNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: ::T.nilable(ArgumentsNode), keyword_loc: Location).void } + def initialize(source, node_id, location, flags, arguments, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, arguments: ::T.nilable(ArgumentsNode), keyword_loc: Location).returns(BreakNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The arguments to the break statement, if present. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # break foo + # ^^^ + sig { returns(::T.nilable(ArgumentsNode)) } + def arguments; end + + # The Location of the `break` keyword. + # + # break foo + # ^^^^^ + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator on a call. + # + # foo.bar &&= value + # ^^^^^^^^^^^^^^^^^ + class CallAndWriteNode < Node + # Initialize a new CallAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, message_loc, read_name, write_name, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # 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). + # + # foo.bar &&= value + # ^^^ + sig { returns(::T.nilable(Node)) } + def receiver; end + + # Represents the Location of the call operator. + # + # foo.bar &&= value + # ^ + sig { returns(::T.nilable(Location)) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_call_operator_loc(repository); end + + # Represents the Location of the message. + # + # foo.bar &&= value + # ^^^ + sig { returns(::T.nilable(Location)) } + def message_loc; end + + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_message_loc(repository); end + + # Represents the name of the method being called. + # + # foo.bar &&= value # read_name `:bar` + # ^^^ + sig { returns(Symbol) } + def read_name; end + + # Represents the name of the method being written to. + # + # foo.bar &&= value # write_name `:bar=` + # ^^^ + sig { returns(Symbol) } + def write_name; end + + # Represents the Location of the operator. + # + # foo.bar &&= value + # ^^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Represents the value being assigned. + # + # foo.bar &&= value + # ^^^^^ + sig { returns(Node) } + def value; end + + # Slice the location of call_operator_loc from the source. + sig { returns(::T.nilable(String)) } + def call_operator; end + + # Slice the location of message_loc from the source. + sig { returns(::T.nilable(String)) } + def message; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a method call, in all of the various forms that can take. + # + # foo + # ^^^ + # + # foo() + # ^^^^^ + # + # +foo + # ^^^^ + # + # foo + bar + # ^^^^^^^^^ + # + # foo.bar + # ^^^^^^^ + # + # foo&.bar + # ^^^^^^^^ + class CallNode < Node + # Initialize a new CallNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), name: Symbol, message_loc: ::T.nilable(Location), opening_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), closing_loc: ::T.nilable(Location), equal_loc: ::T.nilable(Location), block: ::T.nilable(::T.any(BlockNode, BlockArgumentNode))).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, name, message_loc, opening_loc, arguments, closing_loc, equal_loc, block); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), name: Symbol, message_loc: ::T.nilable(Location), opening_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), closing_loc: ::T.nilable(Location), equal_loc: ::T.nilable(Location), block: ::T.nilable(::T.any(BlockNode, BlockArgumentNode))).returns(CallNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), name: T.unsafe(nil), message_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), equal_loc: T.unsafe(nil), block: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # 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). + # + # foo.bar + # ^^^ + # + # +foo + # ^^^ + # + # foo + bar + # ^^^ + sig { returns(::T.nilable(Node)) } + def receiver; end + + # Represents the Location of the call operator. + # + # foo.bar + # ^ + # + # foo&.bar + # ^^ + sig { returns(::T.nilable(Location)) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_call_operator_loc(repository); end + + # Represents the name of the method being called. + # + # foo.bar # name `:foo` + # ^^^ + sig { returns(Symbol) } + def name; end + + # Represents the Location of the message. + # + # foo.bar + # ^^^ + sig { returns(::T.nilable(Location)) } + def message_loc; end + + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_message_loc(repository); end + + # Represents the Location of the left parenthesis. + # + # foo(bar) + # ^ + sig { returns(::T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Represents the arguments to the method call. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo(bar) + # ^^^ + sig { returns(::T.nilable(ArgumentsNode)) } + def arguments; end + + # Represents the Location of the right parenthesis. + # + # foo(bar) + # ^ + sig { returns(::T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Represents the Location of the equal sign, in the case that this is an attribute write. + # + # foo.bar = value + # ^ + # + # foo[bar] = value + # ^ + sig { returns(::T.nilable(Location)) } + def equal_loc; end + + # Save the equal_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_equal_loc(repository); end + + # Represents the block that is being passed to the method. + # + # foo { |a| a } + # ^^^^^^^^^ + sig { returns(::T.nilable(::T.any(BlockNode, BlockArgumentNode))) } + def block; end + + # Slice the location of call_operator_loc from the source. + sig { returns(::T.nilable(String)) } + def call_operator; end + + # Slice the location of message_loc from the source. + sig { returns(::T.nilable(String)) } + def message; end + + # Slice the location of opening_loc from the source. + sig { returns(::T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(::T.nilable(String)) } + def closing; end + + # Slice the location of equal_loc from the source. + sig { returns(::T.nilable(String)) } + def equal; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of an assignment operator on a call. + # + # foo.bar += baz + # ^^^^^^^^^^^^^^ + class CallOperatorWriteNode < Node + # Initialize a new CallOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, binary_operator: Symbol, binary_operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, message_loc, read_name, write_name, binary_operator, binary_operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(CallOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), binary_operator: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # The object that the method is being called on. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar += value + # ^^^ + sig { returns(::T.nilable(Node)) } + def receiver; end + + # Represents the Location of the call operator. + # + # foo.bar += value + # ^ + sig { returns(::T.nilable(Location)) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_call_operator_loc(repository); end + + # Represents the Location of the message. + # + # foo.bar += value + # ^^^ + sig { returns(::T.nilable(Location)) } + def message_loc; end + + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_message_loc(repository); end + + # Represents the name of the method being called. + # + # foo.bar += value # read_name `:bar` + # ^^^ + sig { returns(Symbol) } + def read_name; end + + # Represents the name of the method being written to. + # + # foo.bar += value # write_name `:bar=` + # ^^^ + sig { returns(Symbol) } + def write_name; end + + # Represents the binary operator being used. + # + # foo.bar += value # binary_operator `:+` + # ^ + sig { returns(Symbol) } + def binary_operator; end + + # Represents the Location of the binary operator. + # + # foo.bar += value + # ^^ + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Represents the value being assigned. + # + # foo.bar += value + # ^^^^^ + sig { returns(Node) } + def value; end + + # Slice the location of call_operator_loc from the source. + sig { returns(::T.nilable(String)) } + def call_operator; end + + # Slice the location of message_loc from the source. + sig { returns(::T.nilable(String)) } + def message; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator on a call. + # + # foo.bar ||= value + # ^^^^^^^^^^^^^^^^^ + class CallOrWriteNode < Node + # Initialize a new CallOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, message_loc, read_name, write_name, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # The object that the method is being called on. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar ||= value + # ^^^ + sig { returns(::T.nilable(Node)) } + def receiver; end + + # Represents the Location of the call operator. + # + # foo.bar ||= value + # ^ + sig { returns(::T.nilable(Location)) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_call_operator_loc(repository); end + + # Represents the Location of the message. + # + # foo.bar ||= value + # ^^^ + sig { returns(::T.nilable(Location)) } + def message_loc; end + + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_message_loc(repository); end + + # Represents the name of the method being called. + # + # foo.bar ||= value # read_name `:bar` + # ^^^ + sig { returns(Symbol) } + def read_name; end + + # Represents the name of the method being written to. + # + # foo.bar ||= value # write_name `:bar=` + # ^^^ + sig { returns(Symbol) } + def write_name; end + + # Represents the Location of the operator. + # + # foo.bar ||= value + # ^^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Represents the value being assigned. + # + # foo.bar ||= value + # ^^^^^ + sig { returns(Node) } + def value; end + + # Slice the location of call_operator_loc from the source. + sig { returns(::T.nilable(String)) } + def call_operator; end + + # Slice the location of message_loc from the source. + sig { returns(::T.nilable(String)) } + def message; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to a method call. + # + # foo.bar, = 1 + # ^^^^^^^ + # + # begin + # rescue => foo.bar + # ^^^^^^^ + # end + # + # for foo.bar in baz do end + # ^^^^^^^ + class CallTargetNode < Node + # Initialize a new CallTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: Node, call_operator_loc: Location, name: Symbol, message_loc: Location).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, name, message_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: Node, call_operator_loc: Location, name: Symbol, message_loc: Location).returns(CallTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), name: T.unsafe(nil), message_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # The object that the method is being called on. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar = 1 + # ^^^ + sig { returns(Node) } + def receiver; end + + # Represents the Location of the call operator. + # + # foo.bar = 1 + # ^ + sig { returns(Location) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_call_operator_loc(repository); end + + # Represents the name of the method being called. + # + # foo.bar = 1 # name `:foo` + # ^^^ + sig { returns(Symbol) } + def name; end + + # Represents the Location of the message. + # + # foo.bar = 1 + # ^^^ + sig { returns(Location) } + def message_loc; end + + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_message_loc(repository); end + + # Slice the location of call_operator_loc from the source. + sig { returns(String) } + def call_operator; end + + # Slice the location of message_loc from the source. + sig { returns(String) } + def message; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to a local variable in pattern matching. + # + # foo => [bar => baz] + # ^^^^^^^^^^ + class CapturePatternNode < Node + # Initialize a new CapturePatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Node, target: LocalVariableTargetNode, operator_loc: Location).void } + def initialize(source, node_id, location, flags, value, target, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, value: Node, target: LocalVariableTargetNode, operator_loc: Location).returns(CapturePatternNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the value to capture. + # + # foo => bar + # ^^^ + sig { returns(Node) } + def value; end + + # Represents the target of the capture. + # + # foo => bar + # ^^^ + sig { returns(LocalVariableTargetNode) } + def target; end + + # Represents the Location of the `=>` operator. + # + # foo => bar + # ^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of a case statement for pattern matching. + # + # case true + # in false + # end + # ^^^^^^^^^ + class CaseMatchNode < Node + # Initialize a new CaseMatchNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: ::T.nilable(Node), conditions: T::Array[InNode], else_clause: ::T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).void } + def initialize(source, node_id, location, flags, predicate, conditions, else_clause, case_keyword_loc, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, predicate: ::T.nilable(Node), conditions: T::Array[InNode], else_clause: ::T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseMatchNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), predicate: T.unsafe(nil), conditions: T.unsafe(nil), else_clause: T.unsafe(nil), case_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the predicate of the case match. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # case true; in false; end + # ^^^^ + sig { returns(::T.nilable(Node)) } + def predicate; end + + # Represents the conditions of the case match. + # + # case true; in false; end + # ^^^^^^^^ + sig { returns(T::Array[InNode]) } + def conditions; end + + # Represents the else clause of the case match. + # + # case true; in false; else; end + # ^^^^^^^^^ + sig { returns(::T.nilable(ElseNode)) } + def else_clause; end + + # Represents the Location of the `case` keyword. + # + # case true; in false; end + # ^^^^ + sig { returns(Location) } + def case_keyword_loc; end + + # Save the case_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_case_keyword_loc(repository); end + + # Represents the Location of the `end` keyword. + # + # case true; in false; end + # ^^^ + sig { returns(Location) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_end_keyword_loc(repository); end + + # Slice the location of case_keyword_loc from the source. + sig { returns(String) } + def case_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(String) } + def end_keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of a case statement. + # + # case true + # when false + # end + # ^^^^^^^^^^ + class CaseNode < Node + # Initialize a new CaseNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: ::T.nilable(Node), conditions: T::Array[WhenNode], else_clause: ::T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).void } + def initialize(source, node_id, location, flags, predicate, conditions, else_clause, case_keyword_loc, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, predicate: ::T.nilable(Node), conditions: T::Array[WhenNode], else_clause: ::T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), predicate: T.unsafe(nil), conditions: T.unsafe(nil), else_clause: T.unsafe(nil), case_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the predicate of the case statement. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # case true; when false; end + # ^^^^ + sig { returns(::T.nilable(Node)) } + def predicate; end + + # Represents the conditions of the case statement. + # + # case true; when false; end + # ^^^^^^^^^^ + sig { returns(T::Array[WhenNode]) } + def conditions; end + + # Represents the else clause of the case statement. + # + # case true; when false; else; end + # ^^^^^^^^^ + sig { returns(::T.nilable(ElseNode)) } + def else_clause; end + + # Represents the Location of the `case` keyword. + # + # case true; when false; end + # ^^^^ + sig { returns(Location) } + def case_keyword_loc; end + + # Save the case_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_case_keyword_loc(repository); end + + # Represents the Location of the `end` keyword. + # + # case true; when false; end + # ^^^ + sig { returns(Location) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_end_keyword_loc(repository); end + + # Slice the location of case_keyword_loc from the source. + sig { returns(String) } + def case_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(String) } + def end_keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a class declaration involving the `class` keyword. + # + # class Foo end + # ^^^^^^^^^^^^^ + class ClassNode < Node + # Initialize a new ClassNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, constant_path: ::T.any(ConstantReadNode, ConstantPathNode, CallNode), inheritance_operator_loc: ::T.nilable(Location), superclass: ::T.nilable(Node), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).void } + def initialize(source, node_id, location, flags, locals, class_keyword_loc, constant_path, inheritance_operator_loc, superclass, body, end_keyword_loc, name); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, constant_path: ::T.any(ConstantReadNode, ConstantPathNode, CallNode), inheritance_operator_loc: ::T.nilable(Location), superclass: ::T.nilable(Node), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ClassNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), class_keyword_loc: T.unsafe(nil), constant_path: T.unsafe(nil), inheritance_operator_loc: T.unsafe(nil), superclass: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `locals` attribute. + sig { returns(T::Array[Symbol]) } + def locals; end + + # Represents the Location of the `class` keyword. + # + # class Foo end + # ^^^^^ + sig { returns(Location) } + def class_keyword_loc; end + + # Save the class_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_class_keyword_loc(repository); end + + # Returns the `constant_path` attribute. + sig { returns(::T.any(ConstantReadNode, ConstantPathNode, CallNode)) } + def constant_path; end + + # Represents the Location of the `<` operator. + # + # class Foo < Bar + # ^ + sig { returns(::T.nilable(Location)) } + def inheritance_operator_loc; end + + # Save the inheritance_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_inheritance_operator_loc(repository); end + + # Represents the superclass of the class. + # + # class Foo < Bar + # ^^^ + sig { returns(::T.nilable(Node)) } + def superclass; end + + # Represents the body of the class. + # + # class Foo; bar; end + # ^^^ + sig { returns(::T.nilable(::T.any(StatementsNode, BeginNode))) } + def body; end + + # Represents the Location of the `end` keyword. + # + # class Foo end + # ^^^ + sig { returns(Location) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_end_keyword_loc(repository); end + + # The name of the class. + # + # class Foo end # name `:Foo` + sig { returns(Symbol) } + def name; end + + # Slice the location of class_keyword_loc from the source. + sig { returns(String) } + def class_keyword; end + + # Slice the location of inheritance_operator_loc from the source. + sig { returns(::T.nilable(String)) } + def inheritance_operator; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(String) } + def end_keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator for assignment to a class variable. + # + # @@target &&= value + # ^^^^^^^^^^^^^^^^^^ + class ClassVariableAndWriteNode < Node + # Initialize a new ClassVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ClassVariableAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @@target &&= value # name `:@@target` + # ^^^^^^^^ + sig { returns(Symbol) } + def name; end + + # Represents the Location of the variable name. + # + # @@target &&= value + # ^^^^^^^^ + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Represents the Location of the `&&=` operator. + # + # @@target &&= value + # ^^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Represents the value being assigned. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # @@target &&= value + # ^^^^^ + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to a class variable using an operator that isn't `=`. + # + # @@target += value + # ^^^^^^^^^^^^^^^^^ + class ClassVariableOperatorWriteNode < Node + # Initialize a new ClassVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).void } + def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ClassVariableOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `binary_operator_loc`. + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `binary_operator` attribute. + sig { returns(Symbol) } + def binary_operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator for assignment to a class variable. + # + # @@target ||= value + # ^^^^^^^^^^^^^^^^^^ + class ClassVariableOrWriteNode < Node + # Initialize a new ClassVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ClassVariableOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents referencing a class variable. + # + # @@foo + # ^^^^^ + class ClassVariableReadNode < Node + # Initialize a new ClassVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ClassVariableReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @@abc # name `:@@abc` + # + # @@_test # name `:@@_test` + sig { returns(Symbol) } + def name; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a class variable in a context that doesn't have an explicit value. + # + # @@foo, @@bar = baz + # ^^^^^ ^^^^^ + class ClassVariableTargetNode < Node + # Initialize a new ClassVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ClassVariableTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a class variable. + # + # @@foo = 1 + # ^^^^^^^^^ + class ClassVariableWriteNode < Node + # Initialize a new ClassVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(ClassVariableWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @@abc = 123 # name `@@abc` + # + # @@_test = :test # name `@@_test` + sig { returns(Symbol) } + def name; end + + # The Location of the variable name. + # + # @@foo = :bar + # ^^^^^ + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # 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). + # + # @@foo = :bar + # ^^^^ + # + # @@_xyz = 123 + # ^^^ + sig { returns(Node) } + def value; end + + # The Location of the `=` operator. + # + # @@foo = :bar + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator for assignment to a constant. + # + # Target &&= value + # ^^^^^^^^^^^^^^^^ + class ConstantAndWriteNode < Node + # Initialize a new ConstantAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ConstantAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to a constant using an operator that isn't `=`. + # + # Target += value + # ^^^^^^^^^^^^^^^ + class ConstantOperatorWriteNode < Node + # Initialize a new ConstantOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).void } + def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ConstantOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `binary_operator_loc`. + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `binary_operator` attribute. + sig { returns(Symbol) } + def binary_operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator for assignment to a constant. + # + # Target ||= value + # ^^^^^^^^^^^^^^^^ + class ConstantOrWriteNode < Node + # Initialize a new ConstantOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ConstantOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator for assignment to a constant path. + # + # Parent::Child &&= value + # ^^^^^^^^^^^^^^^^^^^^^^^ + class ConstantPathAndWriteNode < Node + # Initialize a new ConstantPathAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, target, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `target` attribute. + sig { returns(ConstantPathNode) } + def target; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents accessing a constant through a path of `::` operators. + # + # Foo::Bar + # ^^^^^^^^ + class ConstantPathNode < Node + # Initialize a new ConstantPathNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: ::T.nilable(Node), name: ::T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).void } + def initialize(source, node_id, location, flags, parent, name, delimiter_loc, name_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, parent: ::T.nilable(Node), name: ::T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parent: T.unsafe(nil), name: T.unsafe(nil), delimiter_loc: T.unsafe(nil), name_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # 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. + # + # Foo::Bar + # ^^^ + # + # self::Test + # ^^^^ + # + # a.b::C + # ^^^ + sig { returns(::T.nilable(Node)) } + def parent; end + + # The name of the constant being accessed. This could be `nil` in the event of a syntax error. + sig { returns(::T.nilable(Symbol)) } + def name; end + + # The Location of the `::` delimiter. + # + # ::Foo + # ^^ + # + # One::Two + # ^^ + sig { returns(Location) } + def delimiter_loc; end + + # Save the delimiter_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_delimiter_loc(repository); end + + # The Location of the name of the constant. + # + # ::Foo + # ^^^ + # + # One::Two + # ^^^ + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Slice the location of delimiter_loc from the source. + sig { returns(String) } + def delimiter; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to a constant path using an operator that isn't `=`. + # + # Parent::Child += value + # ^^^^^^^^^^^^^^^^^^^^^^ + class ConstantPathOperatorWriteNode < Node + # Initialize a new ConstantPathOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, binary_operator_loc: Location, value: Node, binary_operator: Symbol).void } + def initialize(source, node_id, location, flags, target, binary_operator_loc, value, binary_operator); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ConstantPathOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `target` attribute. + sig { returns(ConstantPathNode) } + def target; end + + # Returns the Location represented by `binary_operator_loc`. + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `binary_operator` attribute. + sig { returns(Symbol) } + def binary_operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator for assignment to a constant path. + # + # Parent::Child ||= value + # ^^^^^^^^^^^^^^^^^^^^^^^ + class ConstantPathOrWriteNode < Node + # Initialize a new ConstantPathOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, target, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `target` attribute. + sig { returns(ConstantPathNode) } + def target; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a constant path in a context that doesn't have an explicit value. + # + # Foo::Foo, Bar::Bar = baz + # ^^^^^^^^ ^^^^^^^^ + class ConstantPathTargetNode < Node + # Initialize a new ConstantPathTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: ::T.nilable(Node), name: ::T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).void } + def initialize(source, node_id, location, flags, parent, name, delimiter_loc, name_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, parent: ::T.nilable(Node), name: ::T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parent: T.unsafe(nil), name: T.unsafe(nil), delimiter_loc: T.unsafe(nil), name_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `parent` attribute. + sig { returns(::T.nilable(Node)) } + def parent; end + + # Returns the `name` attribute. + sig { returns(::T.nilable(Symbol)) } + def name; end + + # Returns the Location represented by `delimiter_loc`. + sig { returns(Location) } + def delimiter_loc; end + + # Save the delimiter_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_delimiter_loc(repository); end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Slice the location of delimiter_loc from the source. + sig { returns(String) } + def delimiter; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a constant path. + # + # ::Foo = 1 + # ^^^^^^^^^ + # + # Foo::Bar = 1 + # ^^^^^^^^^^^^ + # + # ::Foo::Bar = 1 + # ^^^^^^^^^^^^^^ + class ConstantPathWriteNode < Node + # Initialize a new ConstantPathWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, target, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # A node representing the constant path being written to. + # + # Foo::Bar = 1 + # ^^^^^^^^ + # + # ::Foo = :abc + # ^^^^^ + sig { returns(ConstantPathNode) } + def target; end + + # The Location of the `=` operator. + # + # ::ABC = 123 + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # 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). + # + # FOO::BAR = :abc + # ^^^^ + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents referencing a constant. + # + # Foo + # ^^^ + class ConstantReadNode < Node + # Initialize a new ConstantReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ConstantReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the [constant](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#constants). + # + # X # name `:X` + # + # SOME_CONSTANT # name `:SOME_CONSTANT` + sig { returns(Symbol) } + def name; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a constant in a context that doesn't have an explicit value. + # + # Foo, Bar = baz + # ^^^ ^^^ + class ConstantTargetNode < Node + # Initialize a new ConstantTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ConstantTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a constant. + # + # Foo = 1 + # ^^^^^^^ + class ConstantWriteNode < Node + # Initialize a new ConstantWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(ConstantWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the [constant](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#constants). + # + # Foo = :bar # name `:Foo` + # + # XYZ = 1 # name `:XYZ` + sig { returns(Symbol) } + def name; end + + # The Location of the constant name. + # + # FOO = 1 + # ^^^ + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # 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). + # + # FOO = :bar + # ^^^^ + # + # MyClass = Class.new + # ^^^^^^^^^ + sig { returns(Node) } + def value; end + + # The Location of the `=` operator. + # + # FOO = :bar + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a method definition. + # + # def method + # end + # ^^^^^^^^^^ + class DefNode < Node + # Initialize a new DefNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, receiver: ::T.nilable(Node), parameters: ::T.nilable(ParametersNode), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), locals: T::Array[Symbol], def_keyword_loc: Location, operator_loc: ::T.nilable(Location), lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location), equal_loc: ::T.nilable(Location), end_keyword_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, name, name_loc, receiver, parameters, body, locals, def_keyword_loc, operator_loc, lparen_loc, rparen_loc, equal_loc, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, receiver: ::T.nilable(Node), parameters: ::T.nilable(ParametersNode), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), locals: T::Array[Symbol], def_keyword_loc: Location, operator_loc: ::T.nilable(Location), lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location), equal_loc: ::T.nilable(Location), end_keyword_loc: ::T.nilable(Location)).returns(DefNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), receiver: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil), locals: T.unsafe(nil), def_keyword_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil), equal_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the `receiver` attribute. + sig { returns(::T.nilable(Node)) } + def receiver; end + + # Returns the `parameters` attribute. + sig { returns(::T.nilable(ParametersNode)) } + def parameters; end + + # Returns the `body` attribute. + sig { returns(::T.nilable(::T.any(StatementsNode, BeginNode))) } + def body; end + + # Returns the `locals` attribute. + sig { returns(T::Array[Symbol]) } + def locals; end + + # Returns the Location represented by `def_keyword_loc`. + sig { returns(Location) } + def def_keyword_loc; end + + # Save the def_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_def_keyword_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(::T.nilable(Location)) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_operator_loc(repository); end + + # Returns the Location represented by `lparen_loc`. + sig { returns(::T.nilable(Location)) } + def lparen_loc; end + + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_lparen_loc(repository); end + + # Returns the Location represented by `rparen_loc`. + sig { returns(::T.nilable(Location)) } + def rparen_loc; end + + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_rparen_loc(repository); end + + # Returns the Location represented by `equal_loc`. + sig { returns(::T.nilable(Location)) } + def equal_loc; end + + # Save the equal_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_equal_loc(repository); end + + # Returns the Location represented by `end_keyword_loc`. + sig { returns(::T.nilable(Location)) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_end_keyword_loc(repository); end + + # Slice the location of def_keyword_loc from the source. + sig { returns(String) } + def def_keyword; end + + # Slice the location of operator_loc from the source. + sig { returns(::T.nilable(String)) } + def operator; end + + # Slice the location of lparen_loc from the source. + sig { returns(::T.nilable(String)) } + def lparen; end + + # Slice the location of rparen_loc from the source. + sig { returns(::T.nilable(String)) } + def rparen; end + + # Slice the location of equal_loc from the source. + sig { returns(::T.nilable(String)) } + def equal; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(::T.nilable(String)) } + def end_keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `defined?` keyword. + # + # defined?(a) + # ^^^^^^^^^^^ + class DefinedNode < Node + # Initialize a new DefinedNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lparen_loc: ::T.nilable(Location), value: Node, rparen_loc: ::T.nilable(Location), keyword_loc: Location).void } + def initialize(source, node_id, location, flags, lparen_loc, value, rparen_loc, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, lparen_loc: ::T.nilable(Location), value: Node, rparen_loc: ::T.nilable(Location), keyword_loc: Location).returns(DefinedNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lparen_loc: T.unsafe(nil), value: T.unsafe(nil), rparen_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `lparen_loc`. + sig { returns(::T.nilable(Location)) } + def lparen_loc; end + + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_lparen_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the Location represented by `rparen_loc`. + sig { returns(::T.nilable(Location)) } + def rparen_loc; end + + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_rparen_loc(repository); end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of lparen_loc from the source. + sig { returns(::T.nilable(String)) } + def lparen; end + + # Slice the location of rparen_loc from the source. + sig { returns(::T.nilable(String)) } + def rparen; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an `else` clause in a `case`, `if`, or `unless` statement. + # + # if a then b else c end + # ^^^^^^^^^^ + class ElseNode < Node + # Initialize a new ElseNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, else_keyword_loc: Location, statements: ::T.nilable(StatementsNode), end_keyword_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, else_keyword_loc, statements, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, else_keyword_loc: Location, statements: ::T.nilable(StatementsNode), end_keyword_loc: ::T.nilable(Location)).returns(ElseNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), else_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `else_keyword_loc`. + sig { returns(Location) } + def else_keyword_loc; end + + # Save the else_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_else_keyword_loc(repository); end + + # Returns the `statements` attribute. + sig { returns(::T.nilable(StatementsNode)) } + def statements; end + + # Returns the Location represented by `end_keyword_loc`. + sig { returns(::T.nilable(Location)) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_end_keyword_loc(repository); end + + # Slice the location of else_keyword_loc from the source. + sig { returns(String) } + def else_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(::T.nilable(String)) } + def end_keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an interpolated set of statements. + # + # "foo #{bar}" + # ^^^^^^ + class EmbeddedStatementsNode < Node + # Initialize a new EmbeddedStatementsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, statements: ::T.nilable(StatementsNode), closing_loc: Location).void } + def initialize(source, node_id, location, flags, opening_loc, statements, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, statements: ::T.nilable(StatementsNode), closing_loc: Location).returns(EmbeddedStatementsNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), statements: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `statements` attribute. + sig { returns(::T.nilable(StatementsNode)) } + def statements; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an interpolated variable. + # + # "foo #@bar" + # ^^^^^ + class EmbeddedVariableNode < Node + # Initialize a new EmbeddedVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, variable: ::T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)).void } + def initialize(source, node_id, location, flags, operator_loc, variable); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, variable: ::T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)).returns(EmbeddedVariableNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), variable: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `variable` attribute. + sig { returns(::T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)) } + def variable; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an `ensure` clause in a `begin` statement. + # + # begin + # foo + # ensure + # ^^^^^^ + # bar + # end + class EnsureNode < Node + # Initialize a new EnsureNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, ensure_keyword_loc: Location, statements: ::T.nilable(StatementsNode), end_keyword_loc: Location).void } + def initialize(source, node_id, location, flags, ensure_keyword_loc, statements, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, ensure_keyword_loc: Location, statements: ::T.nilable(StatementsNode), end_keyword_loc: Location).returns(EnsureNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), ensure_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `ensure_keyword_loc`. + sig { returns(Location) } + def ensure_keyword_loc; end + + # Save the ensure_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_ensure_keyword_loc(repository); end + + # Returns the `statements` attribute. + sig { returns(::T.nilable(StatementsNode)) } + def statements; end + + # Returns the Location represented by `end_keyword_loc`. + sig { returns(Location) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_end_keyword_loc(repository); end + + # Slice the location of ensure_keyword_loc from the source. + sig { returns(String) } + def ensure_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(String) } + def end_keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the literal `false` keyword. + # + # false + # ^^^^^ + class FalseNode < Node + # Initialize a new FalseNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(FalseNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a find pattern in pattern matching. + # + # foo in *bar, baz, *qux + # ^^^^^^^^^^^^^^^ + # + # foo in [*bar, baz, *qux] + # ^^^^^^^^^^^^^^^^^ + # + # foo in Foo(*bar, baz, *qux) + # ^^^^^^^^^^^^^^^^^^^^ + # + # foo => *bar, baz, *qux + # ^^^^^^^^^^^^^^^ + class FindPatternNode < Node + # Initialize a new FindPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), left: SplatNode, requireds: T::Array[Node], right: ::T.any(SplatNode, MissingNode), opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, constant, left, requireds, right, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), left: SplatNode, requireds: T::Array[Node], right: ::T.any(SplatNode, MissingNode), opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(FindPatternNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), left: T.unsafe(nil), requireds: T.unsafe(nil), right: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the optional constant preceding the pattern + # + # foo in Foo(*bar, baz, *qux) + # ^^^ + sig { returns(::T.nilable(::T.any(ConstantPathNode, ConstantReadNode))) } + def constant; end + + # Represents the first wildcard node in the pattern. + # + # foo in *bar, baz, *qux + # ^^^^ + # + # foo in Foo(*bar, baz, *qux) + # ^^^^ + sig { returns(SplatNode) } + def left; end + + # Represents the nodes in between the wildcards. + # + # foo in *bar, baz, *qux + # ^^^ + # + # foo in Foo(*bar, baz, 1, *qux) + # ^^^^^^ + sig { returns(T::Array[Node]) } + def requireds; end + + # Represents the second wildcard node in the pattern. + # + # foo in *bar, baz, *qux + # ^^^^ + # + # foo in Foo(*bar, baz, *qux) + # ^^^^ + sig { returns(::T.any(SplatNode, MissingNode)) } + def right; end + + # The Location of the opening brace. + # + # foo in [*bar, baz, *qux] + # ^ + # + # foo in Foo(*bar, baz, *qux) + # ^ + sig { returns(::T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # The Location of the closing brace. + # + # foo in [*bar, baz, *qux] + # ^ + # + # foo in Foo(*bar, baz, *qux) + # ^ + sig { returns(::T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(::T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(::T.nilable(String)) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `..` or `...` operators to create flip flops. + # + # baz if foo .. bar + # ^^^^^^^^^^ + class FlipFlopNode < Node + # Initialize a new FlipFlopNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: ::T.nilable(Node), right: ::T.nilable(Node), operator_loc: Location).void } + def initialize(source, node_id, location, flags, left, right, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, left: ::T.nilable(Node), right: ::T.nilable(Node), operator_loc: Location).returns(FlipFlopNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # ... operator + sig { returns(T::Boolean) } + def exclude_end?; end + + # Returns the `left` attribute. + sig { returns(::T.nilable(Node)) } + def left; end + + # Returns the `right` attribute. + sig { returns(::T.nilable(Node)) } + def right; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a floating point number literal. + # + # 1.0 + # ^^^ + class FloatNode < Node + # Initialize a new FloatNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Float).void } + def initialize(source, node_id, location, flags, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, value: Float).returns(FloatNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The value of the floating point number as a Float. + sig { returns(Float) } + def value; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `for` keyword. + # + # for i in a end + # ^^^^^^^^^^^^^^ + class ForNode < Node + # Initialize a new ForNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, index: ::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode), collection: Node, statements: ::T.nilable(StatementsNode), for_keyword_loc: Location, in_keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), end_keyword_loc: Location).void } + def initialize(source, node_id, location, flags, index, collection, statements, for_keyword_loc, in_keyword_loc, do_keyword_loc, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, index: ::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode), collection: Node, statements: ::T.nilable(StatementsNode), for_keyword_loc: Location, in_keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), end_keyword_loc: Location).returns(ForNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), index: T.unsafe(nil), collection: T.unsafe(nil), statements: T.unsafe(nil), for_keyword_loc: T.unsafe(nil), in_keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The index expression for `for` loops. + # + # for i in a end + # ^ + sig { returns(::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)) } + def index; end + + # The collection to iterate over. + # + # for i in a end + # ^ + sig { returns(Node) } + def collection; end + + # Represents the body of statements to execute for each iteration of the loop. + # + # for i in a + # foo(i) + # ^^^^^^ + # end + sig { returns(::T.nilable(StatementsNode)) } + def statements; end + + # The Location of the `for` keyword. + # + # for i in a end + # ^^^ + sig { returns(Location) } + def for_keyword_loc; end + + # Save the for_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_for_keyword_loc(repository); end + + # The Location of the `in` keyword. + # + # for i in a end + # ^^ + sig { returns(Location) } + def in_keyword_loc; end + + # Save the in_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_in_keyword_loc(repository); end + + # The Location of the `do` keyword, if present. + # + # for i in a do end + # ^^ + sig { returns(::T.nilable(Location)) } + def do_keyword_loc; end + + # Save the do_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_do_keyword_loc(repository); end + + # The Location of the `end` keyword. + # + # for i in a end + # ^^^ + sig { returns(Location) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_end_keyword_loc(repository); end + + # Slice the location of for_keyword_loc from the source. + sig { returns(String) } + def for_keyword; end + + # Slice the location of in_keyword_loc from the source. + sig { returns(String) } + def in_keyword; end + + # Slice the location of do_keyword_loc from the source. + sig { returns(::T.nilable(String)) } + def do_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(String) } + def end_keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents forwarding all arguments to this method to another method. + # + # def foo(...) + # bar(...) + # ^^^ + # end + class ForwardingArgumentsNode < Node + # Initialize a new ForwardingArgumentsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(ForwardingArgumentsNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the forwarding parameter in a method, block, or lambda declaration. + # + # def foo(...) + # ^^^ + # end + class ForwardingParameterNode < Node + # Initialize a new ForwardingParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(ForwardingParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `super` keyword without parentheses or arguments, but which might have a block. + # + # super + # ^^^^^ + # + # super { 123 } + # ^^^^^^^^^^^^^ + # + # If it has any other arguments, it would be a `SuperNode` instead. + class ForwardingSuperNode < Node + # Initialize a new ForwardingSuperNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, block: ::T.nilable(BlockNode)).void } + def initialize(source, node_id, location, flags, block); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, block: ::T.nilable(BlockNode)).returns(ForwardingSuperNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), block: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # All other arguments are forwarded as normal, except the original block is replaced with the new block. + sig { returns(::T.nilable(BlockNode)) } + def block; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator for assignment to a global variable. + # + # $target &&= value + # ^^^^^^^^^^^^^^^^^ + class GlobalVariableAndWriteNode < Node + # Initialize a new GlobalVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(GlobalVariableAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to a global variable using an operator that isn't `=`. + # + # $target += value + # ^^^^^^^^^^^^^^^^ + class GlobalVariableOperatorWriteNode < Node + # Initialize a new GlobalVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).void } + def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(GlobalVariableOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `binary_operator_loc`. + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `binary_operator` attribute. + sig { returns(Symbol) } + def binary_operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator for assignment to a global variable. + # + # $target ||= value + # ^^^^^^^^^^^^^^^^^ + class GlobalVariableOrWriteNode < Node + # Initialize a new GlobalVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(GlobalVariableOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents referencing a global variable. + # + # $foo + # ^^^^ + class GlobalVariableReadNode < Node + # Initialize a new GlobalVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(GlobalVariableReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the global variable, which is a `$` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). Alternatively, it can be one of the special global variables designated by a symbol. + # + # $foo # name `:$foo` + # + # $_Test # name `:$_Test` + sig { returns(Symbol) } + def name; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a global variable in a context that doesn't have an explicit value. + # + # $foo, $bar = baz + # ^^^^ ^^^^ + class GlobalVariableTargetNode < Node + # Initialize a new GlobalVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(GlobalVariableTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a global variable. + # + # $foo = 1 + # ^^^^^^^^ + class GlobalVariableWriteNode < Node + # Initialize a new GlobalVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(GlobalVariableWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the global variable, which is a `$` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). Alternatively, it can be one of the special global variables designated by a symbol. + # + # $foo = :bar # name `:$foo` + # + # $_Test = 123 # name `:$_Test` + sig { returns(Symbol) } + def name; end + + # The Location of the global variable's name. + # + # $foo = :bar + # ^^^^ + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # 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). + # + # $foo = :bar + # ^^^^ + # + # $-xyz = 123 + # ^^^ + sig { returns(Node) } + def value; end + + # The Location of the `=` operator. + # + # $foo = :bar + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a hash literal. + # + # { a => b } + # ^^^^^^^^^^ + class HashNode < Node + # Initialize a new HashNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, elements: T::Array[::T.any(AssocNode, AssocSplatNode)], closing_loc: Location).void } + def initialize(source, node_id, location, flags, opening_loc, elements, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, elements: T::Array[::T.any(AssocNode, AssocSplatNode)], closing_loc: Location).returns(HashNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), elements: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The Location of the opening brace. + # + # { a => b } + # ^ + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # The elements of the hash. These can be either `AssocNode`s or `AssocSplatNode`s. + # + # { a: b } + # ^^^^ + # + # { **foo } + # ^^^^^ + sig { returns(T::Array[::T.any(AssocNode, AssocSplatNode)]) } + def elements; end + + # The Location of the closing brace. + # + # { a => b } + # ^ + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a hash pattern in pattern matching. + # + # foo => { a: 1, b: 2 } + # ^^^^^^^^^^^^^^ + # + # foo => { a: 1, b: 2, **c } + # ^^^^^^^^^^^^^^^^^^^ + # + # foo => Bar[a: 1, b: 2] + # ^^^^^^^^^^^^^^^ + # + # foo in { a: 1, b: 2 } + # ^^^^^^^^^^^^^^ + class HashPatternNode < Node + # Initialize a new HashPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), elements: T::Array[AssocNode], rest: ::T.nilable(::T.any(AssocSplatNode, NoKeywordsParameterNode)), opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, constant, elements, rest, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), elements: T::Array[AssocNode], rest: ::T.nilable(::T.any(AssocSplatNode, NoKeywordsParameterNode)), opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(HashPatternNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), elements: T.unsafe(nil), rest: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the optional constant preceding the Hash. + # + # foo => Bar[a: 1, b: 2] + # ^^^ + # + # foo => Bar::Baz[a: 1, b: 2] + # ^^^^^^^^ + sig { returns(::T.nilable(::T.any(ConstantPathNode, ConstantReadNode))) } + def constant; end + + # Represents the explicit named hash keys and values. + # + # foo => { a: 1, b:, ** } + # ^^^^^^^^ + sig { returns(T::Array[AssocNode]) } + def elements; end + + # Represents the rest of the Hash keys and values. This can be named, unnamed, or explicitly forbidden via `**nil`, this last one results in a `NoKeywordsParameterNode`. + # + # foo => { a: 1, b:, **c } + # ^^^ + # + # foo => { a: 1, b:, ** } + # ^^ + # + # foo => { a: 1, b:, **nil } + # ^^^^^ + sig { returns(::T.nilable(::T.any(AssocSplatNode, NoKeywordsParameterNode))) } + def rest; end + + # The Location of the opening brace. + # + # foo => { a: 1 } + # ^ + # + # foo => Bar[a: 1] + # ^ + sig { returns(::T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # The Location of the closing brace. + # + # foo => { a: 1 } + # ^ + # + # foo => Bar[a: 1] + # ^ + sig { returns(::T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(::T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(::T.nilable(String)) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `if` keyword, either in the block form or the modifier form, or a ternary expression. + # + # bar if foo + # ^^^^^^^^^^ + # + # if foo then bar end + # ^^^^^^^^^^^^^^^^^^^ + # + # foo ? bar : baz + # ^^^^^^^^^^^^^^^ + class IfNode < Node + # Initialize a new IfNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, if_keyword_loc: ::T.nilable(Location), predicate: Node, then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), subsequent: ::T.nilable(::T.any(ElseNode, IfNode)), end_keyword_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, if_keyword_loc, predicate, then_keyword_loc, statements, subsequent, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, if_keyword_loc: ::T.nilable(Location), predicate: Node, then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), subsequent: ::T.nilable(::T.any(ElseNode, IfNode)), end_keyword_loc: ::T.nilable(Location)).returns(IfNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), if_keyword_loc: T.unsafe(nil), predicate: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), subsequent: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The Location of the `if` keyword if present. + # + # bar if foo + # ^^ + # + # The `if_keyword_loc` field will be `nil` when the `IfNode` represents a ternary expression. + sig { returns(::T.nilable(Location)) } + def if_keyword_loc; end + + # Save the if_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_if_keyword_loc(repository); end + + # The node for the condition the `IfNode` is testing. + # + # if foo + # ^^^ + # bar + # end + # + # bar if foo + # ^^^ + # + # foo ? bar : baz + # ^^^ + sig { returns(Node) } + def predicate; end + + # The Location of the `then` keyword (if present) or the `?` in a ternary expression, `nil` otherwise. + # + # if foo then bar end + # ^^^^ + # + # a ? b : c + # ^ + sig { returns(::T.nilable(Location)) } + def then_keyword_loc; end + + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_then_keyword_loc(repository); end + + # Represents the body of statements that will be executed when the predicate is evaluated as truthy. Will be `nil` when no body is provided. + # + # if foo + # bar + # ^^^ + # baz + # ^^^ + # end + sig { returns(::T.nilable(StatementsNode)) } + def statements; end + + # Represents an `ElseNode` or an `IfNode` when there is an `else` or an `elsif` in the `if` statement. + # + # if foo + # bar + # elsif baz + # ^^^^^^^^^ + # qux + # ^^^ + # end + # ^^^ + # + # if foo then bar else baz end + # ^^^^^^^^^^^^ + sig { returns(::T.nilable(::T.any(ElseNode, IfNode))) } + def subsequent; end + + # The Location of the `end` keyword if present, `nil` otherwise. + # + # if foo + # bar + # end + # ^^^ + sig { returns(::T.nilable(Location)) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_end_keyword_loc(repository); end + + # Slice the location of if_keyword_loc from the source. + sig { returns(::T.nilable(String)) } + def if_keyword; end + + # Slice the location of then_keyword_loc from the source. + sig { returns(::T.nilable(String)) } + def then_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(::T.nilable(String)) } + def end_keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an imaginary number literal. + # + # 1.0i + # ^^^^ + class ImaginaryNode < Node + # Initialize a new ImaginaryNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, numeric: ::T.any(FloatNode, IntegerNode, RationalNode)).void } + def initialize(source, node_id, location, flags, numeric); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, numeric: ::T.any(FloatNode, IntegerNode, RationalNode)).returns(ImaginaryNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), numeric: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `numeric` attribute. + sig { returns(::T.any(FloatNode, IntegerNode, RationalNode)) } + def numeric; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a node that is implicitly being added to the tree but doesn't correspond directly to a node in the source. + # + # { foo: } + # ^^^^ + # + # { Foo: } + # ^^^^ + # + # foo in { bar: } + # ^^^^ + class ImplicitNode < Node + # Initialize a new ImplicitNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: ::T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)).void } + def initialize(source, node_id, location, flags, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, value: ::T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)).returns(ImplicitNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `value` attribute. + sig { returns(::T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)) } + def value; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents using a trailing comma to indicate an implicit rest parameter. + # + # foo { |bar,| } + # ^ + # + # foo in [bar,] + # ^ + # + # for foo, in bar do end + # ^ + # + # foo, = bar + # ^ + class ImplicitRestNode < Node + # Initialize a new ImplicitRestNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(ImplicitRestNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `in` keyword in a case statement. + # + # case a; in b then c end + # ^^^^^^^^^^^ + class InNode < Node + # Initialize a new InNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, pattern: Node, statements: ::T.nilable(StatementsNode), in_loc: Location, then_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, pattern, statements, in_loc, then_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, pattern: Node, statements: ::T.nilable(StatementsNode), in_loc: Location, then_loc: ::T.nilable(Location)).returns(InNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), pattern: T.unsafe(nil), statements: T.unsafe(nil), in_loc: T.unsafe(nil), then_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `pattern` attribute. + sig { returns(Node) } + def pattern; end + + # Returns the `statements` attribute. + sig { returns(::T.nilable(StatementsNode)) } + def statements; end + + # Returns the Location represented by `in_loc`. + sig { returns(Location) } + def in_loc; end + + # Save the in_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_in_loc(repository); end + + # Returns the Location represented by `then_loc`. + sig { returns(::T.nilable(Location)) } + def then_loc; end + + # Save the then_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_then_loc(repository); end + + # Slice the location of in_loc from the source. + sig { returns(String) } + def in; end + + # Slice the location of then_loc from the source. + sig { returns(::T.nilable(String)) } + def then; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator on a call to the `[]` method. + # + # foo.bar[baz] &&= value + # ^^^^^^^^^^^^^^^^^^^^^^ + class IndexAndWriteNode < Node + # Initialize a new IndexAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # Returns the `receiver` attribute. + sig { returns(::T.nilable(Node)) } + def receiver; end + + # Returns the Location represented by `call_operator_loc`. + sig { returns(::T.nilable(Location)) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_call_operator_loc(repository); end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `arguments` attribute. + sig { returns(::T.nilable(ArgumentsNode)) } + def arguments; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `block` attribute. + sig { returns(::T.nilable(BlockArgumentNode)) } + def block; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of call_operator_loc from the source. + sig { returns(::T.nilable(String)) } + def call_operator; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of an assignment operator on a call to `[]`. + # + # foo.bar[baz] += value + # ^^^^^^^^^^^^^^^^^^^^^ + class IndexOperatorWriteNode < Node + # Initialize a new IndexOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), binary_operator: Symbol, binary_operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, binary_operator, binary_operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(IndexOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), binary_operator: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # Returns the `receiver` attribute. + sig { returns(::T.nilable(Node)) } + def receiver; end + + # Returns the Location represented by `call_operator_loc`. + sig { returns(::T.nilable(Location)) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_call_operator_loc(repository); end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `arguments` attribute. + sig { returns(::T.nilable(ArgumentsNode)) } + def arguments; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `block` attribute. + sig { returns(::T.nilable(BlockArgumentNode)) } + def block; end + + # Returns the `binary_operator` attribute. + sig { returns(Symbol) } + def binary_operator; end + + # Returns the Location represented by `binary_operator_loc`. + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of call_operator_loc from the source. + sig { returns(::T.nilable(String)) } + def call_operator; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator on a call to `[]`. + # + # foo.bar[baz] ||= value + # ^^^^^^^^^^^^^^^^^^^^^^ + class IndexOrWriteNode < Node + # Initialize a new IndexOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # Returns the `receiver` attribute. + sig { returns(::T.nilable(Node)) } + def receiver; end + + # Returns the Location represented by `call_operator_loc`. + sig { returns(::T.nilable(Location)) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_call_operator_loc(repository); end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `arguments` attribute. + sig { returns(::T.nilable(ArgumentsNode)) } + def arguments; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `block` attribute. + sig { returns(::T.nilable(BlockArgumentNode)) } + def block; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of call_operator_loc from the source. + sig { returns(::T.nilable(String)) } + def call_operator; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to an index. + # + # foo[bar], = 1 + # ^^^^^^^^ + # + # begin + # rescue => foo[bar] + # ^^^^^^^^ + # end + # + # for foo[bar] in baz do end + # ^^^^^^^^ + class IndexTargetNode < Node + # Initialize a new IndexTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: Node, opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode)).void } + def initialize(source, node_id, location, flags, receiver, opening_loc, arguments, closing_loc, block); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: Node, opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode)).returns(IndexTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # Returns the `receiver` attribute. + sig { returns(Node) } + def receiver; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `arguments` attribute. + sig { returns(::T.nilable(ArgumentsNode)) } + def arguments; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `block` attribute. + sig { returns(::T.nilable(BlockArgumentNode)) } + def block; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator for assignment to an instance variable. + # + # @target &&= value + # ^^^^^^^^^^^^^^^^^ + class InstanceVariableAndWriteNode < Node + # Initialize a new InstanceVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(InstanceVariableAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to an instance variable using an operator that isn't `=`. + # + # @target += value + # ^^^^^^^^^^^^^^^^ + class InstanceVariableOperatorWriteNode < Node + # Initialize a new InstanceVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).void } + def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(InstanceVariableOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `binary_operator_loc`. + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `binary_operator` attribute. + sig { returns(Symbol) } + def binary_operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator for assignment to an instance variable. + # + # @target ||= value + # ^^^^^^^^^^^^^^^^^ + class InstanceVariableOrWriteNode < Node + # Initialize a new InstanceVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(InstanceVariableOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents referencing an instance variable. + # + # @foo + # ^^^^ + class InstanceVariableReadNode < Node + # Initialize a new InstanceVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(InstanceVariableReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the instance variable, which is a `@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @x # name `:@x` + # + # @_test # name `:@_test` + sig { returns(Symbol) } + def name; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to an instance variable in a context that doesn't have an explicit value. + # + # @foo, @bar = baz + # ^^^^ ^^^^ + class InstanceVariableTargetNode < Node + # Initialize a new InstanceVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(InstanceVariableTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to an instance variable. + # + # @foo = 1 + # ^^^^^^^^ + class InstanceVariableWriteNode < Node + # Initialize a new InstanceVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(InstanceVariableWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the instance variable, which is a `@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @x = :y # name `:@x` + # + # @_foo = "bar" # name `@_foo` + sig { returns(Symbol) } + def name; end + + # The Location of the variable name. + # + # @_x = 1 + # ^^^ + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # 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). + # + # @foo = :bar + # ^^^^ + # + # @_x = 1234 + # ^^^^ + sig { returns(Node) } + def value; end + + # The Location of the `=` operator. + # + # @x = y + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an integer number literal. + # + # 1 + # ^ + class IntegerNode < Node + # Initialize a new IntegerNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Integer).void } + def initialize(source, node_id, location, flags, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, value: Integer).returns(IntegerNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # 0b prefix + sig { returns(T::Boolean) } + def binary?; end + + # 0d or no prefix + sig { returns(T::Boolean) } + def decimal?; end + + # 0o or 0 prefix + sig { returns(T::Boolean) } + def octal?; end + + # 0x prefix + sig { returns(T::Boolean) } + def hexadecimal?; end + + # The value of the integer literal as a number. + sig { returns(Integer) } + def value; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a regular expression literal that contains interpolation that is being used in the predicate of a conditional to implicitly match against the last line read by an IO object. + # + # if /foo #{bar} baz/ then end + # ^^^^^^^^^^^^^^^^ + class InterpolatedMatchLastLineNode < Node + # Initialize a new InterpolatedMatchLastLineNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).void } + def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedMatchLastLineNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # i - ignores the case of characters when matching + sig { returns(T::Boolean) } + def ignore_case?; end + + # x - ignores whitespace and allows comments in regular expressions + sig { returns(T::Boolean) } + def extended?; end + + # m - allows $ to match the end of lines within strings + sig { returns(T::Boolean) } + def multi_line?; end + + # o - only interpolates values into the regular expression once + sig { returns(T::Boolean) } + def once?; end + + # e - forces the EUC-JP encoding + sig { returns(T::Boolean) } + def euc_jp?; end + + # n - forces the ASCII-8BIT encoding + sig { returns(T::Boolean) } + def ascii_8bit?; end + + # s - forces the Windows-31J encoding + sig { returns(T::Boolean) } + def windows_31j?; end + + # u - forces the UTF-8 encoding + sig { returns(T::Boolean) } + def utf_8?; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # internal bytes forced the encoding to US-ASCII + sig { returns(T::Boolean) } + def forced_us_ascii_encoding?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `parts` attribute. + sig { returns(T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } + def parts; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a regular expression literal that contains interpolation. + # + # /foo #{bar} baz/ + # ^^^^^^^^^^^^^^^^ + class InterpolatedRegularExpressionNode < Node + # Initialize a new InterpolatedRegularExpressionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).void } + def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedRegularExpressionNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # i - ignores the case of characters when matching + sig { returns(T::Boolean) } + def ignore_case?; end + + # x - ignores whitespace and allows comments in regular expressions + sig { returns(T::Boolean) } + def extended?; end + + # m - allows $ to match the end of lines within strings + sig { returns(T::Boolean) } + def multi_line?; end + + # o - only interpolates values into the regular expression once + sig { returns(T::Boolean) } + def once?; end + + # e - forces the EUC-JP encoding + sig { returns(T::Boolean) } + def euc_jp?; end + + # n - forces the ASCII-8BIT encoding + sig { returns(T::Boolean) } + def ascii_8bit?; end + + # s - forces the Windows-31J encoding + sig { returns(T::Boolean) } + def windows_31j?; end + + # u - forces the UTF-8 encoding + sig { returns(T::Boolean) } + def utf_8?; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # internal bytes forced the encoding to US-ASCII + sig { returns(T::Boolean) } + def forced_us_ascii_encoding?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `parts` attribute. + sig { returns(T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } + def parts; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a string literal that contains interpolation. + # + # "foo #{bar} baz" + # ^^^^^^^^^^^^^^^^ + class InterpolatedStringNode < Node + # Initialize a new InterpolatedStringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)], closing_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)], closing_loc: ::T.nilable(Location)).returns(InterpolatedStringNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + sig { returns(T::Boolean) } + def frozen?; end + + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + sig { returns(T::Boolean) } + def mutable?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(::T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Returns the `parts` attribute. + sig { returns(T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)]) } + def parts; end + + # Returns the Location represented by `closing_loc`. + sig { returns(::T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(::T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(::T.nilable(String)) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a symbol literal that contains interpolation. + # + # :"foo #{bar} baz" + # ^^^^^^^^^^^^^^^^^ + class InterpolatedSymbolNode < Node + # Initialize a new InterpolatedSymbolNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: ::T.nilable(Location)).returns(InterpolatedSymbolNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `opening_loc`. + sig { returns(::T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Returns the `parts` attribute. + sig { returns(T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } + def parts; end + + # Returns the Location represented by `closing_loc`. + sig { returns(::T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(::T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(::T.nilable(String)) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an xstring literal that contains interpolation. + # + # `foo #{bar} baz` + # ^^^^^^^^^^^^^^^^ + class InterpolatedXStringNode < Node + # Initialize a new InterpolatedXStringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).void } + def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedXStringNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `parts` attribute. + sig { returns(T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } + def parts; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents reading from the implicit `it` local variable. + # + # -> { it } + # ^^ + class ItLocalVariableReadNode < Node + # Initialize a new ItLocalVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(ItLocalVariableReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an implicit set of parameters through the use of the `it` keyword within a block or lambda. + # + # -> { it + it } + # ^^^^^^^^^^^^^^ + class ItParametersNode < Node + # Initialize a new ItParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(ItParametersNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a hash literal without opening and closing braces. + # + # foo(a: b) + # ^^^^ + class KeywordHashNode < Node + # Initialize a new KeywordHashNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[::T.any(AssocNode, AssocSplatNode)]).void } + def initialize(source, node_id, location, flags, elements); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, elements: T::Array[::T.any(AssocNode, AssocSplatNode)]).returns(KeywordHashNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), elements: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a keyword hash which only has `AssocNode` elements all with symbol keys, which means the elements can be treated as keyword arguments + sig { returns(T::Boolean) } + def symbol_keys?; end + + # Returns the `elements` attribute. + sig { returns(T::Array[::T.any(AssocNode, AssocSplatNode)]) } + def elements; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a keyword rest parameter to a method, block, or lambda definition. + # + # def a(**b) + # ^^^ + # end + class KeywordRestParameterNode < Node + # Initialize a new KeywordRestParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).returns(KeywordRestParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # Returns the `name` attribute. + sig { returns(::T.nilable(Symbol)) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(::T.nilable(Location)) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents using a lambda literal (not the lambda method call). + # + # ->(value) { value * 2 } + # ^^^^^^^^^^^^^^^^^^^^^^^ + class LambdaNode < Node + # Initialize a new LambdaNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], operator_loc: Location, opening_loc: Location, closing_loc: Location, parameters: ::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: ::T.nilable(::T.any(StatementsNode, BeginNode))).void } + def initialize(source, node_id, location, flags, locals, operator_loc, opening_loc, closing_loc, parameters, body); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], operator_loc: Location, opening_loc: Location, closing_loc: Location, parameters: ::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: ::T.nilable(::T.any(StatementsNode, BeginNode))).returns(LambdaNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `locals` attribute. + sig { returns(T::Array[Symbol]) } + def locals; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `parameters` attribute. + sig { returns(::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode))) } + def parameters; end + + # Returns the `body` attribute. + sig { returns(::T.nilable(::T.any(StatementsNode, BeginNode))) } + def body; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator for assignment to a local variable. + # + # target &&= value + # ^^^^^^^^^^^^^^^^ + class LocalVariableAndWriteNode < Node + # Initialize a new LocalVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).void } + def initialize(source, node_id, location, flags, name_loc, operator_loc, value, name, depth); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).returns(LocalVariableAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the `depth` attribute. + sig { returns(Integer) } + def depth; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to a local variable using an operator that isn't `=`. + # + # target += value + # ^^^^^^^^^^^^^^^ + class LocalVariableOperatorWriteNode < Node + # Initialize a new LocalVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name_loc: Location, binary_operator_loc: Location, value: Node, name: Symbol, binary_operator: Symbol, depth: Integer).void } + def initialize(source, node_id, location, flags, name_loc, binary_operator_loc, value, name, binary_operator, depth); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name_loc: Location, binary_operator_loc: Location, value: Node, name: Symbol, binary_operator: Symbol, depth: Integer).returns(LocalVariableOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), binary_operator: T.unsafe(nil), depth: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `binary_operator_loc`. + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the `binary_operator` attribute. + sig { returns(Symbol) } + def binary_operator; end + + # Returns the `depth` attribute. + sig { returns(Integer) } + def depth; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator for assignment to a local variable. + # + # target ||= value + # ^^^^^^^^^^^^^^^^ + class LocalVariableOrWriteNode < Node + # Initialize a new LocalVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).void } + def initialize(source, node_id, location, flags, name_loc, operator_loc, value, name, depth); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).returns(LocalVariableOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the `depth` attribute. + sig { returns(Integer) } + def depth; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents reading a local variable. Note that this requires that a local variable of the same name has already been written to in the same scope, otherwise it is parsed as a method call. + # + # foo + # ^^^ + class LocalVariableReadNode < Node + # Initialize a new LocalVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).void } + def initialize(source, node_id, location, flags, name, depth); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).returns(LocalVariableReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the local variable, which is an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # x # name `:x` + # + # _Test # name `:_Test` + # + # Note that this can also be an underscore followed by a number for the default block parameters. + # + # _1 # name `:_1` + sig { returns(Symbol) } + def name; end + + # The number of visible scopes that should be searched to find the origin of this local variable. + # + # foo = 1; foo # depth 0 + # + # bar = 2; tap { bar } # depth 1 + # + # The specific rules for calculating the depth may differ from individual Ruby implementations, as they are not specified by the language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md). + sig { returns(Integer) } + def depth; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a local variable in a context that doesn't have an explicit value. + # + # foo, bar = baz + # ^^^ ^^^ + # + # foo => baz + # ^^^ + class LocalVariableTargetNode < Node + # Initialize a new LocalVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).void } + def initialize(source, node_id, location, flags, name, depth); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).returns(LocalVariableTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the `depth` attribute. + sig { returns(Integer) } + def depth; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a local variable. + # + # foo = 1 + # ^^^^^^^ + class LocalVariableWriteNode < Node + # Initialize a new LocalVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer, name_loc: Location, value: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, depth, name_loc, value, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer, name_loc: Location, value: Node, operator_loc: Location).returns(LocalVariableWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the local variable, which is an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # foo = :bar # name `:foo` + # + # abc = 123 # name `:abc` + sig { returns(Symbol) } + def name; end + + # The number of semantic scopes we have to traverse to find the declaration of this variable. + # + # foo = 1 # depth 0 + # + # tap { foo = 1 } # depth 1 + # + # The specific rules for calculating the depth may differ from individual Ruby implementations, as they are not specified by the language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md). + sig { returns(Integer) } + def depth; end + + # The Location of the variable name. + # + # foo = :bar + # ^^^ + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # 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). + # + # foo = :bar + # ^^^^ + # + # abc = 1234 + # ^^^^ + # + # Note that since the name of a local variable is known before the value is parsed, it is valid for a local variable to appear within the value of its own write. + # + # foo = foo + sig { returns(Node) } + def value; end + + # The Location of the `=` operator. + # + # x = :y + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a regular expression literal used in the predicate of a conditional to implicitly match against the last line read by an IO object. + # + # if /foo/i then end + # ^^^^^^ + class MatchLastLineNode < Node + # Initialize a new MatchLastLineNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).void } + def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(MatchLastLineNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # i - ignores the case of characters when matching + sig { returns(T::Boolean) } + def ignore_case?; end + + # x - ignores whitespace and allows comments in regular expressions + sig { returns(T::Boolean) } + def extended?; end + + # m - allows $ to match the end of lines within strings + sig { returns(T::Boolean) } + def multi_line?; end + + # o - only interpolates values into the regular expression once + sig { returns(T::Boolean) } + def once?; end + + # e - forces the EUC-JP encoding + sig { returns(T::Boolean) } + def euc_jp?; end + + # n - forces the ASCII-8BIT encoding + sig { returns(T::Boolean) } + def ascii_8bit?; end + + # s - forces the Windows-31J encoding + sig { returns(T::Boolean) } + def windows_31j?; end + + # u - forces the UTF-8 encoding + sig { returns(T::Boolean) } + def utf_8?; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # internal bytes forced the encoding to US-ASCII + sig { returns(T::Boolean) } + def forced_us_ascii_encoding?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the Location represented by `content_loc`. + sig { returns(Location) } + def content_loc; end + + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_content_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `unescaped` attribute. + sig { returns(String) } + def unescaped; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of content_loc from the source. + sig { returns(String) } + def content; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the modifier `in` operator. + # + # foo in bar + # ^^^^^^^^^^ + class MatchPredicateNode < Node + # Initialize a new MatchPredicateNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, value, pattern, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).returns(MatchPredicateNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), pattern: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `pattern` attribute. + sig { returns(Node) } + def pattern; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `=>` operator. + # + # foo => bar + # ^^^^^^^^^^ + class MatchRequiredNode < Node + # Initialize a new MatchRequiredNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, value, pattern, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).returns(MatchRequiredNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), pattern: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the left-hand side of the operator. + # + # foo => bar + # ^^^ + sig { returns(Node) } + def value; end + + # Represents the right-hand side of the operator. The type of the node depends on the expression. + # + # Anything that looks like a local variable name (including `_`) will result in a `LocalVariableTargetNode`. + # + # foo => a # This is equivalent to writing `a = foo` + # ^ + # + # Using an explicit `Array` or combining expressions with `,` will result in a `ArrayPatternNode`. This can be preceded by a constant. + # + # foo => [a] + # ^^^ + # + # foo => a, b + # ^^^^ + # + # foo => Bar[a, b] + # ^^^^^^^^^ + # + # If the array pattern contains at least two wildcard matches, a `FindPatternNode` is created instead. + # + # foo => *, 1, *a + # ^^^^^ + # + # Using an explicit `Hash` or a constant with square brackets and hash keys in the square brackets will result in a `HashPatternNode`. + # + # foo => { a: 1, b: } + # + # foo => Bar[a: 1, b:] + # + # foo => Bar[**] + # + # To use any variable that needs run time evaluation, pinning is required. This results in a `PinnedVariableNode` + # + # foo => ^a + # ^^ + # + # Similar, any expression can be used with pinning. This results in a `PinnedExpressionNode`. + # + # foo => ^(a + 1) + # + # Anything else will result in the regular node for that expression, for example a `ConstantReadNode`. + # + # foo => CONST + sig { returns(Node) } + def pattern; end + + # The Location of the operator. + # + # foo => bar + # ^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing local variables using a regular expression match with named capture groups. + # + # /(?bar)/ =~ baz + # ^^^^^^^^^^^^^^^^^^^^ + class MatchWriteNode < Node + # Initialize a new MatchWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, call: CallNode, targets: T::Array[LocalVariableTargetNode]).void } + def initialize(source, node_id, location, flags, call, targets); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, call: CallNode, targets: T::Array[LocalVariableTargetNode]).returns(MatchWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), call: T.unsafe(nil), targets: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `call` attribute. + sig { returns(CallNode) } + def call; end + + # Returns the `targets` attribute. + sig { returns(T::Array[LocalVariableTargetNode]) } + def targets; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a node that is missing from the source and results in a syntax error. + class MissingNode < Node + # Initialize a new MissingNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(MissingNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a module declaration involving the `module` keyword. + # + # module Foo end + # ^^^^^^^^^^^^^^ + class ModuleNode < Node + # Initialize a new ModuleNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], module_keyword_loc: Location, constant_path: ::T.any(ConstantReadNode, ConstantPathNode, MissingNode), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).void } + def initialize(source, node_id, location, flags, locals, module_keyword_loc, constant_path, body, end_keyword_loc, name); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], module_keyword_loc: Location, constant_path: ::T.any(ConstantReadNode, ConstantPathNode, MissingNode), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ModuleNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), module_keyword_loc: T.unsafe(nil), constant_path: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `locals` attribute. + sig { returns(T::Array[Symbol]) } + def locals; end + + # Returns the Location represented by `module_keyword_loc`. + sig { returns(Location) } + def module_keyword_loc; end + + # Save the module_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_module_keyword_loc(repository); end + + # Returns the `constant_path` attribute. + sig { returns(::T.any(ConstantReadNode, ConstantPathNode, MissingNode)) } + def constant_path; end + + # Returns the `body` attribute. + sig { returns(::T.nilable(::T.any(StatementsNode, BeginNode))) } + def body; end + + # Returns the Location represented by `end_keyword_loc`. + sig { returns(Location) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_end_keyword_loc(repository); end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Slice the location of module_keyword_loc from the source. + sig { returns(String) } + def module_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(String) } + def end_keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # 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]] + # ^^^^ + class MultiTargetNode < Node + # Initialize a new MultiTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: ::T.nilable(::T.any(ImplicitRestNode, SplatNode)), rights: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, lefts, rest, rights, lparen_loc, rparen_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, lefts: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: ::T.nilable(::T.any(ImplicitRestNode, SplatNode)), rights: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location)).returns(MultiTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lefts: T.unsafe(nil), rest: T.unsafe(nil), rights: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # 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 + # ^^^^ + sig { returns(T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } + def lefts; end + + # 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 + # ^ + sig { returns(::T.nilable(::T.any(ImplicitRestNode, SplatNode))) } + def rest; end + + # Represents the targets expressions after a splat node. + # + # a, (*, b, c) = 1, 2, 3, 4, 5 + # ^^^^ + sig { returns(T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } + def rights; end + + # The Location of the opening parenthesis. + # + # a, (b, c) = 1, 2, 3 + # ^ + sig { returns(::T.nilable(Location)) } + def lparen_loc; end + + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_lparen_loc(repository); end + + # The Location of the closing parenthesis. + # + # a, (b, c) = 1, 2, 3 + # ^ + sig { returns(::T.nilable(Location)) } + def rparen_loc; end + + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_rparen_loc(repository); end + + # Slice the location of lparen_loc from the source. + sig { returns(::T.nilable(String)) } + def lparen; end + + # Slice the location of rparen_loc from the source. + sig { returns(::T.nilable(String)) } + def rparen; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a write to a multi-target expression. + # + # a, b, c = 1, 2, 3 + # ^^^^^^^^^^^^^^^^^ + class MultiWriteNode < Node + # Initialize a new MultiWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: ::T.nilable(::T.any(ImplicitRestNode, SplatNode)), rights: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location), operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, lefts, rest, rights, lparen_loc, rparen_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, lefts: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: ::T.nilable(::T.any(ImplicitRestNode, SplatNode)), rights: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location), operator_loc: Location, value: Node).returns(MultiWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lefts: T.unsafe(nil), rest: T.unsafe(nil), rights: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # 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 + # ^^^^^^^ + sig { returns(T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } + def lefts; end + + # 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 + # ^ + sig { returns(::T.nilable(::T.any(ImplicitRestNode, SplatNode))) } + def rest; end + + # Represents the targets expressions after a splat node. + # + # a, *, b, c = 1, 2, 3, 4, 5 + # ^^^^ + sig { returns(T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } + def rights; end + + # The Location of the opening parenthesis. + # + # (a, b, c) = 1, 2, 3 + # ^ + sig { returns(::T.nilable(Location)) } + def lparen_loc; end + + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_lparen_loc(repository); end + + # The Location of the closing parenthesis. + # + # (a, b, c) = 1, 2, 3 + # ^ + sig { returns(::T.nilable(Location)) } + def rparen_loc; end + + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_rparen_loc(repository); end + + # The Location of the operator. + # + # a, b, c = 1, 2, 3 + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # 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 + # ^^^^^^^ + sig { returns(Node) } + def value; end + + # Slice the location of lparen_loc from the source. + sig { returns(::T.nilable(String)) } + def lparen; end + + # Slice the location of rparen_loc from the source. + sig { returns(::T.nilable(String)) } + def rparen; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `next` keyword. + # + # next 1 + # ^^^^^^ + class NextNode < Node + # Initialize a new NextNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: ::T.nilable(ArgumentsNode), keyword_loc: Location).void } + def initialize(source, node_id, location, flags, arguments, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, arguments: ::T.nilable(ArgumentsNode), keyword_loc: Location).returns(NextNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `arguments` attribute. + sig { returns(::T.nilable(ArgumentsNode)) } + def arguments; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `nil` keyword. + # + # nil + # ^^^ + class NilNode < Node + # Initialize a new NilNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(NilNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of `&nil` inside method arguments. + # + # def a(&nil) + # ^^^^ + # end + class NoBlockParameterNode < Node + # Initialize a new NoBlockParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).void } + def initialize(source, node_id, location, flags, operator_loc, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).returns(NoBlockParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of `**nil` inside method arguments. + # + # def a(**nil) + # ^^^^^ + # end + class NoKeywordsParameterNode < Node + # Initialize a new NoKeywordsParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).void } + def initialize(source, node_id, location, flags, operator_loc, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).returns(NoKeywordsParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an implicit set of parameters through the use of numbered parameters within a block or lambda. + # + # -> { _1 + _2 } + # ^^^^^^^^^^^^^^ + class NumberedParametersNode < Node + # Initialize a new NumberedParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, maximum: Integer).void } + def initialize(source, node_id, location, flags, maximum); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, maximum: Integer).returns(NumberedParametersNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), maximum: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `maximum` attribute. + sig { returns(Integer) } + def maximum; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents reading a numbered reference to a capture in the previous match. + # + # $1 + # ^^ + class NumberedReferenceReadNode < Node + # Initialize a new NumberedReferenceReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, number: Integer).void } + def initialize(source, node_id, location, flags, number); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, number: Integer).returns(NumberedReferenceReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), number: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The (1-indexed, from the left) number of the capture group. Numbered references that are too large result in this value being `0`. + # + # $1 # number `1` + # + # $5432 # number `5432` + # + # $4294967296 # number `0` + sig { returns(Integer) } + def number; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an optional keyword parameter to a method, block, or lambda definition. + # + # def a(b: 1) + # ^^^^ + # end + class OptionalKeywordParameterNode < Node + # Initialize a new OptionalKeywordParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node).returns(OptionalKeywordParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an optional parameter to a method, block, or lambda definition. + # + # def a(b = 1) + # ^^^^^ + # end + class OptionalParameterNode < Node + # Initialize a new OptionalParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(OptionalParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||` operator or the `or` keyword. + # + # left or right + # ^^^^^^^^^^^^^ + class OrNode < Node + # Initialize a new OrNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, left, right, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(OrNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # 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). + # + # left or right + # ^^^^ + # + # 1 || 2 + # ^ + sig { returns(Node) } + def left; end + + # Represents the right side of the expression. + # + # left || right + # ^^^^^ + # + # 1 or 2 + # ^ + sig { returns(Node) } + def right; end + + # The Location of the `or` keyword or the `||` operator. + # + # left or right + # ^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the list of parameters on a method, block, or lambda definition. + # + # def a(b, c, d) + # ^^^^^^^ + # end + class ParametersNode < Node + # Initialize a new ParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, requireds: T::Array[::T.any(RequiredParameterNode, MultiTargetNode)], optionals: T::Array[OptionalParameterNode], rest: ::T.nilable(::T.any(RestParameterNode, ImplicitRestNode)), posts: T::Array[::T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)], keywords: T::Array[::T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)], keyword_rest: ::T.nilable(::T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode)), block: ::T.nilable(::T.any(BlockParameterNode, NoBlockParameterNode))).void } + def initialize(source, node_id, location, flags, requireds, optionals, rest, posts, keywords, keyword_rest, block); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, requireds: T::Array[::T.any(RequiredParameterNode, MultiTargetNode)], optionals: T::Array[OptionalParameterNode], rest: ::T.nilable(::T.any(RestParameterNode, ImplicitRestNode)), posts: T::Array[::T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)], keywords: T::Array[::T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)], keyword_rest: ::T.nilable(::T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode)), block: ::T.nilable(::T.any(BlockParameterNode, NoBlockParameterNode))).returns(ParametersNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), requireds: T.unsafe(nil), optionals: T.unsafe(nil), rest: T.unsafe(nil), posts: T.unsafe(nil), keywords: T.unsafe(nil), keyword_rest: T.unsafe(nil), block: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `requireds` attribute. + sig { returns(T::Array[::T.any(RequiredParameterNode, MultiTargetNode)]) } + def requireds; end + + # Returns the `optionals` attribute. + sig { returns(T::Array[OptionalParameterNode]) } + def optionals; end + + # Returns the `rest` attribute. + sig { returns(::T.nilable(::T.any(RestParameterNode, ImplicitRestNode))) } + def rest; end + + # Returns the `posts` attribute. + sig { returns(T::Array[::T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)]) } + def posts; end + + # Returns the `keywords` attribute. + sig { returns(T::Array[::T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)]) } + def keywords; end + + # Returns the `keyword_rest` attribute. + sig { returns(::T.nilable(::T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode))) } + def keyword_rest; end + + # Returns the `block` attribute. + sig { returns(::T.nilable(::T.any(BlockParameterNode, NoBlockParameterNode))) } + def block; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a parenthesized expression + # + # (10 + 34) + # ^^^^^^^^^ + class ParenthesesNode < Node + # Initialize a new ParenthesesNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, body: ::T.nilable(Node), opening_loc: Location, closing_loc: Location).void } + def initialize(source, node_id, location, flags, body, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, body: ::T.nilable(Node), opening_loc: Location, closing_loc: Location).returns(ParenthesesNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), body: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # parentheses that contain multiple potentially void statements + sig { returns(T::Boolean) } + def multiple_statements?; end + + # Returns the `body` attribute. + sig { returns(::T.nilable(Node)) } + def body; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `^` operator for pinning an expression in a pattern matching expression. + # + # foo in ^(bar) + # ^^^^^^ + class PinnedExpressionNode < Node + # Initialize a new PinnedExpressionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: Node, operator_loc: Location, lparen_loc: Location, rparen_loc: Location).void } + def initialize(source, node_id, location, flags, expression, operator_loc, lparen_loc, rparen_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, expression: Node, operator_loc: Location, lparen_loc: Location, rparen_loc: Location).returns(PinnedExpressionNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), operator_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The expression used in the pinned expression + # + # foo in ^(bar) + # ^^^ + sig { returns(Node) } + def expression; end + + # The Location of the `^` operator + # + # foo in ^(bar) + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # The Location of the opening parenthesis. + # + # foo in ^(bar) + # ^ + sig { returns(Location) } + def lparen_loc; end + + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_lparen_loc(repository); end + + # The Location of the closing parenthesis. + # + # foo in ^(bar) + # ^ + sig { returns(Location) } + def rparen_loc; end + + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_rparen_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + # Slice the location of lparen_loc from the source. + sig { returns(String) } + def lparen; end + + # Slice the location of rparen_loc from the source. + sig { returns(String) } + def rparen; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `^` operator for pinning a variable in a pattern matching expression. + # + # foo in ^bar + # ^^^^ + class PinnedVariableNode < Node + # Initialize a new PinnedVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, variable: ::T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode), operator_loc: Location).void } + def initialize(source, node_id, location, flags, variable, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, variable: ::T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode), operator_loc: Location).returns(PinnedVariableNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), variable: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The variable used in the pinned expression + # + # foo in ^bar + # ^^^ + sig { returns(::T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode)) } + def variable; end + + # The Location of the `^` operator + # + # foo in ^bar + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `END` keyword. + # + # END { foo } + # ^^^^^^^^^^^ + class PostExecutionNode < Node + # Initialize a new PostExecutionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: ::T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).void } + def initialize(source, node_id, location, flags, statements, keyword_loc, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, statements: ::T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PostExecutionNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), statements: T.unsafe(nil), keyword_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `statements` attribute. + sig { returns(::T.nilable(StatementsNode)) } + def statements; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `BEGIN` keyword. + # + # BEGIN { foo } + # ^^^^^^^^^^^^^ + class PreExecutionNode < Node + # Initialize a new PreExecutionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: ::T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).void } + def initialize(source, node_id, location, flags, statements, keyword_loc, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, statements: ::T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PreExecutionNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), statements: T.unsafe(nil), keyword_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `statements` attribute. + sig { returns(::T.nilable(StatementsNode)) } + def statements; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # The top level node of any parse tree. + class ProgramNode < Node + # Initialize a new ProgramNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], statements: StatementsNode).void } + def initialize(source, node_id, location, flags, locals, statements); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], statements: StatementsNode).returns(ProgramNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), statements: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `locals` attribute. + sig { returns(T::Array[Symbol]) } + def locals; end + + # Returns the `statements` attribute. + sig { returns(StatementsNode) } + def statements; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `..` or `...` operators. + # + # 1..2 + # ^^^^ + # + # c if a =~ /left/ ... b =~ /right/ + # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + class RangeNode < Node + # Initialize a new RangeNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: ::T.nilable(Node), right: ::T.nilable(Node), operator_loc: Location).void } + def initialize(source, node_id, location, flags, left, right, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, left: ::T.nilable(Node), right: ::T.nilable(Node), operator_loc: Location).returns(RangeNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # ... operator + sig { returns(T::Boolean) } + def exclude_end?; end + + # 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). + # + # 1... + # ^ + # + # hello...goodbye + # ^^^^^ + sig { returns(::T.nilable(Node)) } + def left; end + + # 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). + # + # ..5 + # ^ + # + # 1...foo + # ^^^ + # If neither right-hand or left-hand side was included, this will be a MissingNode. + sig { returns(::T.nilable(Node)) } + def right; end + + # The Location of the `..` or `...` operator. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a rational number literal. + # + # 1.0r + # ^^^^ + class RationalNode < Node + # Initialize a new RationalNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, numerator: Integer, denominator: Integer).void } + def initialize(source, node_id, location, flags, numerator, denominator); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, numerator: Integer, denominator: Integer).returns(RationalNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), numerator: T.unsafe(nil), denominator: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # 0b prefix + sig { returns(T::Boolean) } + def binary?; end + + # 0d or no prefix + sig { returns(T::Boolean) } + def decimal?; end + + # 0o or 0 prefix + sig { returns(T::Boolean) } + def octal?; end + + # 0x prefix + sig { returns(T::Boolean) } + def hexadecimal?; end + + # The numerator of the rational number. + # + # 1.5r # numerator 3 + sig { returns(Integer) } + def numerator; end + + # The denominator of the rational number. + # + # 1.5r # denominator 2 + sig { returns(Integer) } + def denominator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `redo` keyword. + # + # redo + # ^^^^ + class RedoNode < Node + # Initialize a new RedoNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(RedoNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a regular expression literal with no interpolation. + # + # /foo/i + # ^^^^^^ + class RegularExpressionNode < Node + # Initialize a new RegularExpressionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).void } + def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(RegularExpressionNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # i - ignores the case of characters when matching + sig { returns(T::Boolean) } + def ignore_case?; end + + # x - ignores whitespace and allows comments in regular expressions + sig { returns(T::Boolean) } + def extended?; end + + # m - allows $ to match the end of lines within strings + sig { returns(T::Boolean) } + def multi_line?; end + + # o - only interpolates values into the regular expression once + sig { returns(T::Boolean) } + def once?; end + + # e - forces the EUC-JP encoding + sig { returns(T::Boolean) } + def euc_jp?; end + + # n - forces the ASCII-8BIT encoding + sig { returns(T::Boolean) } + def ascii_8bit?; end + + # s - forces the Windows-31J encoding + sig { returns(T::Boolean) } + def windows_31j?; end + + # u - forces the UTF-8 encoding + sig { returns(T::Boolean) } + def utf_8?; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # internal bytes forced the encoding to US-ASCII + sig { returns(T::Boolean) } + def forced_us_ascii_encoding?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the Location represented by `content_loc`. + sig { returns(Location) } + def content_loc; end + + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_content_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `unescaped` attribute. + sig { returns(String) } + def unescaped; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of content_loc from the source. + sig { returns(String) } + def content; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a required keyword parameter to a method, block, or lambda definition. + # + # def a(b: ) + # ^^ + # end + class RequiredKeywordParameterNode < Node + # Initialize a new RequiredKeywordParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location).returns(RequiredKeywordParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a required parameter to a method, block, or lambda definition. + # + # def a(b) + # ^ + # end + class RequiredParameterNode < Node + # Initialize a new RequiredParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(RequiredParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an expression modified with a rescue. + # + # foo rescue nil + # ^^^^^^^^^^^^^^ + class RescueModifierNode < Node + # Initialize a new RescueModifierNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: Node, keyword_loc: Location, rescue_expression: Node).void } + def initialize(source, node_id, location, flags, expression, keyword_loc, rescue_expression); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, expression: Node, keyword_loc: Location, rescue_expression: Node).returns(RescueModifierNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), keyword_loc: T.unsafe(nil), rescue_expression: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `expression` attribute. + sig { returns(Node) } + def expression; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the `rescue_expression` attribute. + sig { returns(Node) } + def rescue_expression; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a rescue statement. + # + # begin + # rescue Foo, *splat, Bar => ex + # foo + # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + # end + # + # `Foo, *splat, Bar` are in the `exceptions` field. `ex` is in the `reference` field. + class RescueNode < Node + # Initialize a new RescueNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, exceptions: T::Array[Node], operator_loc: ::T.nilable(Location), reference: ::T.nilable(::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)), then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), subsequent: ::T.nilable(RescueNode)).void } + def initialize(source, node_id, location, flags, keyword_loc, exceptions, operator_loc, reference, then_keyword_loc, statements, subsequent); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, exceptions: T::Array[Node], operator_loc: ::T.nilable(Location), reference: ::T.nilable(::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)), then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), subsequent: ::T.nilable(RescueNode)).returns(RescueNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), exceptions: T.unsafe(nil), operator_loc: T.unsafe(nil), reference: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), subsequent: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the `exceptions` attribute. + sig { returns(T::Array[Node]) } + def exceptions; end + + # Returns the Location represented by `operator_loc`. + sig { returns(::T.nilable(Location)) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_operator_loc(repository); end + + # Returns the `reference` attribute. + sig { returns(::T.nilable(::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode))) } + def reference; end + + # Returns the Location represented by `then_keyword_loc`. + sig { returns(::T.nilable(Location)) } + def then_keyword_loc; end + + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_then_keyword_loc(repository); end + + # Returns the `statements` attribute. + sig { returns(::T.nilable(StatementsNode)) } + def statements; end + + # Returns the `subsequent` attribute. + sig { returns(::T.nilable(RescueNode)) } + def subsequent; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of operator_loc from the source. + sig { returns(::T.nilable(String)) } + def operator; end + + # Slice the location of then_keyword_loc from the source. + sig { returns(::T.nilable(String)) } + def then_keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a rest parameter to a method, block, or lambda definition. + # + # def a(*b) + # ^^ + # end + class RestParameterNode < Node + # Initialize a new RestParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).returns(RestParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # Returns the `name` attribute. + sig { returns(::T.nilable(Symbol)) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(::T.nilable(Location)) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `retry` keyword. + # + # retry + # ^^^^^ + class RetryNode < Node + # Initialize a new RetryNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(RetryNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `return` keyword. + # + # return 1 + # ^^^^^^^^ + class ReturnNode < Node + # Initialize a new ReturnNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, arguments: ::T.nilable(ArgumentsNode)).void } + def initialize(source, node_id, location, flags, keyword_loc, arguments); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, arguments: ::T.nilable(ArgumentsNode)).returns(ReturnNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), arguments: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the `arguments` attribute. + sig { returns(::T.nilable(ArgumentsNode)) } + def arguments; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the `self` keyword. + # + # self + # ^^^^ + class SelfNode < Node + # Initialize a new SelfNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(SelfNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # This node wraps a constant write to indicate that when the value is written, it should have its shareability state modified. + # + # # shareable_constant_value: literal + # C = { a: 1 } + # ^^^^^^^^^^^^ + class ShareableConstantNode < Node + # Initialize a new ShareableConstantNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, write: ::T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)).void } + def initialize(source, node_id, location, flags, write); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, write: ::T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)).returns(ShareableConstantNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), write: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # constant writes that should be modified with shareable constant value literal + sig { returns(T::Boolean) } + def literal?; end + + # constant writes that should be modified with shareable constant value experimental everything + sig { returns(T::Boolean) } + def experimental_everything?; end + + # constant writes that should be modified with shareable constant value experimental copy + sig { returns(T::Boolean) } + def experimental_copy?; end + + # The constant write that should be modified with the shareability state. + sig { returns(::T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)) } + def write; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a singleton class declaration involving the `class` keyword. + # + # class << self end + # ^^^^^^^^^^^^^^^^^ + class SingletonClassNode < Node + # Initialize a new SingletonClassNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, operator_loc: Location, expression: Node, body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location).void } + def initialize(source, node_id, location, flags, locals, class_keyword_loc, operator_loc, expression, body, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, operator_loc: Location, expression: Node, body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location).returns(SingletonClassNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), class_keyword_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), expression: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `locals` attribute. + sig { returns(T::Array[Symbol]) } + def locals; end + + # Returns the Location represented by `class_keyword_loc`. + sig { returns(Location) } + def class_keyword_loc; end + + # Save the class_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_class_keyword_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `expression` attribute. + sig { returns(Node) } + def expression; end + + # Returns the `body` attribute. + sig { returns(::T.nilable(::T.any(StatementsNode, BeginNode))) } + def body; end + + # Returns the Location represented by `end_keyword_loc`. + sig { returns(Location) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_end_keyword_loc(repository); end + + # Slice the location of class_keyword_loc from the source. + sig { returns(String) } + def class_keyword; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(String) } + def end_keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `__ENCODING__` keyword. + # + # __ENCODING__ + # ^^^^^^^^^^^^ + class SourceEncodingNode < Node + # Initialize a new SourceEncodingNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(SourceEncodingNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `__FILE__` keyword. + # + # __FILE__ + # ^^^^^^^^ + class SourceFileNode < Node + # Initialize a new SourceFileNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, filepath: String).void } + def initialize(source, node_id, location, flags, filepath); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, filepath: String).returns(SourceFileNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), filepath: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal` + sig { returns(T::Boolean) } + def frozen?; end + + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` + sig { returns(T::Boolean) } + def mutable?; end + + # Represents the file path being parsed. This corresponds directly to the `filepath` option given to the various `Prism.parse*` APIs. + sig { returns(String) } + def filepath; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `__LINE__` keyword. + # + # __LINE__ + # ^^^^^^^^ + class SourceLineNode < Node + # Initialize a new SourceLineNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(SourceLineNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the splat operator. + # + # [*a] + # ^^ + class SplatNode < Node + # Initialize a new SplatNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, expression: ::T.nilable(Node)).void } + def initialize(source, node_id, location, flags, operator_loc, expression); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, expression: ::T.nilable(Node)).returns(SplatNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), expression: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `expression` attribute. + sig { returns(::T.nilable(Node)) } + def expression; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a set of statements contained within some scope. + # + # foo; bar; baz + # ^^^^^^^^^^^^^ + class StatementsNode < Node + # Initialize a new StatementsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, body: T::Array[Node]).void } + def initialize(source, node_id, location, flags, body); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, body: T::Array[Node]).returns(StatementsNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), body: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `body` attribute. + sig { returns(T::Array[Node]) } + def body; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a string literal, a string contained within a `%w` list, or plain string content within an interpolated string. + # + # "foo" + # ^^^^^ + # + # %w[foo] + # ^^^ + # + # "foo #{bar} baz" + # ^^^^ ^^^^ + class StringNode < Node + # Initialize a new StringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), content_loc: Location, closing_loc: ::T.nilable(Location), unescaped: String).void } + def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), content_loc: Location, closing_loc: ::T.nilable(Location), unescaped: String).returns(StringNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal` + sig { returns(T::Boolean) } + def frozen?; end + + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` + sig { returns(T::Boolean) } + def mutable?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(::T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Returns the Location represented by `content_loc`. + sig { returns(Location) } + def content_loc; end + + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_content_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(::T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Returns the `unescaped` attribute. + sig { returns(String) } + def unescaped; end + + # Slice the location of opening_loc from the source. + sig { returns(::T.nilable(String)) } + def opening; end + + # Slice the location of content_loc from the source. + sig { returns(String) } + def content; end + + # Slice the location of closing_loc from the source. + sig { returns(::T.nilable(String)) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `super` keyword with parentheses or arguments. + # + # super() + # ^^^^^^^ + # + # super foo, bar + # ^^^^^^^^^^^^^^ + # + # If no arguments are provided (except for a block), it would be a `ForwardingSuperNode` instead. + class SuperNode < Node + # Initialize a new SuperNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), rparen_loc: ::T.nilable(Location), block: ::T.nilable(::T.any(BlockNode, BlockArgumentNode))).void } + def initialize(source, node_id, location, flags, keyword_loc, lparen_loc, arguments, rparen_loc, block); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), rparen_loc: ::T.nilable(Location), block: ::T.nilable(::T.any(BlockNode, BlockArgumentNode))).returns(SuperNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), arguments: T.unsafe(nil), rparen_loc: T.unsafe(nil), block: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the Location represented by `lparen_loc`. + sig { returns(::T.nilable(Location)) } + def lparen_loc; end + + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_lparen_loc(repository); end + + # Can be only `nil` when there are empty parentheses, like `super()`. + sig { returns(::T.nilable(ArgumentsNode)) } + def arguments; end + + # Returns the Location represented by `rparen_loc`. + sig { returns(::T.nilable(Location)) } + def rparen_loc; end + + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_rparen_loc(repository); end + + # Returns the `block` attribute. + sig { returns(::T.nilable(::T.any(BlockNode, BlockArgumentNode))) } + def block; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of lparen_loc from the source. + sig { returns(::T.nilable(String)) } + def lparen; end + + # Slice the location of rparen_loc from the source. + sig { returns(::T.nilable(String)) } + def rparen; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a symbol literal or a symbol contained within a `%i` list. + # + # :foo + # ^^^^ + # + # %i[foo] + # ^^^ + class SymbolNode < Node + # Initialize a new SymbolNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), value_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), unescaped: String).void } + def initialize(source, node_id, location, flags, opening_loc, value_loc, closing_loc, unescaped); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), value_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), unescaped: String).returns(SymbolNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), value_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # internal bytes forced the encoding to US-ASCII + sig { returns(T::Boolean) } + def forced_us_ascii_encoding?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(::T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Returns the Location represented by `value_loc`. + sig { returns(::T.nilable(Location)) } + def value_loc; end + + # Save the value_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_value_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(::T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Returns the `unescaped` attribute. + sig { returns(String) } + def unescaped; end + + # Slice the location of opening_loc from the source. + sig { returns(::T.nilable(String)) } + def opening; end + + # Slice the location of value_loc from the source. + sig { returns(::T.nilable(String)) } + def value; end + + # Slice the location of closing_loc from the source. + sig { returns(::T.nilable(String)) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the literal `true` keyword. + # + # true + # ^^^^ + class TrueNode < Node + # Initialize a new TrueNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(TrueNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `undef` keyword. + # + # undef :foo, :bar, :baz + # ^^^^^^^^^^^^^^^^^^^^^^ + class UndefNode < Node + # Initialize a new UndefNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, names: T::Array[::T.any(SymbolNode, InterpolatedSymbolNode)], keyword_loc: Location).void } + def initialize(source, node_id, location, flags, names, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, names: T::Array[::T.any(SymbolNode, InterpolatedSymbolNode)], keyword_loc: Location).returns(UndefNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), names: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `names` attribute. + sig { returns(T::Array[::T.any(SymbolNode, InterpolatedSymbolNode)]) } + def names; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `unless` keyword, either in the block form or the modifier form. + # + # bar unless foo + # ^^^^^^^^^^^^^^ + # + # unless foo then bar end + # ^^^^^^^^^^^^^^^^^^^^^^^ + class UnlessNode < Node + # Initialize a new UnlessNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, predicate: Node, then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), else_clause: ::T.nilable(ElseNode), end_keyword_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, keyword_loc, predicate, then_keyword_loc, statements, else_clause, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, predicate: Node, then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), else_clause: ::T.nilable(ElseNode), end_keyword_loc: ::T.nilable(Location)).returns(UnlessNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), predicate: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), else_clause: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The Location of the `unless` keyword. + # + # unless cond then bar end + # ^^^^^^ + # + # bar unless cond + # ^^^^^^ + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # 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). + # + # unless cond then bar end + # ^^^^ + # + # bar unless cond + # ^^^^ + sig { returns(Node) } + def predicate; end + + # The Location of the `then` keyword, if present. + # + # unless cond then bar end + # ^^^^ + sig { returns(::T.nilable(Location)) } + def then_keyword_loc; end + + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_then_keyword_loc(repository); end + + # The body of statements that will executed if the unless condition is + # falsey. Will be `nil` if no body is provided. + # + # unless cond then bar end + # ^^^ + sig { returns(::T.nilable(StatementsNode)) } + def statements; end + + # The else clause of the unless expression, if present. + # + # unless cond then bar else baz end + # ^^^^^^^^^^^^ + sig { returns(::T.nilable(ElseNode)) } + def else_clause; end + + # The Location of the `end` keyword, if present. + # + # unless cond then bar end + # ^^^ + sig { returns(::T.nilable(Location)) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_end_keyword_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of then_keyword_loc from the source. + sig { returns(::T.nilable(String)) } + def then_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(::T.nilable(String)) } + def end_keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `until` keyword, either in the block form or the modifier form. + # + # bar until foo + # ^^^^^^^^^^^^^ + # + # until foo do bar end + # ^^^^^^^^^^^^^^^^^^^^ + class UntilNode < Node + # Initialize a new UntilNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), predicate: Node, statements: ::T.nilable(StatementsNode)).void } + def initialize(source, node_id, location, flags, keyword_loc, do_keyword_loc, closing_loc, predicate, statements); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), predicate: Node, statements: ::T.nilable(StatementsNode)).returns(UntilNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), predicate: T.unsafe(nil), statements: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a loop after a begin statement, so the body is executed first before the condition + sig { returns(T::Boolean) } + def begin_modifier?; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the Location represented by `do_keyword_loc`. + sig { returns(::T.nilable(Location)) } + def do_keyword_loc; end + + # Save the do_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_do_keyword_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(::T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Returns the `predicate` attribute. + sig { returns(Node) } + def predicate; end + + # Returns the `statements` attribute. + sig { returns(::T.nilable(StatementsNode)) } + def statements; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of do_keyword_loc from the source. + sig { returns(::T.nilable(String)) } + def do_keyword; end + + # Slice the location of closing_loc from the source. + sig { returns(::T.nilable(String)) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `when` keyword within a case statement. + # + # case true + # when true + # ^^^^^^^^^ + # end + class WhenNode < Node + # Initialize a new WhenNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, conditions: T::Array[Node], then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode)).void } + def initialize(source, node_id, location, flags, keyword_loc, conditions, then_keyword_loc, statements); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, conditions: T::Array[Node], then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode)).returns(WhenNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), conditions: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the `conditions` attribute. + sig { returns(T::Array[Node]) } + def conditions; end + + # Returns the Location represented by `then_keyword_loc`. + sig { returns(::T.nilable(Location)) } + def then_keyword_loc; end + + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_then_keyword_loc(repository); end + + # Returns the `statements` attribute. + sig { returns(::T.nilable(StatementsNode)) } + def statements; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of then_keyword_loc from the source. + sig { returns(::T.nilable(String)) } + def then_keyword; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `while` keyword, either in the block form or the modifier form. + # + # bar while foo + # ^^^^^^^^^^^^^ + # + # while foo do bar end + # ^^^^^^^^^^^^^^^^^^^^ + class WhileNode < Node + # Initialize a new WhileNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), predicate: Node, statements: ::T.nilable(StatementsNode)).void } + def initialize(source, node_id, location, flags, keyword_loc, do_keyword_loc, closing_loc, predicate, statements); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), predicate: Node, statements: ::T.nilable(StatementsNode)).returns(WhileNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), predicate: T.unsafe(nil), statements: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a loop after a begin statement, so the body is executed first before the condition + sig { returns(T::Boolean) } + def begin_modifier?; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the Location represented by `do_keyword_loc`. + sig { returns(::T.nilable(Location)) } + def do_keyword_loc; end + + # Save the do_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_do_keyword_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(::T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Returns the `predicate` attribute. + sig { returns(Node) } + def predicate; end + + # Returns the `statements` attribute. + sig { returns(::T.nilable(StatementsNode)) } + def statements; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of do_keyword_loc from the source. + sig { returns(::T.nilable(String)) } + def do_keyword; end + + # Slice the location of closing_loc from the source. + sig { returns(::T.nilable(String)) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an xstring literal with no interpolation. + # + # `foo` + # ^^^^^ + class XStringNode < Node + # Initialize a new XStringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).void } + def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(XStringNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the Location represented by `content_loc`. + sig { returns(Location) } + def content_loc; end + + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_content_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `unescaped` attribute. + sig { returns(String) } + def unescaped; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of content_loc from the source. + sig { returns(String) } + def content; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `yield` keyword. + # + # yield 1 + # ^^^^^^^ + class YieldNode < Node + # Initialize a new YieldNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), rparen_loc: ::T.nilable(Location)).void } + def initialize(source, node_id, location, flags, keyword_loc, lparen_loc, arguments, rparen_loc); end + + # See Node.accept. + sig { override.params(visitor: Visitor).returns(::T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[::T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[::T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), rparen_loc: ::T.nilable(Location)).returns(YieldNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), arguments: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end + + sig { override.returns(T::Array[::T.nilable(Node)]) } + def deconstruct; end + + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the Location represented by `lparen_loc`. + sig { returns(::T.nilable(Location)) } + def lparen_loc; end + + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_lparen_loc(repository); end + + # Returns the `arguments` attribute. + sig { returns(::T.nilable(ArgumentsNode)) } + def arguments; end + + # Returns the Location represented by `rparen_loc`. + sig { returns(::T.nilable(Location)) } + def rparen_loc; end + + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } + def save_rparen_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of lparen_loc from the source. + sig { returns(::T.nilable(String)) } + def lparen; end + + # Slice the location of rparen_loc from the source. + sig { returns(::T.nilable(String)) } + def rparen; end + + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } + def ===(other); end + end + + # Flags for arguments nodes. + module ArgumentsNodeFlags + # if the arguments contain forwarding + CONTAINS_FORWARDING = T.let(nil, ::T.untyped) + + # if the arguments contain keywords + CONTAINS_KEYWORDS = T.let(nil, ::T.untyped) + + # if the arguments contain a keyword splat + CONTAINS_KEYWORD_SPLAT = T.let(nil, ::T.untyped) + + # if the arguments contain a splat + CONTAINS_SPLAT = T.let(nil, ::T.untyped) + + # if the arguments contain multiple splats + CONTAINS_MULTIPLE_SPLATS = T.let(nil, ::T.untyped) + end + + # Flags for array nodes. + module ArrayNodeFlags + # if array contains splat nodes + CONTAINS_SPLAT = T.let(nil, ::T.untyped) + end + + # Flags for call nodes. + module CallNodeFlags + # &. operator + SAFE_NAVIGATION = T.let(nil, ::T.untyped) + + # a call that could have been a local variable + VARIABLE_CALL = T.let(nil, ::T.untyped) + + # a call that is an attribute write, so the value being written should be returned + ATTRIBUTE_WRITE = T.let(nil, ::T.untyped) + + # a call that ignores method visibility + IGNORE_VISIBILITY = T.let(nil, ::T.untyped) + end + + # Flags for nodes that have unescaped content. + module EncodingFlags + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING = T.let(nil, ::T.untyped) + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING = T.let(nil, ::T.untyped) + end + + # Flags for integer nodes that correspond to the base of the integer. + module IntegerBaseFlags + # 0b prefix + BINARY = T.let(nil, ::T.untyped) + + # 0d or no prefix + DECIMAL = T.let(nil, ::T.untyped) + + # 0o or 0 prefix + OCTAL = T.let(nil, ::T.untyped) + + # 0x prefix + HEXADECIMAL = T.let(nil, ::T.untyped) + end + + # Flags for interpolated string nodes that indicated mutability if they are also marked as literals. + module InterpolatedStringNodeFlags + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + FROZEN = T.let(nil, ::T.untyped) + + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + MUTABLE = T.let(nil, ::T.untyped) + end + + # Flags for keyword hash nodes. + module KeywordHashNodeFlags + # a keyword hash which only has `AssocNode` elements all with symbol keys, which means the elements can be treated as keyword arguments + SYMBOL_KEYS = T.let(nil, ::T.untyped) + end + + # Flags for while and until loop nodes. + module LoopFlags + # a loop after a begin statement, so the body is executed first before the condition + BEGIN_MODIFIER = T.let(nil, ::T.untyped) + end + + # Flags for parameter nodes. + module ParameterFlags + # a parameter name that has been repeated in the method signature + REPEATED_PARAMETER = T.let(nil, ::T.untyped) + end + + # Flags for parentheses nodes. + module ParenthesesNodeFlags + # parentheses that contain multiple potentially void statements + MULTIPLE_STATEMENTS = T.let(nil, ::T.untyped) + end + + # Flags for range and flip-flop nodes. + module RangeFlags + # ... operator + EXCLUDE_END = T.let(nil, ::T.untyped) + end + + # Flags for regular expression and match last line nodes. + module RegularExpressionFlags + # i - ignores the case of characters when matching + IGNORE_CASE = T.let(nil, ::T.untyped) + + # x - ignores whitespace and allows comments in regular expressions + EXTENDED = T.let(nil, ::T.untyped) + + # m - allows $ to match the end of lines within strings + MULTI_LINE = T.let(nil, ::T.untyped) + + # o - only interpolates values into the regular expression once + ONCE = T.let(nil, ::T.untyped) + + # e - forces the EUC-JP encoding + EUC_JP = T.let(nil, ::T.untyped) + + # n - forces the ASCII-8BIT encoding + ASCII_8BIT = T.let(nil, ::T.untyped) + + # s - forces the Windows-31J encoding + WINDOWS_31J = T.let(nil, ::T.untyped) + + # u - forces the UTF-8 encoding + UTF_8 = T.let(nil, ::T.untyped) + + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING = T.let(nil, ::T.untyped) + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING = T.let(nil, ::T.untyped) + + # internal bytes forced the encoding to US-ASCII + FORCED_US_ASCII_ENCODING = T.let(nil, ::T.untyped) + end + + # Flags for shareable constant nodes. + module ShareableConstantNodeFlags + # constant writes that should be modified with shareable constant value literal + LITERAL = T.let(nil, ::T.untyped) + + # constant writes that should be modified with shareable constant value experimental everything + EXPERIMENTAL_EVERYTHING = T.let(nil, ::T.untyped) + + # constant writes that should be modified with shareable constant value experimental copy + EXPERIMENTAL_COPY = T.let(nil, ::T.untyped) + end + + # Flags for string nodes. + module StringFlags + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING = T.let(nil, ::T.untyped) + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING = T.let(nil, ::T.untyped) + + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal` + FROZEN = T.let(nil, ::T.untyped) + + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` + MUTABLE = T.let(nil, ::T.untyped) + end + + # Flags for symbol nodes. + module SymbolFlags + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING = T.let(nil, ::T.untyped) + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING = T.let(nil, ::T.untyped) + + # internal bytes forced the encoding to US-ASCII + FORCED_US_ASCII_ENCODING = T.let(nil, ::T.untyped) + 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 = T.let(nil, 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(nil, Integer) + end +end diff --git a/rbi/generated/prism/node_ext.rbi b/rbi/generated/prism/node_ext.rbi new file mode 100644 index 0000000000..25255d073b --- /dev/null +++ b/rbi/generated/prism/node_ext.rbi @@ -0,0 +1,333 @@ +# typed: true + +module Prism + class Node + abstract! + + sig { params(replacements: String).void } + def deprecated(*replacements); end + end + + module RegularExpressionOptions + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + sig { params(flags: Integer).returns(Integer) } + def self.options(flags); end + end + + class InterpolatedMatchLastLineNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + sig { returns(Integer) } + def options; end + end + + class InterpolatedRegularExpressionNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + sig { returns(Integer) } + def options; end + end + + class MatchLastLineNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + sig { returns(Integer) } + def options; end + end + + class RegularExpressionNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + sig { returns(Integer) } + def options; end + end + + module HeredocQuery + # Returns true if this node was represented as a heredoc in the source code. + sig { params(opening: ::T.nilable(String)).returns(::T.nilable(T::Boolean)) } + def self.heredoc?(opening); end + end + + class InterpolatedStringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + sig { returns(::T.nilable(T::Boolean)) } + def heredoc?; end + end + + class InterpolatedXStringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + sig { returns(::T.nilable(T::Boolean)) } + def heredoc?; end + end + + class StringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + sig { returns(::T.nilable(T::Boolean)) } + def heredoc?; end + + # Occasionally it's helpful to treat a string as if it were interpolated so + # that there's a consistent interface for working with strings. + sig { returns(InterpolatedStringNode) } + def to_interpolated; end + end + + class XStringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + sig { returns(::T.nilable(T::Boolean)) } + def heredoc?; end + + # Occasionally it's helpful to treat a string as if it were interpolated so + # that there's a consistent interface for working with strings. + sig { returns(InterpolatedXStringNode) } + def to_interpolated; end + end + + class ImaginaryNode < Node + # Returns the value of the node as a Ruby Complex. + sig { returns(Complex) } + def value; end + end + + class RationalNode < Node + # Returns the value of the node as a Ruby Rational. + sig { returns(Rational) } + def value; end + + # Returns the value of the node as an IntegerNode or a FloatNode. This + # method is deprecated in favor of #value or #numerator/#denominator. + sig { returns(::T.any(IntegerNode, FloatNode)) } + def numeric; end + end + + class ConstantReadNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + sig { returns(T::Array[Symbol]) } + def full_name_parts; end + + # Returns the full name of this constant. For example: "Foo" + sig { returns(String) } + def full_name; end + end + + class ConstantWriteNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + sig { returns(T::Array[Symbol]) } + def full_name_parts; end + + # Returns the full name of this constant. For example: "Foo" + sig { returns(String) } + def full_name; end + end + + class ConstantPathNode < Node + # An error class raised when dynamic parts are found while computing a + # constant path's full name. For example: + # Foo::Bar::Baz -> does not raise because all parts of the constant path are + # simple constants + # var::Bar::Baz -> raises because the first part of the constant path is a + # local variable + class DynamicPartsInConstantPathError < StandardError; end + + # An error class raised when missing nodes are found while computing a + # constant path's full name. For example: + # Foo:: -> raises because the constant path is missing the last part + class MissingNodesInConstantPathError < StandardError; end + + # Returns the list of parts for the full name of this constant path. + # For example: [:Foo, :Bar] + sig { returns(T::Array[Symbol]) } + def full_name_parts; end + + # Returns the full name of this constant path. For example: "Foo::Bar" + sig { returns(String) } + def full_name; end + + # Previously, we had a child node on this class that contained either a + # constant read or a missing node. To not cause a breaking change, we + # continue to supply that API. + sig { returns(::T.any(ConstantReadNode, MissingNode)) } + def child; end + end + + class ConstantPathTargetNode < Node + # Returns the list of parts for the full name of this constant path. + # For example: [:Foo, :Bar] + sig { returns(T::Array[Symbol]) } + def full_name_parts; end + + # Returns the full name of this constant path. For example: "Foo::Bar" + sig { returns(String) } + def full_name; end + + # Previously, we had a child node on this class that contained either a + # constant read or a missing node. To not cause a breaking change, we + # continue to supply that API. + sig { returns(::T.any(ConstantReadNode, MissingNode)) } + def child; end + end + + class ConstantTargetNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + sig { returns(T::Array[Symbol]) } + def full_name_parts; end + + # Returns the full name of this constant. For example: "Foo" + sig { returns(String) } + def full_name; end + end + + class ParametersNode < Node + # Mirrors the Method#parameters method. + sig { returns(T::Array[::T.any([Symbol, Symbol], [Symbol])]) } + def signature; 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. + sig { returns(::T.nilable(Location)) } + def full_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. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def 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. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def 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. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def 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. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def 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. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def 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. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def 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. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def 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. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def 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. + sig { returns(::T.nilable(ElseNode)) } + def consequent; end + end + + class CaseNode < Node + # Returns the else clause of the case node. This method is deprecated in + # favor of #else_clause. + sig { returns(::T.nilable(ElseNode)) } + def consequent; end + end + + class IfNode < Node + # Returns the subsequent if/elsif/else clause of the if node. This method is + # deprecated in favor of #subsequent. + sig { returns(::T.nilable(::T.any(IfNode, ElseNode))) } + def consequent; end + end + + class RescueNode < Node + # Returns the subsequent rescue clause of the rescue node. This method is + # deprecated in favor of #subsequent. + sig { returns(::T.nilable(RescueNode)) } + def consequent; end + end + + class UnlessNode < Node + # Returns the else clause of the unless node. This method is deprecated in + # favor of #else_clause. + sig { returns(::T.nilable(ElseNode)) } + def consequent; end + end +end diff --git a/rbi/generated/prism/parse_result.rbi b/rbi/generated/prism/parse_result.rbi new file mode 100644 index 0000000000..ddced69934 --- /dev/null +++ b/rbi/generated/prism/parse_result.rbi @@ -0,0 +1,738 @@ +# typed: true + +module Prism + # This represents a source of Ruby code that has been parsed. It is used in + # conjunction with locations to allow them to resolve line numbers and source + # ranges. + class Source + # Create a new source object with the given source code. This method should + # be used instead of `new` and it will return either a `Source` or a + # specialized and more performant `ASCIISource` if no multibyte characters + # are present in the source code. + # + # Note that if you are calling this method manually, you will need to supply + # the start_line and offsets parameters. start_line is the line number that + # the source starts on, which is typically 1 but can be different if this + # source is a subset of a larger source or if this is an eval. offsets is an + # array of byte offsets for the start of each line in the source code, which + # can be calculated by iterating through the source code and recording the + # byte offset whenever a newline character is encountered. + sig { params(source: String, start_line: Integer, offsets: T::Array[Integer]).returns(Source) } + def self.for(source, start_line, offsets); end + + # The source code that this source object represents. + sig { returns(String) } + attr_reader :source + + # The line number where this source starts. + sig { returns(Integer) } + attr_reader :start_line + + # The list of newline byte offsets in the source code. + sig { returns(T::Array[Integer]) } + attr_reader :offsets + + # Create a new source object with the given source code. + sig { params(source: String, start_line: Integer, offsets: T::Array[Integer]).void } + def initialize(source, start_line, offsets); end + + # Replace the value of start_line with the given value. + sig { params(start_line: Integer).void } + def replace_start_line(start_line); end + + # Replace the value of offsets with the given value. + sig { params(offsets: T::Array[Integer]).void } + def replace_offsets(offsets); end + + # Returns the encoding of the source code, which is set by parameters to the + # parser or by the encoding magic comment. + sig { returns(Encoding) } + def encoding; end + + # Returns the lines of the source code as an array of strings. + sig { returns(T::Array[String]) } + def lines; end + + # Perform a byteslice on the source code using the given byte offset and + # byte length. + sig { params(byte_offset: Integer, length: Integer).returns(String) } + def slice(byte_offset, length); end + + # Converts the line number and column in bytes to a byte offset. + sig { params(line: Integer, column: Integer).returns(Integer) } + def byte_offset(line, column); end + + # Binary search through the offsets to find the line number for the given + # byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def line(byte_offset); end + + # Return the byte offset of the start of the line corresponding to the given + # byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def line_start(byte_offset); end + + # Returns the byte offset of the end of the line corresponding to the given + # byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def line_end(byte_offset); end + + # Return the column in bytes for the given byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def column(byte_offset); end + + # Return the character offset for the given byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def character_offset(byte_offset); end + + # Return the column in characters for the given byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def character_column(byte_offset); end + + # Returns the offset from the start of the file for the given byte offset + # counting in code units for the given encoding. + # + # 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. + sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } + def code_units_offset(byte_offset, encoding); end + + # Generate a cache that targets a specific encoding for calculating code + # unit offsets. + sig { params(encoding: Encoding).returns(CodeUnitsCache) } + def code_units_cache(encoding); end + + # Returns the column in code units for the given encoding for the + # given byte offset. + sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } + def code_units_column(byte_offset, encoding); end + + # Freeze this object and the objects it contains. + sig { void } + def deep_freeze; end + + # Binary search through the offsets to find the line number for the given + # byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + private 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 + sig { params(source: String, encoding: Encoding).void } + def initialize(source, encoding); end + + sig { params(byte_offset: Integer, byte_length: Integer).returns(Integer) } + def count(byte_offset, byte_length); end + end + + class LengthCounter + sig { params(source: String, encoding: Encoding).void } + def initialize(source, encoding); end + + sig { params(byte_offset: Integer, byte_length: Integer).returns(Integer) } + def count(byte_offset, byte_length); end + end + + # Initialize a new cache with the given source and encoding. + sig { params(source: String, encoding: Encoding).void } + def initialize(source, encoding); end + + # Retrieve the code units offset from the given byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def [](byte_offset); 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. + # + # 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. + sig { params(byte_offset: Integer).returns(Integer) } + def character_offset(byte_offset); end + + # Return the column in characters for the given byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def character_column(byte_offset); end + + # Returns the offset from the start of the file for the given byte offset + # counting in code units for the given encoding. + # + # 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. + sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } + def code_units_offset(byte_offset, encoding); 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. + sig { params(encoding: Encoding).returns(::T.untyped) } + def code_units_cache(encoding); end + + # Specialized version of `code_units_column` that does not depend on + # `code_units_offset`, which is a more expensive operation. This is + # essentially the same as `Prism::Source#column`. + sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } + def code_units_column(byte_offset, encoding); end + end + + # This represents a location in the source. + class Location + # A Source object that is used to determine more information from the given + # offset and length. + sig { returns(Source) } + attr_reader :source + + # The byte offset from the beginning of the source where this location + # starts. + sig { returns(Integer) } + attr_reader :start_offset + + # The length of this location in bytes. + sig { returns(Integer) } + attr_reader :length + + # Create a new location object with the given source, start byte offset, and + # byte length. + sig { params(source: Source, start_offset: Integer, length: Integer).void } + def initialize(source, start_offset, length); end + + # These are the comments that are associated with this location that exist + # before the start of this location. + sig { returns(T::Array[Comment]) } + def leading_comments; end + + # Attach a comment to the leading comments of this location. + sig { params(comment: Comment).void } + def leading_comment(comment); end + + # These are the comments that are associated with this location that exist + # after the end of this location. + sig { returns(T::Array[Comment]) } + def trailing_comments; end + + # Attach a comment to the trailing comments of this location. + sig { params(comment: Comment).void } + def trailing_comment(comment); end + + # Returns all comments that are associated with this location (both leading + # and trailing comments). + sig { returns(T::Array[Comment]) } + def comments; end + + # Create a new location object with the given options. + sig { params(source: Source, start_offset: Integer, length: Integer).returns(Location) } + def copy(source: T.unsafe(nil), start_offset: T.unsafe(nil), length: T.unsafe(nil)); end + + # Returns a new location that is the result of chopping off the last byte. + sig { returns(Location) } + def chop; end + + # Returns a string representation of this location. + sig { returns(String) } + def inspect; end + + # Returns all of the lines of the source code associated with this location. + sig { returns(T::Array[String]) } + def source_lines; end + + # The source code that this location represents. + sig { returns(String) } + def slice; end + + # The source code that this location represents starting from the beginning + # of the line that this location starts on to the end of the line that this + # location ends on. + sig { returns(String) } + def slice_lines; end + + # The character offset from the beginning of the source where this location + # starts. + sig { returns(Integer) } + def start_character_offset; end + + # The offset from the start of the file in code units of the given encoding. + sig { params(encoding: Encoding).returns(Integer) } + def start_code_units_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. + sig { params(cache: ::T.untyped).returns(Integer) } + def cached_start_code_units_offset(cache); end + + # The byte offset from the beginning of the source where this location ends. + sig { returns(Integer) } + def end_offset; end + + # The character offset from the beginning of the source where this location + # ends. + sig { returns(Integer) } + def end_character_offset; end + + # The offset from the start of the file in code units of the given encoding. + sig { params(encoding: Encoding).returns(Integer) } + def end_code_units_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. + sig { params(cache: ::T.untyped).returns(Integer) } + def cached_end_code_units_offset(cache); end + + # The line number where this location starts. + sig { returns(Integer) } + def start_line; end + + # The content of the line where this location starts before this location. + sig { returns(String) } + def start_line_slice; end + + # The line number where this location ends. + sig { returns(Integer) } + def end_line; end + + # The column in bytes where this location starts from the start of + # the line. + sig { returns(Integer) } + def start_column; end + + # The column in characters where this location ends from the start of + # the line. + sig { returns(Integer) } + def start_character_column; end + + # The column in code units of the given encoding where this location + # starts from the start of the line. + sig { params(encoding: Encoding).returns(Integer) } + def start_code_units_column(encoding = T.unsafe(nil)); end + + # The start column in code units using the given cache to fetch or calculate + # the value. + sig { params(cache: ::T.untyped).returns(Integer) } + def cached_start_code_units_column(cache); end + + # The column in bytes where this location ends from the start of the + # line. + sig { returns(Integer) } + def end_column; end + + # The column in characters where this location ends from the start of + # the line. + sig { returns(Integer) } + def end_character_column; end + + # The column in code units of the given encoding where this location + # ends from the start of the line. + sig { params(encoding: Encoding).returns(Integer) } + def end_code_units_column(encoding = T.unsafe(nil)); end + + # The end column in code units using the given cache to fetch or calculate + # the value. + sig { params(cache: ::T.untyped).returns(Integer) } + def cached_end_code_units_column(cache); end + + # Implement the hash pattern matching interface for Location. + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # Implement the pretty print interface for Location. + sig { params(q: PP).void } + def pretty_print(q); end + + # Returns true if the given other location is equal to this location. + sig { params(other: ::T.untyped).returns(T::Boolean) } + def ==(other); end + + # Returns a new location that stretches from this location to the given + # other location. Raises an error if this location is not before the other + # location or if they don't share the same source. + sig { params(other: Location).returns(Location) } + def join(other); end + + # Join this location with the first occurrence of the string in the source + # that occurs after this location on the same line, and return the new + # location. This will raise an error if the string does not exist. + sig { params(string: String).returns(Location) } + def adjoin(string); end + end + + # This represents a comment that was encountered during parsing. It is the + # base class for all comment types. + class Comment + # The Location of this comment in the source. + sig { returns(Location) } + attr_reader :location + + # Create a new comment object with the given location. + sig { params(location: Location).void } + def initialize(location); end + + # Implement the hash pattern matching interface for Comment. + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # Returns the content of the comment by slicing it from the source code. + sig { returns(String) } + def slice; end + + # Returns true if this comment happens on the same line as other code and + # false if the comment is by itself. This can only be true for inline + # comments and should be false for block comments. + sig { returns(T::Boolean) } + def trailing?; end + end + + # InlineComment objects are the most common. They correspond to comments in + # the source file like this one that start with #. + class InlineComment < Comment + # Returns true if this comment happens on the same line as other code and + # false if the comment is by itself. + sig { returns(T::Boolean) } + def trailing?; end + + # Returns a string representation of this comment. + sig { returns(String) } + def inspect; end + end + + # EmbDocComment objects correspond to comments that are surrounded by =begin + # and =end. + class EmbDocComment < Comment + # Returns false. This can only be true for inline comments. + sig { returns(T::Boolean) } + def trailing?; end + + # Returns a string representation of this comment. + sig { returns(String) } + def inspect; end + end + + # This represents a magic comment that was encountered during parsing. + class MagicComment + # A Location object representing the location of the key in the source. + sig { returns(Location) } + attr_reader :key_loc + + # A Location object representing the location of the value in the source. + sig { returns(Location) } + attr_reader :value_loc + + # Create a new magic comment object with the given key and value locations. + sig { params(key_loc: Location, value_loc: Location).void } + def initialize(key_loc, value_loc); end + + # Returns the key of the magic comment by slicing it from the source code. + sig { returns(String) } + def key; end + + # Returns the value of the magic comment by slicing it from the source code. + sig { returns(String) } + def value; end + + # Implement the hash pattern matching interface for MagicComment. + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # Returns a string representation of this magic comment. + sig { returns(String) } + def inspect; end + end + + # This represents an error that was encountered during parsing. + class ParseError + # The type of error. This is an _internal_ symbol that is used for + # communicating with translation layers. It is not meant to be public API. + sig { returns(Symbol) } + attr_reader :type + + # The message associated with this error. + sig { returns(String) } + attr_reader :message + + # A Location object representing the location of this error in the source. + sig { returns(Location) } + attr_reader :location + + # The level of this error. + sig { returns(Symbol) } + attr_reader :level + + # Create a new error object with the given message and location. + sig { params(type: Symbol, message: String, location: Location, level: Symbol).void } + def initialize(type, message, location, level); end + + # Implement the hash pattern matching interface for ParseError. + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # Returns a string representation of this error. + sig { returns(String) } + def inspect; end + end + + # This represents a warning that was encountered during parsing. + class ParseWarning + # The type of warning. This is an _internal_ symbol that is used for + # communicating with translation layers. It is not meant to be public API. + sig { returns(Symbol) } + attr_reader :type + + # The message associated with this warning. + sig { returns(String) } + attr_reader :message + + # A Location object representing the location of this warning in the source. + sig { returns(Location) } + attr_reader :location + + # The level of this warning. + sig { returns(Symbol) } + attr_reader :level + + # Create a new warning object with the given message and location. + sig { params(type: Symbol, message: String, location: Location, level: Symbol).void } + def initialize(type, message, location, level); end + + # Implement the hash pattern matching interface for ParseWarning. + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # Returns a string representation of this warning. + sig { returns(String) } + def inspect; end + end + + # This represents the result of a call to Prism.parse or Prism.parse_file. + # It contains the requested structure, any comments that were encounters, + # and any errors that were encountered. + class Result + # The list of comments that were encountered during parsing. + sig { returns(T::Array[Comment]) } + attr_reader :comments + + # The list of magic comments that were encountered during parsing. + sig { returns(T::Array[MagicComment]) } + attr_reader :magic_comments + + # An optional location that represents the location of the __END__ marker + # and the rest of the content of the file. This content is loaded into the + # DATA constant when the file being parsed is the main file being executed. + sig { returns(::T.nilable(Location)) } + attr_reader :data_loc + + # The list of errors that were generated during parsing. + sig { returns(T::Array[ParseError]) } + attr_reader :errors + + # The list of warnings that were generated during parsing. + sig { returns(T::Array[ParseWarning]) } + attr_reader :warnings + + # A Source instance that represents the source code that was parsed. + sig { returns(Source) } + attr_reader :source + + # Create a new result object with the given values. + sig { params(comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], continuable: T::Boolean, source: Source).void } + def initialize(comments, magic_comments, data_loc, errors, warnings, continuable, source); end + + # Implement the hash pattern matching interface for Result. + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # Returns the encoding of the source code that was parsed. + sig { returns(Encoding) } + def encoding; end + + # Returns true if there were no errors during parsing and false if there + # were. + sig { returns(T::Boolean) } + def success?; end + + # Returns true if there were errors during parsing and false if there were + # not. + sig { returns(T::Boolean) } + def failure?; end + + # Returns true if the parsed source is an incomplete expression that could + # become valid with additional input. This is useful for REPL contexts (such + # as IRB) where the user may be entering a multi-line expression one line at + # a time and the implementation needs to determine whether to wait for more + # input or to evaluate what has been entered so far. + # + # Concretely, this returns true when every error present is caused by the + # parser reaching the end of the input before a construct was closed (e.g. + # an unclosed string, array, block, or keyword), and returns false when any + # error is caused by a token that makes the input structurally invalid + # regardless of what might follow (e.g. a stray `end`, `]`, or `)` with no + # matching opener). + # + # Examples: + # + # Prism.parse("1 + [").continuable? #=> true (unclosed array) + # Prism.parse("1 + ]").continuable? #=> false (stray ]) + # Prism.parse("tap do").continuable? #=> true (unclosed block) + # Prism.parse("end.tap do").continuable? #=> false (stray end) + # + sig { returns(T::Boolean) } + def continuable?; end + + # Create a code units cache for the given encoding. + sig { params(encoding: Encoding).returns(::T.untyped) } + def code_units_cache(encoding); end + end + + # This is a result specific to the `parse` and `parse_file` methods. + class ParseResult < Result + # The syntax tree that was parsed from the source code. + sig { returns(ProgramNode) } + attr_reader :value + + # Create a new parse result object with the given values. + sig { params(value: ProgramNode, comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], continuable: T::Boolean, source: Source).void } + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source); end + + # Implement the hash pattern matching interface for ParseResult. + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # Attach the list of comments to their respective locations in the tree. + sig { void } + def attach_comments!; end + + # Walk the tree and mark nodes that are on a new line, loosely emulating + # the behavior of CRuby's `:line` tracepoint event. + sig { void } + def mark_newlines!; end + + # Returns a string representation of the syntax tree with the errors + # displayed inline. + sig { returns(String) } + def errors_format; end + end + + # This is a result specific to the `lex` and `lex_file` methods. + class LexResult < Result + # The list of tokens that were parsed from the source code. + sig { returns(T::Array[[Token, Integer]]) } + attr_reader :value + + # Create a new lex result object with the given values. + sig { params(value: T::Array[[Token, Integer]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], continuable: T::Boolean, source: Source).void } + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source); end + + # Implement the hash pattern matching interface for LexResult. + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + end + + # This is a result specific to the `parse_lex` and `parse_lex_file` methods. + class ParseLexResult < Result + # A tuple of the syntax tree and the list of tokens that were parsed from + # the source code. + sig { returns([ProgramNode, T::Array[[Token, Integer]]]) } + attr_reader :value + + # Create a new parse lex result object with the given values. + sig { params(value: [ProgramNode, T::Array[[Token, Integer]]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], continuable: T::Boolean, source: Source).void } + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source); end + + # Implement the hash pattern matching interface for ParseLexResult. + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + end + + # This represents a token from the Ruby source. + class Token + # The Source object that represents the source this token came from. + sig { returns(Source) } + attr_reader :source + + # The type of token that this token is. + sig { returns(Symbol) } + attr_reader :type + + # A byteslice of the source that this token represents. + sig { returns(String) } + attr_reader :value + + # Create a new token object with the given type, value, and location. + sig { params(source: Source, type: Symbol, value: String, location: ::T.any(Location, Integer)).void } + def initialize(source, type, value, location); end + + # Implement the hash pattern matching interface for Token. + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } + def deconstruct_keys(keys); end + + # A Location object representing the location of this token in the source. + sig { returns(Location) } + def location; end + + # Implement the pretty print interface for Token. + sig { params(q: PP).void } + def pretty_print(q); end + + # Returns true if the given other token is equal to this token. + sig { params(other: ::T.untyped).returns(T::Boolean) } + def ==(other); end + + # Returns a string representation of this token. + sig { returns(String) } + def inspect; end + + # Freeze this object and the objects it contains. + sig { void } + def deep_freeze; end + end + + # This object is passed to the various Prism.* methods that accept the + # `scopes` option as an element of the list. It defines both the local + # variables visible at that scope as well as the forwarding parameters + # available at that scope. + class Scope + # The list of local variables that are defined in this scope. This should be + # defined as an array of symbols. + sig { returns(T::Array[Symbol]) } + attr_reader :locals + + # The list of local variables that are forwarded to the next scope. This + # should by defined as an array of symbols containing the specific values of + sig { returns(T::Array[Symbol]) } + attr_reader :forwarding + + # Create a new scope object with the given locals and forwarding. + sig { params(locals: T::Array[Symbol], forwarding: T::Array[Symbol]).void } + def initialize(locals, forwarding); end + end + + # Create a new scope with the given locals and forwarding options that is + # suitable for passing into one of the Prism.* methods that accepts the + # `scopes` option. + sig { params(locals: T::Array[Symbol], forwarding: T::Array[Symbol]).returns(Scope) } + def self.scope(locals: T.unsafe(nil), forwarding: T.unsafe(nil)); end +end diff --git a/rbi/generated/prism/parse_result/comments.rbi b/rbi/generated/prism/parse_result/comments.rbi new file mode 100644 index 0000000000..f386d03f34 --- /dev/null +++ b/rbi/generated/prism/parse_result/comments.rbi @@ -0,0 +1,90 @@ +# typed: true + +module Prism + 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. + # + # It does this by first finding the nearest locations to each comment. + # Locations can either come from nodes directly or from location fields on + # nodes. For example, a `ClassNode` has an overall location encompassing the + # entire class, but it also has a location for the `class` keyword. + # + # Once the nearest locations are found, it determines which one to attach + # to. If it's a trailing comment (a comment on the same line as other source + # code), it will favor attaching to the nearest location that occurs before + # the comment. Otherwise it will favor attaching to the nearest location + # that is after the comment. + class Comments + # A target for attaching comments that is based on a specific node's + # location. + class NodeTarget + sig { returns(Node) } + attr_reader :node + + sig { params(node: Node).void } + def initialize(node); end + + sig { returns(Integer) } + def start_offset; end + + sig { returns(Integer) } + def end_offset; end + + sig { params(comment: Comment).returns(T::Boolean) } + def encloses?(comment); end + + sig { params(comment: Comment).void } + def leading_comment(comment); end + + sig { params(comment: Comment).void } + def trailing_comment(comment); end + end + + # A target for attaching comments that is based on a location field on a + # node. For example, the `end` token of a ClassNode. + class LocationTarget + sig { returns(Location) } + attr_reader :location + + sig { params(location: Location).void } + def initialize(location); end + + sig { returns(Integer) } + def start_offset; end + + sig { returns(Integer) } + def end_offset; end + + sig { params(comment: Comment).returns(T::Boolean) } + def encloses?(comment); end + + sig { params(comment: Comment).void } + def leading_comment(comment); end + + sig { params(comment: Comment).void } + def trailing_comment(comment); end + end + + # The parse result that we are attaching comments to. + sig { returns(ParseResult) } + attr_reader :parse_result + + # Create a new Comments object that will attach comments to the given + # parse result. + sig { params(parse_result: ParseResult).void } + def initialize(parse_result); end + + # Attach the comments to their respective locations in the tree by + # mutating the parse result. + sig { void } + def attach!; end + + # Responsible for finding the nearest targets to the given comment within + # the context of the given encapsulating node. + sig { params(node: Node, comment: Comment).returns([::T.untyped, ::T.untyped, ::T.untyped]) } + private def nearest_targets(node, comment); end + end + end +end diff --git a/rbi/generated/prism/parse_result/errors.rbi b/rbi/generated/prism/parse_result/errors.rbi new file mode 100644 index 0000000000..f864a3f8c2 --- /dev/null +++ b/rbi/generated/prism/parse_result/errors.rbi @@ -0,0 +1,21 @@ +# typed: true + +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. + sig { returns(ParseResult) } + attr_reader :parse_result + + # Initialize a new set of errors from the given parse result. + sig { params(parse_result: ParseResult).void } + def initialize(parse_result); end + + # Formats the errors in a human-readable way and return them as a string. + sig { returns(String) } + def format; end + end + end +end diff --git a/rbi/generated/prism/parse_result/newlines.rbi b/rbi/generated/prism/parse_result/newlines.rbi new file mode 100644 index 0000000000..f77dee3bbf --- /dev/null +++ b/rbi/generated/prism/parse_result/newlines.rbi @@ -0,0 +1,121 @@ +# typed: true + +module Prism + 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: + # + # * if statements + # * unless statements + # * nodes that are children of statements lists + # + # In order to keep track of the newlines, we have a list of offsets that + # come back from the parser. We assign these offsets to the first nodes that + # we find in the tree that are on those lines. + # + # 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. + sig { params(lines: Integer).void } + def initialize(lines); end + + # Permit block nodes to mark newlines within themselves. + sig { params(node: BlockNode).void } + def visit_block_node(node); end + + # Permit lambda nodes to mark newlines within themselves. + sig { params(node: LambdaNode).void } + def visit_lambda_node(node); end + + # Mark if nodes as newlines. + sig { params(node: IfNode).void } + def visit_if_node(node); end + + # Mark unless nodes as newlines. + sig { params(node: UnlessNode).void } + def visit_unless_node(node); end + + # Permit statements lists to mark newlines within themselves. + sig { params(node: StatementsNode).void } + def visit_statements_node(node); end + end + end + + class Node + abstract! + + sig { returns(T::Boolean) } + def newline_flag?; end + + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class BeginNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class ParenthesesNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class IfNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class UnlessNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class UntilNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class WhileNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class RescueModifierNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class InterpolatedMatchLastLineNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class InterpolatedRegularExpressionNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class InterpolatedStringNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class InterpolatedSymbolNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class InterpolatedXStringNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end +end diff --git a/rbi/generated/prism/pattern.rbi b/rbi/generated/prism/pattern.rbi new file mode 100644 index 0000000000..375518b8f7 --- /dev/null +++ b/rbi/generated/prism/pattern.rbi @@ -0,0 +1,134 @@ +# typed: true + +module Prism + # A pattern is an object that wraps a Ruby pattern matching expression. The + # expression would normally be passed to an `in` clause within a `case` + # expression or a rightward assignment expression. For example, in the + # following snippet: + # + # case node + # in ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]] + # end + # + # the pattern is the ConstantPathNode[...] expression. + # + # The pattern gets compiled into an object that responds to #call by running + # the #compile method. This method itself will run back through Prism to + # parse the expression into a tree, then walk the tree to generate the + # necessary callable objects. For example, if you wanted to compile the + # expression above into a callable, you would: + # + # callable = Prism::Pattern.new("ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]]").compile + # callable.call(node) + # + # The callable object returned by #compile is guaranteed to respond to #call + # with a single argument, which is the node to match against. It also is + # guaranteed to respond to #===, which means it itself can be used in a `case` + # expression, as in: + # + # case node + # when callable + # end + # + # If the query given to the initializer cannot be compiled into a valid + # matcher (either because of a syntax error or because it is using syntax we + # do not yet support) then a Prism::Pattern::CompilationError will be + # raised. + class Pattern + # Raised when the query given to a pattern is either invalid Ruby syntax or + # is using syntax that we don't yet support. + class CompilationError < StandardError + # Create a new CompilationError with the given representation of the node + # that caused the error. + sig { params(repr: String).void } + def initialize(repr); end + end + + # The query that this pattern was initialized with. + sig { returns(String) } + attr_reader :query + + # Create a new pattern with the given query. The query should be a string + # containing a Ruby pattern matching expression. + sig { params(query: String).void } + def initialize(query); end + + # Compile the query into a callable object that can be used to match against + # nodes. + sig { returns(Proc) } + def compile; end + + # Scan the given node and all of its children for nodes that match the + # pattern. If a block is given, it will be called with each node that + # matches the pattern. If no block is given, an enumerator will be returned + # that will yield each node that matches the pattern. + sig { params(root: Node).returns(T::Enumerator[Node]) } + sig { params(root: Node, blk: ::T.proc.params(arg0: Node).void).void } + def scan(root, &blk); end + + # Shortcut for combining two procs into one that returns true if both return + # true. + sig { params(left: Proc, right: Proc).returns(Proc) } + private def combine_and(left, right); end + + # Shortcut for combining two procs into one that returns true if either + # returns true. + sig { params(left: Proc, right: Proc).returns(Proc) } + private def combine_or(left, right); end + + # Raise an error because the given node is not supported. Note purposefully + # not typing this method since it is a no return method that Steep does not + # understand. + sig { params(node: Node).returns(::T.noreturn) } + private def compile_error(node); end + + # in [foo, bar, baz] + sig { params(node: ArrayPatternNode).returns(Proc) } + private def compile_array_pattern_node(node); end + + # in foo | bar + sig { params(node: AlternationPatternNode).returns(Proc) } + private def compile_alternation_pattern_node(node); end + + # in Prism::ConstantReadNode + sig { params(node: ConstantPathNode).returns(Proc) } + private def compile_constant_path_node(node); end + + # in ConstantReadNode + # in String + sig { params(node: ConstantReadNode).returns(Proc) } + private def compile_constant_read_node(node); end + + # Compile a name associated with a constant. + sig { params(node: ::T.any(ConstantPathNode, ConstantReadNode), name: Symbol).returns(Proc) } + private def compile_constant_name(node, name); end + + # in InstanceVariableReadNode[name: Symbol] + # in { name: Symbol } + sig { params(node: HashPatternNode).returns(Proc) } + private def compile_hash_pattern_node(node); end + + # in nil + sig { params(node: NilNode).returns(Proc) } + private def compile_nil_node(node); end + + # in /foo/ + sig { params(node: RegularExpressionNode).returns(Proc) } + private def compile_regular_expression_node(node); end + + # in "" + # in "foo" + sig { params(node: StringNode).returns(Proc) } + private def compile_string_node(node); end + + # in :+ + # in :foo + sig { params(node: SymbolNode).returns(Proc) } + private def compile_symbol_node(node); end + + # Compile any kind of node. Dispatch out to the individual compilation + # methods based on the type of node. + sig { params(node: Node).returns(Proc) } + private def compile_node(node); end + end +end diff --git a/rbi/generated/prism/reflection.rbi b/rbi/generated/prism/reflection.rbi new file mode 100644 index 0000000000..1094c461f4 --- /dev/null +++ b/rbi/generated/prism/reflection.rbi @@ -0,0 +1,89 @@ +# typed: true + +module Prism + # The Reflection module provides the ability to reflect on the structure of + # the syntax tree itself, as opposed to looking at a single syntax tree. This + # is useful in metaprogramming contexts. + module Reflection + # A field represents a single piece of data on a node. It is the base class + # for all other field types. + class Field + # The name of the field. + sig { returns(Symbol) } + attr_reader :name + + # Initializes the field with the given name. + sig { params(name: Symbol).void } + def initialize(name); end + end + + # A node field represents a single child node in the syntax tree. It + # resolves to a Prism::Node in Ruby. + class NodeField < Field; end + + # An optional node field represents a single child node in the syntax tree + # that may or may not be present. It resolves to either a Prism::Node or nil + # in Ruby. + class OptionalNodeField < Field; end + + # A node list field represents a list of child nodes in the syntax tree. It + # resolves to an array of Prism::Node instances in Ruby. + class NodeListField < Field; end + + # A constant field represents a constant value on a node. Effectively, it + # represents an identifier found within the source. It resolves to a symbol + # in Ruby. + class ConstantField < Field; end + + # An optional constant field represents a constant value on a node that may + # or may not be present. It resolves to either a symbol or nil in Ruby. + class OptionalConstantField < Field; end + + # A constant list field represents a list of constant values on a node. It + # resolves to an array of symbols in Ruby. + class ConstantListField < Field; end + + # A string field represents a string value on a node. It almost always + # represents the unescaped value of a string-like literal. It resolves to a + # string in Ruby. + class StringField < Field; end + + # A location field represents the location of some part of the node in the + # source code. For example, the location of a keyword or an operator. It + # resolves to a Prism::Location in Ruby. + class LocationField < Field; end + + # An optional location field represents the location of some part of the + # node in the source code that may or may not be present. It resolves to + # either a Prism::Location or nil in Ruby. + class OptionalLocationField < Field; end + + # An integer field represents an integer value. It is used to represent the + # value of an integer literal, the depth of local variables, and the number + # of a numbered reference. It resolves to an Integer in Ruby. + class IntegerField < Field; end + + # A float field represents a double-precision floating point value. It is + # used exclusively to represent the value of a floating point literal. It + # resolves to a Float in Ruby. + class FloatField < Field; end + + # A flags field represents a bitset of flags on a node. It resolves to an + # integer in Ruby. Note that the flags cannot be accessed directly on the + # node because the integer is kept private. Instead, the various flags in + # the bitset should be accessed through their query methods. + class FlagsField < Field + # The names of the flags in the bitset. + sig { returns(T::Array[Symbol]) } + attr_reader :flags + + # Initializes the flags field with the given name and flags. + sig { params(name: Symbol, flags: T::Array[Symbol]).void } + def initialize(name, flags); end + end + + # Returns the fields for the given node. + sig { params(node: ::T.class_of(Node)).returns(T::Array[Field]) } + def self.fields_for(node); end + end +end diff --git a/rbi/generated/prism/relocation.rbi b/rbi/generated/prism/relocation.rbi new file mode 100644 index 0000000000..7868d065b0 --- /dev/null +++ b/rbi/generated/prism/relocation.rbi @@ -0,0 +1,389 @@ +# typed: true + +module Prism + # Prism parses deterministically for the same input. This provides a nice + # property that is exposed through the #node_id API on nodes. Effectively this + # means that for the same input, these values will remain consistent every + # time the source is parsed. This means we can reparse the source same with a + # #node_id value and find the exact same node again. + # + # The Relocation module provides an API around this property. It allows you to + # "save" nodes and locations using a minimal amount of memory (just the + # node_id and a field identifier) and then reify them later. + module Relocation + # An entry in a repository that will lazily reify its values when they are + # first accessed. + class Entry + # Raised if a value that could potentially be on an entry is missing + # because it was either not configured on the repository or it has not yet + # been fetched. + class MissingValueError < StandardError; end + + # Initialize a new entry with the given repository. + sig { params(repository: Repository).void } + def initialize(repository); end + + # Fetch the filepath of the value. + sig { returns(String) } + def filepath; end + + # Fetch the start line of the value. + sig { returns(Integer) } + def start_line; end + + # Fetch the end line of the value. + sig { returns(Integer) } + def end_line; end + + # Fetch the start byte offset of the value. + sig { returns(Integer) } + def start_offset; end + + # Fetch the end byte offset of the value. + sig { returns(Integer) } + def end_offset; end + + # Fetch the start character offset of the value. + sig { returns(Integer) } + def start_character_offset; end + + # Fetch the end character offset of the value. + sig { returns(Integer) } + def end_character_offset; end + + # Fetch the start code units offset of the value, for the encoding that + # was configured on the repository. + sig { returns(Integer) } + def start_code_units_offset; end + + # Fetch the end code units offset of the value, for the encoding that was + # configured on the repository. + sig { returns(Integer) } + def end_code_units_offset; end + + # Fetch the start byte column of the value. + sig { returns(Integer) } + def start_column; end + + # Fetch the end byte column of the value. + sig { returns(Integer) } + def end_column; end + + # Fetch the start character column of the value. + sig { returns(Integer) } + def start_character_column; end + + # Fetch the end character column of the value. + sig { returns(Integer) } + def end_character_column; end + + # Fetch the start code units column of the value, for the encoding that + # was configured on the repository. + sig { returns(Integer) } + def start_code_units_column; end + + # Fetch the end code units column of the value, for the encoding that was + # configured on the repository. + sig { returns(Integer) } + def end_code_units_column; end + + # Fetch the leading comments of the value. + sig { returns(T::Array[CommentsField::Comment]) } + def leading_comments; end + + # Fetch the trailing comments of the value. + sig { returns(T::Array[CommentsField::Comment]) } + def trailing_comments; end + + # Fetch the leading and trailing comments of the value. + sig { returns(T::Array[CommentsField::Comment]) } + def comments; end + + # Reify the values on this entry with the given values. This is an + # internal-only API that is called from the repository when it is time to + # reify the values. + sig { params(values: T::Hash[Symbol, ::T.untyped]).void } + def reify!(values); end + + # Fetch a value from the entry, raising an error if it is missing. + sig { params(name: Symbol).returns(::T.untyped) } + private def fetch_value(name); end + + # Return the values from the repository, reifying them if necessary. + sig { returns(T::Hash[Symbol, ::T.untyped]) } + private def values; end + end + + # Represents the source of a repository that will be reparsed. + class Source + # The value that will need to be reparsed. + sig { returns(::T.untyped) } + attr_reader :value + + # Initialize the source with the given value. + sig { params(value: ::T.untyped).void } + def initialize(value); end + + # Reparse the value and return the parse result. + sig { returns(ParseResult) } + def result; end + + # Create a code units cache for the given encoding. + sig { params(encoding: Encoding).returns(::T.untyped) } + def code_units_cache(encoding); end + end + + # A source that is represented by a file path. + class SourceFilepath < Source + # Reparse the file and return the parse result. + sig { returns(ParseResult) } + def result; end + end + + # A source that is represented by a string. + class SourceString < Source + # Reparse the string and return the parse result. + sig { returns(ParseResult) } + def result; end + end + + # A field that represents the file path. + class FilepathField + # The file path that this field represents. + sig { returns(String) } + attr_reader :value + + # Initialize a new field with the given file path. + sig { params(value: String).void } + def initialize(value); end + + # Fetch the file path. + sig { params(_value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } + def fields(_value); end + end + + # A field representing the start and end lines. + class LinesField + # Fetches the start and end line of a value. + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } + def fields(value); end + end + + # A field representing the start and end byte offsets. + class OffsetsField + # Fetches the start and end byte offset of a value. + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } + def fields(value); end + end + + # A field representing the start and end character offsets. + class CharacterOffsetsField + # Fetches the start and end character offset of a value. + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } + def fields(value); end + end + + # A field representing the start and end code unit offsets. + class CodeUnitOffsetsField + # A pointer to the repository object that is used for lazily creating a + # code units cache. + sig { returns(Repository) } + attr_reader :repository + + # The associated encoding for the code units. + sig { returns(Encoding) } + attr_reader :encoding + + # Initialize a new field with the associated repository and encoding. + sig { params(repository: Repository, encoding: Encoding).void } + def initialize(repository, encoding); end + + # Fetches the start and end code units offset of a value for a particular + # encoding. + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } + def fields(value); end + + # Lazily create a code units cache for the associated encoding. + sig { returns(::T.untyped) } + private def cache; end + end + + # A field representing the start and end byte columns. + class ColumnsField + # Fetches the start and end byte column of a value. + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } + def fields(value); end + end + + # A field representing the start and end character columns. + class CharacterColumnsField + # Fetches the start and end character column of a value. + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } + def fields(value); end + end + + # A field representing the start and end code unit columns for a specific + # encoding. + class CodeUnitColumnsField + # The repository object that is used for lazily creating a code units + # cache. + sig { returns(Repository) } + attr_reader :repository + + # The associated encoding for the code units. + sig { returns(Encoding) } + attr_reader :encoding + + # Initialize a new field with the associated repository and encoding. + sig { params(repository: Repository, encoding: Encoding).void } + def initialize(repository, encoding); end + + # Fetches the start and end code units column of a value for a particular + # encoding. + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } + def fields(value); end + + # Lazily create a code units cache for the associated encoding. + sig { returns(::T.untyped) } + private def cache; end + end + + # An abstract field used as the parent class of the two comments fields. + class CommentsField + # An object that represents a slice of a comment. + class Comment + # The slice of the comment. + sig { returns(String) } + attr_reader :slice + + # Initialize a new comment with the given slice. + # + sig { params(slice: String).void } + def initialize(slice); end + end + + # Create comment objects from the given values. + sig { params(values: ::T.untyped).returns(T::Array[Comment]) } + private def comments(values); end + end + + # A field representing the leading comments. + class LeadingCommentsField < CommentsField + # Fetches the leading comments of a value. + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } + def fields(value); end + end + + # A field representing the trailing comments. + class TrailingCommentsField < CommentsField + # Fetches the trailing comments of a value. + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } + def fields(value); end + end + + # A repository is a configured collection of fields and a set of entries + # that knows how to reparse a source and reify the values. + class Repository + # Raised when multiple fields of the same type are configured on the same + # repository. + class ConfigurationError < StandardError; end + + # The source associated with this repository. This will be either a + # SourceFilepath (the most common use case) or a SourceString. + sig { returns(Source) } + attr_reader :source + + # The fields that have been configured on this repository. + sig { returns(T::Hash[Symbol, ::T.untyped]) } + attr_reader :fields + + # The entries that have been saved on this repository. + sig { returns(T::Hash[Integer, T::Hash[Symbol, Entry]]) } + attr_reader :entries + + # Initialize a new repository with the given source. + sig { params(source: Source).void } + def initialize(source); end + + # Create a code units cache for the given encoding from the source. + sig { params(encoding: Encoding).returns(::T.untyped) } + def code_units_cache(encoding); end + + # Configure the filepath field for this repository and return self. + sig { returns(::T.self_type) } + def filepath; end + + # Configure the lines field for this repository and return self. + sig { returns(::T.self_type) } + def lines; end + + # Configure the offsets field for this repository and return self. + sig { returns(::T.self_type) } + def offsets; end + + # Configure the character offsets field for this repository and return + # self. + sig { returns(::T.self_type) } + def character_offsets; end + + # Configure the code unit offsets field for this repository for a specific + # encoding and return self. + sig { params(encoding: Encoding).returns(::T.self_type) } + def code_unit_offsets(encoding); end + + # Configure the columns field for this repository and return self. + sig { returns(::T.self_type) } + def columns; end + + # Configure the character columns field for this repository and return + # self. + sig { returns(::T.self_type) } + def character_columns; end + + # Configure the code unit columns field for this repository for a specific + # encoding and return self. + sig { params(encoding: Encoding).returns(::T.self_type) } + def code_unit_columns(encoding); end + + # Configure the leading comments field for this repository and return + # self. + sig { returns(::T.self_type) } + def leading_comments; end + + # Configure the trailing comments field for this repository and return + # self. + sig { returns(::T.self_type) } + def trailing_comments; end + + # Configure both the leading and trailing comment fields for this + # repository and return self. + sig { returns(::T.self_type) } + def comments; end + + # This method is called from nodes and locations when they want to enter + # themselves into the repository. It it internal-only and meant to be + # called from the #save* APIs. + sig { params(node_id: Integer, field_name: Symbol).returns(Entry) } + def enter(node_id, field_name); end + + # This method is called from the entries in the repository when they need + # to reify their values. It is internal-only and meant to be called from + # the various value APIs. + sig { void } + def reify!; end + + # Append the given field to the repository and return the repository so + # that these calls can be chained. + sig { params(name: Symbol, arg0: ::T.untyped).returns(::T.self_type) } + private def field(name, arg0); end + end + + # Create a new repository for the given filepath. + sig { params(value: String).returns(Repository) } + def self.filepath(value); end + + # Create a new repository for the given string. + sig { params(value: String).returns(Repository) } + def self.string(value); end + end +end diff --git a/rbi/generated/prism/serialize.rbi b/rbi/generated/prism/serialize.rbi new file mode 100644 index 0000000000..57b4c61acb --- /dev/null +++ b/rbi/generated/prism/serialize.rbi @@ -0,0 +1,172 @@ +# typed: true + +module Prism + # A module responsible for deserializing parse results. + module Serialize + # The major version of prism that we are expecting to find in the serialized + # strings. + MAJOR_VERSION = T.let(nil, Integer) + + # The minor version of prism that we are expecting to find in the serialized + # strings. + MINOR_VERSION = T.let(nil, Integer) + + # The patch version of prism that we are expecting to find in the serialized + # strings. + PATCH_VERSION = T.let(nil, Integer) + + # Deserialize the dumped output from a request to parse or parse_file. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + sig { params(input: String, serialized: String, freeze: T::Boolean).returns(ParseResult) } + def self.load_parse(input, serialized, freeze); end + + # Deserialize the dumped output from a request to lex or lex_file. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + sig { params(input: String, serialized: String, freeze: T::Boolean).returns(LexResult) } + def self.load_lex(input, serialized, freeze); end + + # Deserialize the dumped output from a request to parse_comments or + # parse_file_comments. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + sig { params(input: String, serialized: String, freeze: T::Boolean).returns(T::Array[Comment]) } + def self.load_parse_comments(input, serialized, freeze); end + + # Deserialize the dumped output from a request to parse_lex or + # parse_lex_file. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + sig { params(input: String, serialized: String, freeze: T::Boolean).returns(ParseLexResult) } + def self.load_parse_lex(input, serialized, freeze); end + + class ConstantPool + sig { returns(Integer) } + attr_reader :size + + sig { params(serialized: String, base: Integer, size: Integer).void } + def initialize(serialized, base, size); end + + sig { params(index: Integer, encoding: Encoding).returns(Symbol) } + def get(index, encoding); end + end + + FastStringIO = T.let(nil, ::T.untyped) + + class Loader + sig { returns(String) } + attr_reader :input + + sig { returns(StringIO) } + attr_reader :io + + sig { returns(Source) } + attr_reader :source + + sig { params(source: Source, serialized: String).void } + def initialize(source, serialized); end + + sig { returns(T::Boolean) } + def eof?; end + + sig { params(constant_pool: ConstantPool).void } + def load_constant_pool(constant_pool); end + + sig { void } + def load_header; end + + sig { returns(Encoding) } + def load_encoding; end + + sig { params(freeze: T::Boolean).returns(T::Array[Integer]) } + def load_line_offsets(freeze); end + + sig { params(freeze: T::Boolean).returns(T::Array[Comment]) } + def load_comments(freeze); end + + sig { params(freeze: T::Boolean).returns(T::Array[MagicComment]) } + def load_magic_comments(freeze); end + + DIAGNOSTIC_TYPES = T.let(nil, T::Array[Symbol]) + + sig { returns(Symbol) } + def load_error_level; end + + sig { params(encoding: Encoding, freeze: T::Boolean).returns(T::Array[ParseError]) } + def load_errors(encoding, freeze); end + + sig { returns(Symbol) } + def load_warning_level; end + + sig { params(encoding: Encoding, freeze: T::Boolean).returns(T::Array[ParseWarning]) } + def load_warnings(encoding, freeze); end + + sig { returns(T::Array[[Token, Integer]]) } + def load_tokens; end + + # variable-length integer using https://en.wikipedia.org/wiki/LEB128 + # This is also what protobuf uses: https://protobuf.dev/programming-guides/encoding/#varints + sig { returns(Integer) } + def load_varuint; end + + sig { returns(Integer) } + def load_varsint; end + + sig { returns(Integer) } + def load_integer; end + + sig { returns(Float) } + def load_double; end + + sig { returns(T::Boolean) } + def load_bool; end + + sig { returns(Integer) } + def load_uint32; end + + sig { params(constant_pool: ConstantPool, encoding: Encoding, freeze: T::Boolean).returns(::T.nilable(Node)) } + def load_optional_node(constant_pool, encoding, freeze); end + + sig { params(encoding: Encoding).returns(String) } + def load_string(encoding); end + + sig { params(freeze: T::Boolean).returns(Location) } + def load_location_object(freeze); end + + # Load a location object from the serialized data. Note that we are lying + # about the signature a bit here, because we sometimes load it as a packed + # integer instead of an object. + sig { params(freeze: T::Boolean).returns(Location) } + def load_location(freeze); end + + # Load an optional location object from the serialized data if it is + # present. Note that we are lying about the signature a bit here, because + # we sometimes load it as a packed integer instead of an object. + sig { params(freeze: T::Boolean).returns(::T.nilable(Location)) } + def load_optional_location(freeze); end + + sig { params(freeze: T::Boolean).returns(::T.nilable(Location)) } + def load_optional_location_object(freeze); end + + sig { params(constant_pool: ConstantPool, encoding: Encoding).returns(Symbol) } + def load_constant(constant_pool, encoding); end + + sig { params(constant_pool: ConstantPool, encoding: Encoding).returns(::T.nilable(Symbol)) } + def load_optional_constant(constant_pool, encoding); end + + sig { params(constant_pool: ConstantPool, encoding: Encoding, freeze: T::Boolean).returns(Node) } + def load_node(constant_pool, encoding, freeze); end + + sig { void } + def define_load_node_lambdas; end + end + + # The token types that can be indexed by their enum values. + TOKEN_TYPES = T.let(nil, T::Array[::T.nilable(Symbol)]) + end +end diff --git a/rbi/generated/prism/string_query.rbi b/rbi/generated/prism/string_query.rbi new file mode 100644 index 0000000000..688ea4f08b --- /dev/null +++ b/rbi/generated/prism/string_query.rbi @@ -0,0 +1,36 @@ +# typed: 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 + 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 + + # The string that this query is wrapping. + sig { returns(String) } + attr_reader :string + + # Initialize a new query with the given string. + sig { params(string: String).void } + def initialize(string); end + + # Whether or not this string is a valid local variable name. + sig { returns(T::Boolean) } + def local?; end + + # Whether or not this string is a valid constant name. + sig { returns(T::Boolean) } + def constant?; end + + # Whether or not this string is a valid method name. + sig { returns(T::Boolean) } + def method_name?; end + end +end diff --git a/rbi/generated/prism/translation.rbi b/rbi/generated/prism/translation.rbi new file mode 100644 index 0000000000..007625b541 --- /dev/null +++ b/rbi/generated/prism/translation.rbi @@ -0,0 +1,7 @@ +# typed: true + +module Prism + # This module is responsible for converting the prism syntax tree into other + # syntax trees. + module Translation; end +end diff --git a/rbi/generated/prism/visitor.rbi b/rbi/generated/prism/visitor.rbi new file mode 100644 index 0000000000..53534f1dc6 --- /dev/null +++ b/rbi/generated/prism/visitor.rbi @@ -0,0 +1,650 @@ +# typed: true + +module Prism + # A class that knows how to walk down the tree. None of the individual visit + # methods are implemented on this visitor, so it forces the consumer to + # implement each one that they need. For a default implementation that + # continues walking the tree, see the Visitor class. + class BasicVisitor + # Calls `accept` on the given node if it is not `nil`, which in turn should + # call back into this visitor by calling the appropriate `visit_*` method. + sig { params(node: ::T.nilable(Node)).void } + def visit(node); end + + # Visits each node in `nodes` by calling `accept` on each one. + sig { params(nodes: T::Array[::T.nilable(Node)]).void } + def visit_all(nodes); end + + # Visits the child nodes of `node` by calling `accept` on each one. + sig { params(node: Node).void } + def visit_child_nodes(node); end + end + + # A visitor is a class that provides a default implementation for every accept + # method defined on the nodes. This means it can walk a tree without the + # caller needing to define any special handling. This allows you to handle a + # subset of the tree, while still walking the whole tree. + # + # For example, to find all of the method calls that call the `foo` method, you + # could write: + # + # class FooCalls < Prism::Visitor + # def visit_call_node(node) + # if node.name == :foo + # # Do something with the node + # end + # + # # Call super so that the visitor continues walking the tree + # super + # end + # end + class Visitor < BasicVisitor + # Visit a AliasGlobalVariableNode node + sig { params(node: AliasGlobalVariableNode).void } + def visit_alias_global_variable_node(node); end + + # Visit a AliasMethodNode node + sig { params(node: AliasMethodNode).void } + def visit_alias_method_node(node); end + + # Visit a AlternationPatternNode node + sig { params(node: AlternationPatternNode).void } + def visit_alternation_pattern_node(node); end + + # Visit a AndNode node + sig { params(node: AndNode).void } + def visit_and_node(node); end + + # Visit a ArgumentsNode node + sig { params(node: ArgumentsNode).void } + def visit_arguments_node(node); end + + # Visit a ArrayNode node + sig { params(node: ArrayNode).void } + def visit_array_node(node); end + + # Visit a ArrayPatternNode node + sig { params(node: ArrayPatternNode).void } + def visit_array_pattern_node(node); end + + # Visit a AssocNode node + sig { params(node: AssocNode).void } + def visit_assoc_node(node); end + + # Visit a AssocSplatNode node + sig { params(node: AssocSplatNode).void } + def visit_assoc_splat_node(node); end + + # Visit a BackReferenceReadNode node + sig { params(node: BackReferenceReadNode).void } + def visit_back_reference_read_node(node); end + + # Visit a BeginNode node + sig { params(node: BeginNode).void } + def visit_begin_node(node); end + + # Visit a BlockArgumentNode node + sig { params(node: BlockArgumentNode).void } + def visit_block_argument_node(node); end + + # Visit a BlockLocalVariableNode node + sig { params(node: BlockLocalVariableNode).void } + def visit_block_local_variable_node(node); end + + # Visit a BlockNode node + sig { params(node: BlockNode).void } + def visit_block_node(node); end + + # Visit a BlockParameterNode node + sig { params(node: BlockParameterNode).void } + def visit_block_parameter_node(node); end + + # Visit a BlockParametersNode node + sig { params(node: BlockParametersNode).void } + def visit_block_parameters_node(node); end + + # Visit a BreakNode node + sig { params(node: BreakNode).void } + def visit_break_node(node); end + + # Visit a CallAndWriteNode node + sig { params(node: CallAndWriteNode).void } + def visit_call_and_write_node(node); end + + # Visit a CallNode node + sig { params(node: CallNode).void } + def visit_call_node(node); end + + # Visit a CallOperatorWriteNode node + sig { params(node: CallOperatorWriteNode).void } + def visit_call_operator_write_node(node); end + + # Visit a CallOrWriteNode node + sig { params(node: CallOrWriteNode).void } + def visit_call_or_write_node(node); end + + # Visit a CallTargetNode node + sig { params(node: CallTargetNode).void } + def visit_call_target_node(node); end + + # Visit a CapturePatternNode node + sig { params(node: CapturePatternNode).void } + def visit_capture_pattern_node(node); end + + # Visit a CaseMatchNode node + sig { params(node: CaseMatchNode).void } + def visit_case_match_node(node); end + + # Visit a CaseNode node + sig { params(node: CaseNode).void } + def visit_case_node(node); end + + # Visit a ClassNode node + sig { params(node: ClassNode).void } + def visit_class_node(node); end + + # Visit a ClassVariableAndWriteNode node + sig { params(node: ClassVariableAndWriteNode).void } + def visit_class_variable_and_write_node(node); end + + # Visit a ClassVariableOperatorWriteNode node + sig { params(node: ClassVariableOperatorWriteNode).void } + def visit_class_variable_operator_write_node(node); end + + # Visit a ClassVariableOrWriteNode node + sig { params(node: ClassVariableOrWriteNode).void } + def visit_class_variable_or_write_node(node); end + + # Visit a ClassVariableReadNode node + sig { params(node: ClassVariableReadNode).void } + def visit_class_variable_read_node(node); end + + # Visit a ClassVariableTargetNode node + sig { params(node: ClassVariableTargetNode).void } + def visit_class_variable_target_node(node); end + + # Visit a ClassVariableWriteNode node + sig { params(node: ClassVariableWriteNode).void } + def visit_class_variable_write_node(node); end + + # Visit a ConstantAndWriteNode node + sig { params(node: ConstantAndWriteNode).void } + def visit_constant_and_write_node(node); end + + # Visit a ConstantOperatorWriteNode node + sig { params(node: ConstantOperatorWriteNode).void } + def visit_constant_operator_write_node(node); end + + # Visit a ConstantOrWriteNode node + sig { params(node: ConstantOrWriteNode).void } + def visit_constant_or_write_node(node); end + + # Visit a ConstantPathAndWriteNode node + sig { params(node: ConstantPathAndWriteNode).void } + def visit_constant_path_and_write_node(node); end + + # Visit a ConstantPathNode node + sig { params(node: ConstantPathNode).void } + def visit_constant_path_node(node); end + + # Visit a ConstantPathOperatorWriteNode node + sig { params(node: ConstantPathOperatorWriteNode).void } + def visit_constant_path_operator_write_node(node); end + + # Visit a ConstantPathOrWriteNode node + sig { params(node: ConstantPathOrWriteNode).void } + def visit_constant_path_or_write_node(node); end + + # Visit a ConstantPathTargetNode node + sig { params(node: ConstantPathTargetNode).void } + def visit_constant_path_target_node(node); end + + # Visit a ConstantPathWriteNode node + sig { params(node: ConstantPathWriteNode).void } + def visit_constant_path_write_node(node); end + + # Visit a ConstantReadNode node + sig { params(node: ConstantReadNode).void } + def visit_constant_read_node(node); end + + # Visit a ConstantTargetNode node + sig { params(node: ConstantTargetNode).void } + def visit_constant_target_node(node); end + + # Visit a ConstantWriteNode node + sig { params(node: ConstantWriteNode).void } + def visit_constant_write_node(node); end + + # Visit a DefNode node + sig { params(node: DefNode).void } + def visit_def_node(node); end + + # Visit a DefinedNode node + sig { params(node: DefinedNode).void } + def visit_defined_node(node); end + + # Visit a ElseNode node + sig { params(node: ElseNode).void } + def visit_else_node(node); end + + # Visit a EmbeddedStatementsNode node + sig { params(node: EmbeddedStatementsNode).void } + def visit_embedded_statements_node(node); end + + # Visit a EmbeddedVariableNode node + sig { params(node: EmbeddedVariableNode).void } + def visit_embedded_variable_node(node); end + + # Visit a EnsureNode node + sig { params(node: EnsureNode).void } + def visit_ensure_node(node); end + + # Visit a FalseNode node + sig { params(node: FalseNode).void } + def visit_false_node(node); end + + # Visit a FindPatternNode node + sig { params(node: FindPatternNode).void } + def visit_find_pattern_node(node); end + + # Visit a FlipFlopNode node + sig { params(node: FlipFlopNode).void } + def visit_flip_flop_node(node); end + + # Visit a FloatNode node + sig { params(node: FloatNode).void } + def visit_float_node(node); end + + # Visit a ForNode node + sig { params(node: ForNode).void } + def visit_for_node(node); end + + # Visit a ForwardingArgumentsNode node + sig { params(node: ForwardingArgumentsNode).void } + def visit_forwarding_arguments_node(node); end + + # Visit a ForwardingParameterNode node + sig { params(node: ForwardingParameterNode).void } + def visit_forwarding_parameter_node(node); end + + # Visit a ForwardingSuperNode node + sig { params(node: ForwardingSuperNode).void } + def visit_forwarding_super_node(node); end + + # Visit a GlobalVariableAndWriteNode node + sig { params(node: GlobalVariableAndWriteNode).void } + def visit_global_variable_and_write_node(node); end + + # Visit a GlobalVariableOperatorWriteNode node + sig { params(node: GlobalVariableOperatorWriteNode).void } + def visit_global_variable_operator_write_node(node); end + + # Visit a GlobalVariableOrWriteNode node + sig { params(node: GlobalVariableOrWriteNode).void } + def visit_global_variable_or_write_node(node); end + + # Visit a GlobalVariableReadNode node + sig { params(node: GlobalVariableReadNode).void } + def visit_global_variable_read_node(node); end + + # Visit a GlobalVariableTargetNode node + sig { params(node: GlobalVariableTargetNode).void } + def visit_global_variable_target_node(node); end + + # Visit a GlobalVariableWriteNode node + sig { params(node: GlobalVariableWriteNode).void } + def visit_global_variable_write_node(node); end + + # Visit a HashNode node + sig { params(node: HashNode).void } + def visit_hash_node(node); end + + # Visit a HashPatternNode node + sig { params(node: HashPatternNode).void } + def visit_hash_pattern_node(node); end + + # Visit a IfNode node + sig { params(node: IfNode).void } + def visit_if_node(node); end + + # Visit a ImaginaryNode node + sig { params(node: ImaginaryNode).void } + def visit_imaginary_node(node); end + + # Visit a ImplicitNode node + sig { params(node: ImplicitNode).void } + def visit_implicit_node(node); end + + # Visit a ImplicitRestNode node + sig { params(node: ImplicitRestNode).void } + def visit_implicit_rest_node(node); end + + # Visit a InNode node + sig { params(node: InNode).void } + def visit_in_node(node); end + + # Visit a IndexAndWriteNode node + sig { params(node: IndexAndWriteNode).void } + def visit_index_and_write_node(node); end + + # Visit a IndexOperatorWriteNode node + sig { params(node: IndexOperatorWriteNode).void } + def visit_index_operator_write_node(node); end + + # Visit a IndexOrWriteNode node + sig { params(node: IndexOrWriteNode).void } + def visit_index_or_write_node(node); end + + # Visit a IndexTargetNode node + sig { params(node: IndexTargetNode).void } + def visit_index_target_node(node); end + + # Visit a InstanceVariableAndWriteNode node + sig { params(node: InstanceVariableAndWriteNode).void } + def visit_instance_variable_and_write_node(node); end + + # Visit a InstanceVariableOperatorWriteNode node + sig { params(node: InstanceVariableOperatorWriteNode).void } + def visit_instance_variable_operator_write_node(node); end + + # Visit a InstanceVariableOrWriteNode node + sig { params(node: InstanceVariableOrWriteNode).void } + def visit_instance_variable_or_write_node(node); end + + # Visit a InstanceVariableReadNode node + sig { params(node: InstanceVariableReadNode).void } + def visit_instance_variable_read_node(node); end + + # Visit a InstanceVariableTargetNode node + sig { params(node: InstanceVariableTargetNode).void } + def visit_instance_variable_target_node(node); end + + # Visit a InstanceVariableWriteNode node + sig { params(node: InstanceVariableWriteNode).void } + def visit_instance_variable_write_node(node); end + + # Visit a IntegerNode node + sig { params(node: IntegerNode).void } + def visit_integer_node(node); end + + # Visit a InterpolatedMatchLastLineNode node + sig { params(node: InterpolatedMatchLastLineNode).void } + def visit_interpolated_match_last_line_node(node); end + + # Visit a InterpolatedRegularExpressionNode node + sig { params(node: InterpolatedRegularExpressionNode).void } + def visit_interpolated_regular_expression_node(node); end + + # Visit a InterpolatedStringNode node + sig { params(node: InterpolatedStringNode).void } + def visit_interpolated_string_node(node); end + + # Visit a InterpolatedSymbolNode node + sig { params(node: InterpolatedSymbolNode).void } + def visit_interpolated_symbol_node(node); end + + # Visit a InterpolatedXStringNode node + sig { params(node: InterpolatedXStringNode).void } + def visit_interpolated_x_string_node(node); end + + # Visit a ItLocalVariableReadNode node + sig { params(node: ItLocalVariableReadNode).void } + def visit_it_local_variable_read_node(node); end + + # Visit a ItParametersNode node + sig { params(node: ItParametersNode).void } + def visit_it_parameters_node(node); end + + # Visit a KeywordHashNode node + sig { params(node: KeywordHashNode).void } + def visit_keyword_hash_node(node); end + + # Visit a KeywordRestParameterNode node + sig { params(node: KeywordRestParameterNode).void } + def visit_keyword_rest_parameter_node(node); end + + # Visit a LambdaNode node + sig { params(node: LambdaNode).void } + def visit_lambda_node(node); end + + # Visit a LocalVariableAndWriteNode node + sig { params(node: LocalVariableAndWriteNode).void } + def visit_local_variable_and_write_node(node); end + + # Visit a LocalVariableOperatorWriteNode node + sig { params(node: LocalVariableOperatorWriteNode).void } + def visit_local_variable_operator_write_node(node); end + + # Visit a LocalVariableOrWriteNode node + sig { params(node: LocalVariableOrWriteNode).void } + def visit_local_variable_or_write_node(node); end + + # Visit a LocalVariableReadNode node + sig { params(node: LocalVariableReadNode).void } + def visit_local_variable_read_node(node); end + + # Visit a LocalVariableTargetNode node + sig { params(node: LocalVariableTargetNode).void } + def visit_local_variable_target_node(node); end + + # Visit a LocalVariableWriteNode node + sig { params(node: LocalVariableWriteNode).void } + def visit_local_variable_write_node(node); end + + # Visit a MatchLastLineNode node + sig { params(node: MatchLastLineNode).void } + def visit_match_last_line_node(node); end + + # Visit a MatchPredicateNode node + sig { params(node: MatchPredicateNode).void } + def visit_match_predicate_node(node); end + + # Visit a MatchRequiredNode node + sig { params(node: MatchRequiredNode).void } + def visit_match_required_node(node); end + + # Visit a MatchWriteNode node + sig { params(node: MatchWriteNode).void } + def visit_match_write_node(node); end + + # Visit a MissingNode node + sig { params(node: MissingNode).void } + def visit_missing_node(node); end + + # Visit a ModuleNode node + sig { params(node: ModuleNode).void } + def visit_module_node(node); end + + # Visit a MultiTargetNode node + sig { params(node: MultiTargetNode).void } + def visit_multi_target_node(node); end + + # Visit a MultiWriteNode node + sig { params(node: MultiWriteNode).void } + def visit_multi_write_node(node); end + + # Visit a NextNode node + sig { params(node: NextNode).void } + def visit_next_node(node); end + + # Visit a NilNode node + sig { params(node: NilNode).void } + def visit_nil_node(node); end + + # Visit a NoBlockParameterNode node + sig { params(node: NoBlockParameterNode).void } + def visit_no_block_parameter_node(node); end + + # Visit a NoKeywordsParameterNode node + sig { params(node: NoKeywordsParameterNode).void } + def visit_no_keywords_parameter_node(node); end + + # Visit a NumberedParametersNode node + sig { params(node: NumberedParametersNode).void } + def visit_numbered_parameters_node(node); end + + # Visit a NumberedReferenceReadNode node + sig { params(node: NumberedReferenceReadNode).void } + def visit_numbered_reference_read_node(node); end + + # Visit a OptionalKeywordParameterNode node + sig { params(node: OptionalKeywordParameterNode).void } + def visit_optional_keyword_parameter_node(node); end + + # Visit a OptionalParameterNode node + sig { params(node: OptionalParameterNode).void } + def visit_optional_parameter_node(node); end + + # Visit a OrNode node + sig { params(node: OrNode).void } + def visit_or_node(node); end + + # Visit a ParametersNode node + sig { params(node: ParametersNode).void } + def visit_parameters_node(node); end + + # Visit a ParenthesesNode node + sig { params(node: ParenthesesNode).void } + def visit_parentheses_node(node); end + + # Visit a PinnedExpressionNode node + sig { params(node: PinnedExpressionNode).void } + def visit_pinned_expression_node(node); end + + # Visit a PinnedVariableNode node + sig { params(node: PinnedVariableNode).void } + def visit_pinned_variable_node(node); end + + # Visit a PostExecutionNode node + sig { params(node: PostExecutionNode).void } + def visit_post_execution_node(node); end + + # Visit a PreExecutionNode node + sig { params(node: PreExecutionNode).void } + def visit_pre_execution_node(node); end + + # Visit a ProgramNode node + sig { params(node: ProgramNode).void } + def visit_program_node(node); end + + # Visit a RangeNode node + sig { params(node: RangeNode).void } + def visit_range_node(node); end + + # Visit a RationalNode node + sig { params(node: RationalNode).void } + def visit_rational_node(node); end + + # Visit a RedoNode node + sig { params(node: RedoNode).void } + def visit_redo_node(node); end + + # Visit a RegularExpressionNode node + sig { params(node: RegularExpressionNode).void } + def visit_regular_expression_node(node); end + + # Visit a RequiredKeywordParameterNode node + sig { params(node: RequiredKeywordParameterNode).void } + def visit_required_keyword_parameter_node(node); end + + # Visit a RequiredParameterNode node + sig { params(node: RequiredParameterNode).void } + def visit_required_parameter_node(node); end + + # Visit a RescueModifierNode node + sig { params(node: RescueModifierNode).void } + def visit_rescue_modifier_node(node); end + + # Visit a RescueNode node + sig { params(node: RescueNode).void } + def visit_rescue_node(node); end + + # Visit a RestParameterNode node + sig { params(node: RestParameterNode).void } + def visit_rest_parameter_node(node); end + + # Visit a RetryNode node + sig { params(node: RetryNode).void } + def visit_retry_node(node); end + + # Visit a ReturnNode node + sig { params(node: ReturnNode).void } + def visit_return_node(node); end + + # Visit a SelfNode node + sig { params(node: SelfNode).void } + def visit_self_node(node); end + + # Visit a ShareableConstantNode node + sig { params(node: ShareableConstantNode).void } + def visit_shareable_constant_node(node); end + + # Visit a SingletonClassNode node + sig { params(node: SingletonClassNode).void } + def visit_singleton_class_node(node); end + + # Visit a SourceEncodingNode node + sig { params(node: SourceEncodingNode).void } + def visit_source_encoding_node(node); end + + # Visit a SourceFileNode node + sig { params(node: SourceFileNode).void } + def visit_source_file_node(node); end + + # Visit a SourceLineNode node + sig { params(node: SourceLineNode).void } + def visit_source_line_node(node); end + + # Visit a SplatNode node + sig { params(node: SplatNode).void } + def visit_splat_node(node); end + + # Visit a StatementsNode node + sig { params(node: StatementsNode).void } + def visit_statements_node(node); end + + # Visit a StringNode node + sig { params(node: StringNode).void } + def visit_string_node(node); end + + # Visit a SuperNode node + sig { params(node: SuperNode).void } + def visit_super_node(node); end + + # Visit a SymbolNode node + sig { params(node: SymbolNode).void } + def visit_symbol_node(node); end + + # Visit a TrueNode node + sig { params(node: TrueNode).void } + def visit_true_node(node); end + + # Visit a UndefNode node + sig { params(node: UndefNode).void } + def visit_undef_node(node); end + + # Visit a UnlessNode node + sig { params(node: UnlessNode).void } + def visit_unless_node(node); end + + # Visit a UntilNode node + sig { params(node: UntilNode).void } + def visit_until_node(node); end + + # Visit a WhenNode node + sig { params(node: WhenNode).void } + def visit_when_node(node); end + + # Visit a WhileNode node + sig { params(node: WhileNode).void } + def visit_while_node(node); end + + # Visit a XStringNode node + sig { params(node: XStringNode).void } + def visit_x_string_node(node); end + + # Visit a YieldNode node + sig { params(node: YieldNode).void } + def visit_yield_node(node); end + end +end diff --git a/rbi/prism.rbi b/rbi/prism.rbi deleted file mode 100644 index b31adc64a1..0000000000 --- a/rbi/prism.rbi +++ /dev/null @@ -1,63 +0,0 @@ -# typed: strict - -module Prism - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), 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, freeze: 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)), freeze: T.nilable(T::Boolean), 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, freeze: 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(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), 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, freeze: 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)), freeze: T.nilable(T::Boolean), 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, freeze: 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 - - sig { params(source: String, serialized: String, freeze: T.nilable(T::Boolean)).returns(Prism::ParseResult) } - def self.load(source, serialized, freeze = false); end - - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), 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, freeze: 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)), freeze: T.nilable(T::Boolean), 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, freeze: 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(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), 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, freeze: 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)), freeze: T.nilable(T::Boolean), 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, freeze: 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(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), 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, freeze: 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), freeze: T.nilable(T::Boolean), 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, freeze: 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)), freeze: T.nilable(T::Boolean), 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, freeze: 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(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), 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, freeze: 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)), freeze: T.nilable(T::Boolean), 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, freeze: 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(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), 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, freeze: 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(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), 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, freeze: 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)), freeze: T.nilable(T::Boolean), 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, freeze: 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)), freeze: T.nilable(T::Boolean), 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, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(locals: T::Array[Symbol], forwarding: T::Array[Symbol]).returns(Prism::Scope) } - def self.scope(locals: [], forwarding: []); end -end diff --git a/rbi/prism/compiler.rbi b/rbi/prism/compiler.rbi deleted file mode 100644 index c738236dea..0000000000 --- a/rbi/prism/compiler.rbi +++ /dev/null @@ -1,12 +0,0 @@ -# typed: strict - -class Prism::Compiler - sig { params(node: T.nilable(Prism::Node)).returns(T.untyped) } - def visit(node); end - - sig { params(nodes: T::Array[T.nilable(Prism::Node)]).returns(T::Array[T.untyped]) } - def visit_all(nodes); end - - sig { params(node: Prism::Node).returns(T::Array[T.untyped]) } - def visit_child_nodes(node); end -end diff --git a/rbi/prism/inspect_visitor.rbi b/rbi/prism/inspect_visitor.rbi deleted file mode 100644 index bb0c22409e..0000000000 --- a/rbi/prism/inspect_visitor.rbi +++ /dev/null @@ -1,12 +0,0 @@ -# typed: strict - -class Prism::InspectVisitor < Prism::Visitor - sig { params(indent: String).void } - def initialize(indent = ""); end - - sig { params(node: Prism::Node).returns(String) } - def self.compose(node); end - - sig { returns(String) } - def compose; end -end diff --git a/rbi/prism/node_ext.rbi b/rbi/prism/node_ext.rbi deleted file mode 100644 index e5cf7376cc..0000000000 --- a/rbi/prism/node_ext.rbi +++ /dev/null @@ -1,107 +0,0 @@ -# typed: strict - -class Prism::InterpolatedMatchLastLineNode < Prism::Node - sig { returns(Integer) } - def options; end -end - -class Prism::InterpolatedRegularExpressionNode < Prism::Node - sig { returns(Integer) } - def options; end -end - -class Prism::MatchLastLineNode < Prism::Node - sig { returns(Integer) } - def options; end -end - -class Prism::RegularExpressionNode < Prism::Node - sig { returns(Integer) } - def options; end -end - -class Prism::InterpolatedStringNode < Prism::Node - sig { returns(T::Boolean) } - def heredoc?; end -end - -class Prism::InterpolatedXStringNode < Prism::Node - sig { returns(T::Boolean) } - def heredoc?; end -end - -class Prism::StringNode < Prism::Node - sig { returns(T::Boolean) } - def heredoc?; end - - sig { returns(Prism::InterpolatedStringNode) } - def to_interpolated; end -end - -class Prism::XStringNode < Prism::Node - sig { returns(T::Boolean) } - def heredoc?; end - - sig { returns(Prism::InterpolatedXStringNode) } - def to_interpolated; end -end - -class Prism::ImaginaryNode < Prism::Node - sig { returns(Complex) } - def value; end -end - -class Prism::RationalNode < Prism::Node - sig { returns(Rational) } - def value; end -end - -class Prism::ConstantReadNode < Prism::Node - sig { returns(T::Array[Symbol]) } - def full_name_parts; end - - sig { returns(String) } - def full_name; end -end - -class Prism::ConstantWriteNode < Prism::Node - sig { returns(T::Array[Symbol]) } - def full_name_parts; end - - sig { returns(String) } - def full_name; end -end - -class Prism::ConstantPathNode < Prism::Node - sig { returns(T::Array[Symbol]) } - def full_name_parts; end - - sig { returns(String) } - def full_name; end -end - -class Prism::ConstantPathTargetNode < Prism::Node - sig { returns(T::Array[Symbol]) } - def full_name_parts; end - - sig { returns(String) } - def full_name; end -end - -class Prism::ConstantTargetNode < Prism::Node - sig { returns(T::Array[Symbol]) } - def full_name_parts; end - - sig { returns(String) } - def full_name; end -end - -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 deleted file mode 100644 index 6f2bbb6146..0000000000 --- a/rbi/prism/parse_result.rbi +++ /dev/null @@ -1,404 +0,0 @@ -# typed: strict - -class Prism::Source - sig { returns(String) } - def source; end - - sig { returns(Integer) } - def start_line; end - - sig { returns(T::Array[Integer]) } - def offsets; end - - sig { params(source: String, start_line: Integer, offsets: T::Array[Integer]).void } - def initialize(source, start_line = 1, offsets = []); end - - sig { params(start_line: Integer).void } - def replace_start_line(start_line); end - - sig { params(offsets: T::Array[Integer]).void } - def replace_offsets(offsets); end - - sig { returns(Encoding) } - def encoding; end - - sig { returns(T::Array[String]) } - def lines; end - - sig { params(byte_offset: Integer, length: Integer).returns(String) } - def slice(byte_offset, length); end - - sig { params(byte_offset: Integer).returns(Integer) } - def line(byte_offset); end - - sig { params(byte_offset: Integer).returns(Integer) } - def line_start(byte_offset); end - - sig { params(byte_offset: Integer).returns(Integer) } - def column(byte_offset); end - - sig { params(byte_offset: Integer).returns(Integer) } - def character_offset(byte_offset); end - - sig { params(byte_offset: Integer).returns(Integer) } - def character_column(byte_offset); end - - 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 - - sig { params(byte_offset: Integer).returns(Integer) } - def character_column(byte_offset); end - - 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::Location - sig { returns(Prism::Source) } - def source; end - - sig { returns(Integer) } - def start_offset; end - - sig { returns(Integer) } - def length; end - - sig { params(source: Prism::Source, start_offset: Integer, length: Integer).void } - def initialize(source, start_offset, length); end - - sig { returns(T::Array[Prism::Comment]) } - def leading_comments; end - - sig { params(comment: Prism::Comment).void } - def leading_comment(comment); end - - sig { returns(T::Array[Prism::Comment]) } - def trailing_comments; end - - sig { params(comment: Prism::Comment).void } - def trailing_comment(comment); end - - sig { returns(T::Array[Prism::Comment]) } - def comments; end - - sig { params(source: Prism::Source, start_offset: Integer, length: Integer).returns(Prism::Location) } - def copy(source: self.source, start_offset: self.start_offset, length: self.length); end - - sig { returns(Prism::Location) } - def chop; end - - sig { returns(String) } - def inspect; end - - sig { returns(T::Array[String]) } - def source_lines; end - - sig { returns(String) } - def slice; end - - sig { returns(Integer) } - def start_character_offset; end - - 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 - - sig { returns(Integer) } - def end_character_offset; end - - 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 - - sig { returns(String) } - def start_line_slice; end - - sig { returns(Integer) } - def end_line; end - - sig { returns(Integer) } - def start_column; end - - sig { returns(Integer) } - def start_character_column; end - - 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 - - sig { returns(Integer) } - def end_character_column; end - - 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 - - sig { params(q: T.untyped).void } - def pretty_print(q); end - - sig { params(other: T.untyped).returns(T::Boolean) } - def ==(other); end - - sig { params(other: Prism::Location).returns(Prism::Location) } - def join(other); end - - sig { params(string: String).returns(Prism::Location) } - def adjoin(string); end -end - -class Prism::Comment - abstract! - - sig { returns(Prism::Location) } - def location; end - - sig { params(location: Prism::Location).void } - def initialize(location); end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end - - sig { returns(String) } - def slice; end - - sig { abstract.returns(T::Boolean) } - def trailing?; end -end - -class Prism::InlineComment < Prism::Comment - sig { override.returns(T::Boolean) } - def trailing?; end - - sig { returns(String) } - def inspect; end -end - -class Prism::EmbDocComment < Prism::Comment - sig { override.returns(T::Boolean) } - def trailing?; end - - sig { returns(String) } - def inspect; end -end - -class Prism::MagicComment - sig { returns(Prism::Location) } - def key_loc; end - - sig { returns(Prism::Location) } - def value_loc; end - - sig { params(key_loc: Prism::Location, value_loc: Prism::Location).void } - def initialize(key_loc, value_loc); end - - sig { returns(String) } - def key; end - - sig { returns(String) } - def value; end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end - - sig { returns(String) } - def inspect; end -end - -class Prism::ParseError - sig { returns(Symbol) } - def type; end - - sig { returns(String) } - def message; end - - sig { returns(Prism::Location) } - def location; end - - sig { returns(Symbol) } - def level; end - - sig { params(type: Symbol, message: String, location: Prism::Location, level: Symbol).void } - def initialize(type, message, location, level); end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end - - sig { returns(String) } - def inspect; end -end - -class Prism::ParseWarning - sig { returns(Symbol) } - def type; end - - sig { returns(String) } - def message; end - - sig { returns(Prism::Location) } - def location; end - - sig { returns(Symbol) } - def level; end - - sig { params(type: Symbol, message: String, location: Prism::Location, level: Symbol).void } - def initialize(type, message, location, level); end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end - - sig { returns(String) } - def inspect; end -end - -class Prism::Result - sig { params(comments: T::Array[Prism::Comment], magic_comments: T::Array[Prism::MagicComment], data_loc: T.nilable(Prism::Location), errors: T::Array[Prism::ParseError], warnings: T::Array[Prism::ParseWarning], source: Prism::Source).void } - def initialize(comments, magic_comments, data_loc, errors, warnings, source); end - - sig { returns(T::Array[Prism::Comment]) } - def comments; end - - sig { returns(T::Array[Prism::MagicComment]) } - def magic_comments; end - - sig { returns(T.nilable(Prism::Location)) } - def data_loc; end - - sig { returns(T::Array[Prism::ParseError]) } - def errors; end - - sig { returns(T::Array[Prism::ParseWarning]) } - def warnings; end - - sig { returns(Prism::Source) } - def source; end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end - - sig { returns(Encoding) } - def encoding; end - - sig { returns(T::Boolean) } - def success?; end - - 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 - sig { params(value: Prism::ProgramNode, comments: T::Array[Prism::Comment], magic_comments: T::Array[Prism::MagicComment], data_loc: T.nilable(Prism::Location), errors: T::Array[Prism::ParseError], warnings: T::Array[Prism::ParseWarning], source: Prism::Source).void } - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end - - sig { returns(Prism::ProgramNode) } - def value; end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end -end - -class Prism::LexResult < Prism::Result - sig { params(value: T::Array[T.untyped], comments: T::Array[Prism::Comment], magic_comments: T::Array[Prism::MagicComment], data_loc: T.nilable(Prism::Location), errors: T::Array[Prism::ParseError], warnings: T::Array[Prism::ParseWarning], source: Prism::Source).void } - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end - - sig { returns(T::Array[T.untyped]) } - def value; end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end -end - -class Prism::ParseLexResult < Prism::Result - sig { params(value: [Prism::ProgramNode, T::Array[T.untyped]], comments: T::Array[Prism::Comment], magic_comments: T::Array[Prism::MagicComment], data_loc: T.nilable(Prism::Location), errors: T::Array[Prism::ParseError], warnings: T::Array[Prism::ParseWarning], source: Prism::Source).void } - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end - - sig { returns([Prism::ProgramNode, T::Array[T.untyped]]) } - def value; end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end -end - -class Prism::Token - sig { returns(Prism::Source) } - def source; end - - sig { returns(Symbol) } - def type; end - - sig { returns(String) } - def value; end - - sig { params(source: Prism::Source, type: Symbol, value: String, location: T.any(Integer, Prism::Location)).void } - def initialize(source, type, value, location); end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end - - sig { returns(Prism::Location) } - def location; end - - sig { params(q: T.untyped).void } - def pretty_print(q); end - - sig { params(other: T.untyped).returns(T::Boolean) } - def ==(other); end -end - -class Prism::Scope - sig { returns(T::Array[Symbol]) } - def locals; end - - sig { returns(T::Array[Symbol]) } - def forwarding; end - - sig { params(locals: T::Array[Symbol], forwarding: T::Array[Symbol]).void } - def initialize(locals, forwarding); end -end diff --git a/rbi/prism/reflection.rbi b/rbi/prism/reflection.rbi deleted file mode 100644 index b21e9b5def..0000000000 --- a/rbi/prism/reflection.rbi +++ /dev/null @@ -1,58 +0,0 @@ -# typed: strict - -module Prism::Reflection -end - -class Prism::Reflection::Field - sig { params(name: Symbol).void } - def initialize(name); end - - sig { returns(Symbol) } - def name; end -end - -class Prism::Reflection::NodeField < Prism::Reflection::Field -end - -class Prism::Reflection::OptionalNodeField < Prism::Reflection::Field -end - -class Prism::Reflection::NodeListField < Prism::Reflection::Field -end - -class Prism::Reflection::ConstantField < Prism::Reflection::Field -end - -class Prism::Reflection::OptionalConstantField < Prism::Reflection::Field -end - -class Prism::Reflection::ConstantListField < Prism::Reflection::Field -end - -class Prism::Reflection::StringField < Prism::Reflection::Field -end - -class Prism::Reflection::LocationField < Prism::Reflection::Field -end - -class Prism::Reflection::OptionalLocationField < Prism::Reflection::Field -end - -class Prism::Reflection::IntegerField < Prism::Reflection::Field -end - -class Prism::Reflection::FloatField < Prism::Reflection::Field -end - -class Prism::Reflection::FlagsField < Prism::Reflection::Field - sig { params(name: Symbol, flags: T::Array[Symbol]).void } - def initialize(name, flags); end - - sig { returns(T::Array[Symbol]) } - def flags; end -end - -module Prism::Reflection - sig { params(node: T.class_of(Prism::Node)).returns(T::Array[Prism::Reflection::Field]) } - def self.fields_for(node); end -end diff --git a/rbi/prism/string_query.rbi b/rbi/prism/string_query.rbi deleted file mode 100644 index 3e5bae1572..0000000000 --- a/rbi/prism/string_query.rbi +++ /dev/null @@ -1,12 +0,0 @@ -# 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/rbi/prism/translation/parser_versions.rbi b/rbi/prism/translation/parser_versions.rbi index 8a7297be3e..2aad1be440 100644 --- a/rbi/prism/translation/parser_versions.rbi +++ b/rbi/prism/translation/parser_versions.rbi @@ -21,3 +21,8 @@ class Prism::Translation::Parser40 < Prism::Translation::Parser sig { override.returns(Integer) } def version; end end + +class Prism::Translation::Parser41 < Prism::Translation::Parser + sig { override.returns(Integer) } + def version; end +end diff --git a/rust/ruby-prism-sys/Cargo.toml b/rust/ruby-prism-sys/Cargo.toml index edda0ed1fd..4578488af3 100644 --- a/rust/ruby-prism-sys/Cargo.toml +++ b/rust/ruby-prism-sys/Cargo.toml @@ -3,7 +3,6 @@ name = "ruby-prism-sys" version = "1.9.0" edition = "2021" license = "MIT" -license-file = "../../LICENSE.md" repository = "https://github.com/ruby/prism" description = "Rust bindings to Ruby's prism parsing library" links = "prism" diff --git a/rust/ruby-prism-sys/build/main.rs b/rust/ruby-prism-sys/build/main.rs index 798d06d8ff..50a8f51d6c 100644 --- a/rust/ruby-prism-sys/build/main.rs +++ b/rust/ruby-prism-sys/build/main.rs @@ -9,6 +9,7 @@ fn main() { let ruby_build_path = prism_lib_path(); let ruby_include_path = prism_include_path(); + emit_rerun_hints(&ruby_include_path); // Tell cargo/rustc that we want to link against `libprism.a`. println!("cargo:rustc-link-lib=static=prism"); @@ -23,6 +24,19 @@ fn main() { write_bindings(&bindings); } +fn emit_rerun_hints(ruby_include_path: &Path) { + println!("cargo:rerun-if-env-changed=PRISM_INCLUDE_DIR"); + println!("cargo:rerun-if-env-changed=PRISM_LIB_DIR"); + println!("cargo:rerun-if-changed={}", ruby_include_path.display()); + + if let Some(project_root) = ruby_include_path.parent() { + let src_path = project_root.join("src"); + if src_path.exists() { + println!("cargo:rerun-if-changed={}", src_path.display()); + } + } +} + /// Gets the path to project files (`libprism*`) at `[root]/build/`. /// fn prism_lib_path() -> PathBuf { @@ -120,7 +134,9 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .allowlist_type("pm_magic_comment_t") .allowlist_type("pm_node_t") .allowlist_type("pm_node_type") - .allowlist_type("pm_pack_size") + .allowlist_type("pm_options_t") + .allowlist_type("pm_options_scope_t") + .allowlist_type("pm_options_version_t") .allowlist_type("pm_parser_t") .allowlist_type("pm_string_t") .allowlist_type(r"^pm_\w+_node_t") @@ -129,29 +145,39 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .rustified_non_exhaustive_enum("pm_comment_type_t") .rustified_non_exhaustive_enum(r"pm_\w+_flags") .rustified_non_exhaustive_enum("pm_node_type") - .rustified_non_exhaustive_enum("pm_pack_encoding") - .rustified_non_exhaustive_enum("pm_pack_endian") - .rustified_non_exhaustive_enum("pm_pack_length_type") - .rustified_non_exhaustive_enum("pm_pack_result") - .rustified_non_exhaustive_enum("pm_pack_signed") - .rustified_non_exhaustive_enum("pm_pack_size") - .rustified_non_exhaustive_enum("pm_pack_type") - .rustified_non_exhaustive_enum("pm_pack_variant") + .rustified_non_exhaustive_enum("pm_options_version_t") // Functions + .allowlist_function("pm_arena_free") + .allowlist_function("pm_line_offset_list_line_column") .allowlist_function("pm_list_empty_p") .allowlist_function("pm_list_free") - .allowlist_function("pm_node_destroy") - .allowlist_function("pm_pack_parse") + .allowlist_function("pm_options_command_line_set") + .allowlist_function("pm_options_encoding_locked_set") + .allowlist_function("pm_options_encoding_set") + .allowlist_function("pm_options_filepath_set") + .allowlist_function("pm_options_free") + .allowlist_function("pm_options_frozen_string_literal_set") + .allowlist_function("pm_options_line_set") + .allowlist_function("pm_options_main_script_set") + .allowlist_function("pm_options_partial_script_set") + .allowlist_function("pm_options_scope_forwarding_set") + .allowlist_function("pm_options_scope_get") + .allowlist_function("pm_options_scope_init") + .allowlist_function("pm_options_scope_local_get") + .allowlist_function("pm_options_scopes_init") .allowlist_function("pm_parse") .allowlist_function("pm_parser_free") .allowlist_function("pm_parser_init") .allowlist_function("pm_size_to_native") + .allowlist_function("pm_string_constant_init") .allowlist_function("pm_string_free") .allowlist_function("pm_string_length") .allowlist_function("pm_string_source") .allowlist_function("pm_version") // Vars .allowlist_var(r"^pm_encoding\S+") + .allowlist_var(r"^PM_OPTIONS_COMMAND_LINE_\w+") + .allowlist_var(r"^PM_OPTIONS_SCOPE_FORWARDING_\w+") .generate() .expect("Unable to generate prism bindings") } diff --git a/rust/ruby-prism-sys/src/lib.rs b/rust/ruby-prism-sys/src/lib.rs index 8d4c979f5d..7d200124fa 100644 --- a/rust/ruby-prism-sys/src/lib.rs +++ b/rust/ruby-prism-sys/src/lib.rs @@ -27,6 +27,7 @@ #[allow(unused_qualifications)] #[allow(clippy::missing_const_for_fn)] #[allow(clippy::use_self)] +#[allow(trivial_casts)] mod bindings { // In `build.rs`, we use `bindgen` to generate bindings based on C headers // and `libprism`. Here is where we pull in those bindings and make diff --git a/rust/ruby-prism-sys/tests/node_tests.rs b/rust/ruby-prism-sys/tests/node_tests.rs index 87b6c2a337..7c7c13629c 100644 --- a/rust/ruby-prism-sys/tests/node_tests.rs +++ b/rust/ruby-prism-sys/tests/node_tests.rs @@ -1,15 +1,17 @@ use std::{ffi::CString, mem::MaybeUninit}; -use ruby_prism_sys::{pm_node_destroy, pm_node_type}; +use ruby_prism_sys::{pm_arena_free, pm_arena_t, pm_node_type}; use ruby_prism_sys::{pm_parse, pm_parser_free, pm_parser_init, pm_parser_t}; #[test] fn node_test() { + let mut arena = MaybeUninit::::zeroed(); let mut parser = MaybeUninit::::uninit(); let code = CString::new("class Foo; end").unwrap(); unsafe { pm_parser_init( + arena.as_mut_ptr(), parser.as_mut_ptr(), code.as_ptr().cast::(), code.as_bytes().len(), @@ -21,7 +23,7 @@ fn node_test() { assert_eq!((*parsed_node).type_, pm_node_type::PM_PROGRAM_NODE as u16); - pm_node_destroy(parser, parsed_node); pm_parser_free(parser); + pm_arena_free(arena.as_mut_ptr()); } } diff --git a/rust/ruby-prism-sys/tests/pack_tests.rs b/rust/ruby-prism-sys/tests/pack_tests.rs deleted file mode 100644 index 63bc1cb1ea..0000000000 --- a/rust/ruby-prism-sys/tests/pack_tests.rs +++ /dev/null @@ -1,57 +0,0 @@ -use std::{ffi::CString, mem::MaybeUninit}; - -use ruby_prism_sys::{ - pm_pack_encoding, pm_pack_endian, pm_pack_length_type, pm_pack_parse, pm_pack_result, pm_pack_signed, pm_pack_size, - pm_pack_type, pm_pack_variant, pm_size_to_native, -}; - -#[test] -fn pack_parse_test() { - let variant_arg = pm_pack_variant::PM_PACK_VARIANT_PACK; - let first_format = CString::new("C").unwrap(); - let end_format = CString::new("").unwrap(); - let mut format = vec![first_format.as_ptr(), end_format.as_ptr()]; - - let mut type_out = MaybeUninit::::uninit(); - let mut signed_type_out = MaybeUninit::::uninit(); - let mut endian_out = MaybeUninit::::uninit(); - let mut size_out = MaybeUninit::::uninit(); - let mut length_type_out = MaybeUninit::::uninit(); - let mut length_out = 0_u64; - let mut encoding_out = MaybeUninit::::uninit(); - - unsafe { - let result = pm_pack_parse( - variant_arg, - format.as_mut_ptr(), - end_format.as_ptr(), - type_out.as_mut_ptr(), - signed_type_out.as_mut_ptr(), - endian_out.as_mut_ptr(), - size_out.as_mut_ptr(), - length_type_out.as_mut_ptr(), - &raw mut length_out, - encoding_out.as_mut_ptr(), - ); - - assert_eq!(result, pm_pack_result::PM_PACK_OK); - - let type_out = type_out.assume_init(); - let signed_type_out = signed_type_out.assume_init(); - let endian_out = endian_out.assume_init(); - let size_out = size_out.assume_init(); - let length_type_out = length_type_out.assume_init(); - let encoding_out = encoding_out.assume_init(); - - assert_eq!(type_out, pm_pack_type::PM_PACK_INTEGER); - assert_eq!(signed_type_out, pm_pack_signed::PM_PACK_UNSIGNED); - assert_eq!(endian_out, pm_pack_endian::PM_PACK_AGNOSTIC_ENDIAN); - assert_eq!(size_out, pm_pack_size::PM_PACK_SIZE_8); - assert_eq!(length_type_out, pm_pack_length_type::PM_PACK_LENGTH_FIXED); - assert_eq!(length_out, 1); - assert_eq!(encoding_out, pm_pack_encoding::PM_PACK_ENCODING_ASCII_8BIT); - - let native_size = pm_size_to_native(size_out); - assert_eq!(native_size, 1); - } -} diff --git a/rust/ruby-prism-sys/tests/parser_tests.rs b/rust/ruby-prism-sys/tests/parser_tests.rs index 6ce3a3b980..d6f827d144 100644 --- a/rust/ruby-prism-sys/tests/parser_tests.rs +++ b/rust/ruby-prism-sys/tests/parser_tests.rs @@ -5,8 +5,8 @@ use std::{ }; use ruby_prism_sys::{ - pm_comment_t, pm_comment_type_t, pm_diagnostic_t, pm_node_destroy, pm_parse, pm_parser_free, pm_parser_init, - pm_parser_t, + pm_arena_free, pm_arena_t, pm_comment_t, pm_comment_type_t, pm_diagnostic_t, pm_parse, pm_parser_free, + pm_parser_init, pm_parser_t, }; fn ruby_file_contents() -> (CString, usize) { @@ -22,30 +22,34 @@ fn ruby_file_contents() -> (CString, usize) { fn init_test() { let (ruby_file_contents, len) = ruby_file_contents(); let source = ruby_file_contents.as_ptr().cast::(); + let mut arena = MaybeUninit::::zeroed(); let mut parser = MaybeUninit::::uninit(); unsafe { - pm_parser_init(parser.as_mut_ptr(), source, len, std::ptr::null()); + pm_parser_init(arena.as_mut_ptr(), parser.as_mut_ptr(), source, len, std::ptr::null()); let parser = parser.assume_init_mut(); pm_parser_free(parser); + pm_arena_free(arena.as_mut_ptr()); } } #[test] fn comments_test() { let source = CString::new("# Meow!").unwrap(); + let mut arena = MaybeUninit::::zeroed(); let mut parser = MaybeUninit::::uninit(); unsafe { pm_parser_init( + arena.as_mut_ptr(), parser.as_mut_ptr(), source.as_ptr().cast::(), source.as_bytes().len(), std::ptr::null(), ); let parser = parser.assume_init_mut(); - let node = pm_parse(parser); + let _node = pm_parse(parser); let comment_list = &parser.comment_list; let comment = comment_list.head as *const pm_comment_t; @@ -58,25 +62,27 @@ fn comments_test() { }; assert_eq!(location, 0..7); - pm_node_destroy(parser, node); pm_parser_free(parser); + pm_arena_free(arena.as_mut_ptr()); } } #[test] fn diagnostics_test() { let source = CString::new("class Foo;").unwrap(); + let mut arena = MaybeUninit::::zeroed(); let mut parser = MaybeUninit::::uninit(); unsafe { pm_parser_init( + arena.as_mut_ptr(), parser.as_mut_ptr(), source.as_ptr().cast::(), source.as_bytes().len(), std::ptr::null(), ); let parser = parser.assume_init_mut(); - let node = pm_parse(parser); + let _node = pm_parse(parser); let error_list = &parser.error_list; assert!(!error_list.head.is_null()); @@ -95,7 +101,7 @@ fn diagnostics_test() { }; assert_eq!(location, 10..10); - pm_node_destroy(parser, node); pm_parser_free(parser); + pm_arena_free(arena.as_mut_ptr()); } } diff --git a/rust/ruby-prism/Cargo.toml b/rust/ruby-prism/Cargo.toml index 426ae159dc..302780399c 100644 --- a/rust/ruby-prism/Cargo.toml +++ b/rust/ruby-prism/Cargo.toml @@ -3,7 +3,6 @@ name = "ruby-prism" version = "1.9.0" edition = "2021" license = "MIT" -license-file = "../../LICENSE.md" repository = "https://github.com/ruby/prism" description = "Rustified version of Ruby's prism parsing library" authors = [ diff --git a/rust/ruby-prism/src/lib.rs b/rust/ruby-prism/src/lib.rs index 6824768193..3725633378 100644 --- a/rust/ruby-prism/src/lib.rs +++ b/rust/ruby-prism/src/lib.rs @@ -14,16 +14,340 @@ mod bindings { } mod node; +mod node_ext; mod parse_result; +use std::ffi::CString; use std::mem::MaybeUninit; use std::ptr::NonNull; pub use self::bindings::*; pub use self::node::{ConstantId, ConstantList, ConstantListIter, Integer, NodeList, NodeListIter}; +pub use self::node_ext::{ConstantPathError, FullName}; pub use self::parse_result::{Comment, CommentType, Comments, Diagnostic, Diagnostics, Location, MagicComment, MagicComments, ParseResult}; -use ruby_prism_sys::{pm_parse, pm_parser_init, pm_parser_t}; +use ruby_prism_sys::{ + pm_arena_t, pm_options_command_line_set, pm_options_encoding_locked_set, pm_options_encoding_set, pm_options_filepath_set, pm_options_free, pm_options_frozen_string_literal_set, pm_options_line_set, pm_options_main_script_set, pm_options_partial_script_set, pm_options_scope_forwarding_set, + pm_options_scope_get, pm_options_scope_init, pm_options_scope_local_get, pm_options_scopes_init, pm_options_t, pm_parse, pm_parser_init, pm_parser_t, pm_string_constant_init, +}; + +/// The version of Ruby syntax to parse with. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Version { + /// Use the latest version of prism. + Latest, + /// The vendored version of prism in `CRuby` 3.3.x. + CRuby3_3, + /// The vendored version of prism in `CRuby` 3.4.x. + CRuby3_4, + /// The vendored version of prism in `CRuby` 3.5.x / 4.0.x. + CRuby3_5, + /// The vendored version of prism in `CRuby` 4.1.x. + CRuby4_1, +} + +impl From for ruby_prism_sys::pm_options_version_t { + fn from(version: Version) -> Self { + match version { + Version::Latest => Self::PM_OPTIONS_VERSION_LATEST, + Version::CRuby3_3 => Self::PM_OPTIONS_VERSION_CRUBY_3_3, + Version::CRuby3_4 => Self::PM_OPTIONS_VERSION_CRUBY_3_4, + Version::CRuby3_5 => Self::PM_OPTIONS_VERSION_CRUBY_3_5, + Version::CRuby4_1 => Self::PM_OPTIONS_VERSION_CRUBY_4_1, + } + } +} + +/// A command line option that affects parsing behavior. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum CommandLineFlag { + /// `-a`: splits the input line `$_` into `$F`. + A, + /// `-e`: specifies a script to be executed. + E, + /// `-l`: chomps the input line by default. + L, + /// `-n`: wraps the script in a `while gets` loop. + N, + /// `-p`: prints the value of `$_` at the end of each loop. + P, + /// `-x`: searches the input file for a shebang. + X, +} + +impl From for u8 { + fn from(flag: CommandLineFlag) -> Self { + match flag { + CommandLineFlag::A => ruby_prism_sys::PM_OPTIONS_COMMAND_LINE_A, + CommandLineFlag::E => ruby_prism_sys::PM_OPTIONS_COMMAND_LINE_E, + CommandLineFlag::L => ruby_prism_sys::PM_OPTIONS_COMMAND_LINE_L, + CommandLineFlag::N => ruby_prism_sys::PM_OPTIONS_COMMAND_LINE_N, + CommandLineFlag::P => ruby_prism_sys::PM_OPTIONS_COMMAND_LINE_P, + CommandLineFlag::X => ruby_prism_sys::PM_OPTIONS_COMMAND_LINE_X, + } + } +} + +/// A forwarding parameter for a scope. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum ScopeForwardingFlag { + /// Forwarding with the `*` parameter. + Positionals, + /// Forwarding with the `**` parameter. + Keywords, + /// Forwarding with the `&` parameter. + Block, + /// Forwarding with the `...` parameter. + All, +} + +impl From for u8 { + fn from(flag: ScopeForwardingFlag) -> Self { + match flag { + ScopeForwardingFlag::Positionals => ruby_prism_sys::PM_OPTIONS_SCOPE_FORWARDING_POSITIONALS, + ScopeForwardingFlag::Keywords => ruby_prism_sys::PM_OPTIONS_SCOPE_FORWARDING_KEYWORDS, + ScopeForwardingFlag::Block => ruby_prism_sys::PM_OPTIONS_SCOPE_FORWARDING_BLOCK, + ScopeForwardingFlag::All => ruby_prism_sys::PM_OPTIONS_SCOPE_FORWARDING_ALL, + } + } +} + +/// A scope of locals surrounding the code that is being parsed. +#[derive(Debug, Clone, Default)] +pub struct Scope { + locals: Vec>, + forwarding: Vec, +} + +impl Scope { + /// Sets the local variable names in this scope. + #[must_use] + pub fn locals(mut self, locals: Vec>) -> Self { + self.locals = locals; + self + } + + /// Sets the forwarding parameters in this scope. + #[must_use] + pub fn forwarding(mut self, forwarding: Vec) -> Self { + self.forwarding = forwarding; + self + } +} + +/// Options that can be passed to the parser. +#[derive(Debug, Clone, Default)] +pub struct Options { + filepath: Option, + line: Option, + encoding: Option, + encoding_locked: bool, + frozen_string_literal: Option, + command_line: Vec, + version: Option, + main_script: bool, + partial_script: bool, + scopes: Vec, +} + +impl Options { + /// Sets the filepath option. + #[must_use] + pub fn filepath(mut self, filepath: &str) -> Self { + self.filepath = Some(filepath.to_string()); + self + } + + /// Sets the line option. + #[must_use] + pub const fn line(mut self, line: i32) -> Self { + self.line = Some(line); + self + } + + /// Sets the encoding option. + #[must_use] + pub fn encoding(mut self, encoding: &str) -> Self { + self.encoding = Some(encoding.to_string()); + self + } + + /// Sets the encoding locked option. + #[must_use] + pub const fn encoding_locked(mut self, locked: bool) -> Self { + self.encoding_locked = locked; + self + } + + /// Sets the frozen string literal option. `Some(true)` freezes string + /// literals, `Some(false)` keeps them mutable, and `None` leaves the + /// option unset. + #[must_use] + pub const fn frozen_string_literal(mut self, frozen: Option) -> Self { + self.frozen_string_literal = frozen; + self + } + + /// Sets the command line flags. + #[must_use] + pub fn command_line(mut self, command_line: Vec) -> Self { + self.command_line = command_line; + self + } + + /// Sets the version option. + #[must_use] + pub const fn version(mut self, version: Version) -> Self { + self.version = Some(version); + self + } + + /// Sets the main script option. + #[must_use] + pub const fn main_script(mut self, main_script: bool) -> Self { + self.main_script = main_script; + self + } + + /// Sets the partial script option. + #[must_use] + pub const fn partial_script(mut self, partial_script: bool) -> Self { + self.partial_script = partial_script; + self + } + + /// Adds a scope to the options. + #[must_use] + pub fn scope(mut self, scope: Scope) -> Self { + self.scopes.push(scope); + self + } + + /// Sets the scopes, replacing any previously added scopes. + #[must_use] + pub fn scopes(mut self, scopes: Vec) -> Self { + self.scopes = scopes; + self + } + + /// Builds the C-level parse options from these options. The returned + /// `ParseOptions` must outlive any `ParseResult` created from it. + /// + /// # Panics + /// + /// Panics if `filepath` or `encoding` contain interior null bytes. + #[must_use] + pub fn build(self) -> ParseOptions { + let mut opts = pm_options_t::default(); + + let c_filepath = self.filepath.map(|filepath| { + let cstring = CString::new(filepath).unwrap(); + unsafe { pm_options_filepath_set(&raw mut opts, cstring.as_ptr()) }; + cstring + }); + + if let Some(line) = self.line { + unsafe { pm_options_line_set(&raw mut opts, line) }; + } + + let c_encoding = self.encoding.map(|encoding| { + let cstring = CString::new(encoding).unwrap(); + unsafe { pm_options_encoding_set(&raw mut opts, cstring.as_ptr()) }; + cstring + }); + + if self.encoding_locked { + unsafe { pm_options_encoding_locked_set(&raw mut opts, true) }; + } + + if let Some(frozen) = self.frozen_string_literal { + unsafe { pm_options_frozen_string_literal_set(&raw mut opts, frozen) }; + } + + let command_line = self.command_line.iter().fold(0u8, |acc, &flag| acc | u8::from(flag)); + if command_line != 0 { + unsafe { pm_options_command_line_set(&raw mut opts, command_line) }; + } + + if let Some(version) = self.version { + opts.version = version.into(); + } + + if self.main_script { + unsafe { pm_options_main_script_set(&raw mut opts, true) }; + } + + if self.partial_script { + unsafe { pm_options_partial_script_set(&raw mut opts, true) }; + } + + if !self.scopes.is_empty() { + unsafe { pm_options_scopes_init(&raw mut opts, self.scopes.len()) }; + + for (scope_index, scope) in self.scopes.iter().enumerate() { + let pm_scope = unsafe { pm_options_scope_get(&raw const opts, scope_index).cast_mut() }; + unsafe { pm_options_scope_init(pm_scope, scope.locals.len()) }; + + for (local_index, local) in scope.locals.iter().enumerate() { + let pm_local = unsafe { pm_options_scope_local_get(pm_scope, local_index).cast_mut() }; + unsafe { pm_string_constant_init(pm_local, local.as_ptr().cast::(), local.len()) }; + } + + let forwarding = scope.forwarding.iter().fold(0u8, |acc, &flag| acc | u8::from(flag)); + if forwarding != 0 { + unsafe { pm_options_scope_forwarding_set(pm_scope, forwarding) }; + } + } + } + + ParseOptions { + options: opts, + _filepath: c_filepath, + _encoding: c_encoding, + _scopes: self.scopes, + } + } +} + +/// The C-level parse options. Created from [`Options::build`]. Must outlive +/// any [`ParseResult`] created with [`parse_with_options`]. +#[derive(Debug)] +pub struct ParseOptions { + options: pm_options_t, + // These CStrings back the constant pm_string_t values inside `options`. + // They must not be dropped before `options` is freed. + _filepath: Option, + _encoding: Option, + // The scopes data that pm_string_t values point into. + _scopes: Vec, +} + +impl Drop for ParseOptions { + fn drop(&mut self) { + unsafe { pm_options_free(&raw mut self.options) }; + } +} + +/// Initializes a parser, parses the source, and returns the result. +/// +/// # Safety +/// +/// `options` must be a valid pointer to a `pm_options_t` or null. +unsafe fn parse_impl(source: &[u8], options: *const pm_options_t) -> ParseResult<'_> { + let mut arena = Box::new(MaybeUninit::::zeroed().assume_init()); + let uninit = Box::new(MaybeUninit::::uninit()); + let uninit = Box::into_raw(uninit); + + pm_parser_init(arena.as_mut(), (*uninit).as_mut_ptr(), source.as_ptr(), source.len(), options); + + let parser = (*uninit).assume_init_mut(); + let parser = NonNull::new_unchecked(parser); + + let node = pm_parse(parser.as_ptr()); + let node = NonNull::new_unchecked(node); + + ParseResult::new(source, arena, parser, node) +} /// Parses the given source string and returns a parse result. /// @@ -33,20 +357,19 @@ use ruby_prism_sys::{pm_parse, pm_parser_init, pm_parser_t}; /// #[must_use] pub fn parse(source: &[u8]) -> ParseResult<'_> { - unsafe { - let uninit = Box::new(MaybeUninit::::uninit()); - let uninit = Box::into_raw(uninit); - - pm_parser_init((*uninit).as_mut_ptr(), source.as_ptr(), source.len(), std::ptr::null()); - - let parser = (*uninit).assume_init_mut(); - let parser = NonNull::new_unchecked(parser); - - let node = pm_parse(parser.as_ptr()); - let node = NonNull::new_unchecked(node); + unsafe { parse_impl(source, std::ptr::null()) } +} - ParseResult::new(source, parser, node) - } +/// Parses the given source string with the given options and returns a parse +/// result. The `options` must outlive the returned `ParseResult`. +/// +/// # Panics +/// +/// Panics if the parser fails to initialize. +/// +#[must_use] +pub fn parse_with_options<'a>(source: &'a [u8], options: &'a ParseOptions) -> ParseResult<'a> { + unsafe { parse_impl(source, &raw const options.options) } } #[cfg(test)] @@ -65,6 +388,27 @@ mod tests { } } + #[test] + fn line_offsets_test() { + let source = ""; + let result = parse(source.as_ref()); + + let expected: [u32; 1] = [0]; + assert_eq!(expected, result.line_offsets()); + + let source = "1 + 1"; + let result = parse(source.as_ref()); + + let expected: [u32; 1] = [0]; + assert_eq!(expected, result.line_offsets()); + + let source = "begin\n1 + 1\n2 + 2\nend"; + let result = parse(source.as_ref()); + + let expected: [u32; 4] = [0, 6, 12, 18]; + assert_eq!(expected, result.line_offsets()); + } + #[test] fn magic_comments_test() { use crate::MagicComment; @@ -106,7 +450,7 @@ mod tests { } #[test] - fn location_test() { + fn location_slice_test() { let source = "111 + 222 + 333"; let result = parse(source.as_ref()); @@ -121,6 +465,7 @@ mod tests { assert_eq!(slice, "222"); assert_eq!(6, location.start); + assert_eq!(location.start, location.start()); assert_eq!(9, location.end()); let recv_loc = plus.receiver().unwrap().location(); @@ -160,6 +505,48 @@ mod tests { assert_eq!(slice, "222"); } + #[test] + fn location_line_column_test() { + let source = "first\nsecond\nthird"; + let result = parse(source.as_ref()); + + let node = result.node(); + let program = node.as_program_node().unwrap(); + let statements = program.statements().body(); + let mut iter = statements.iter(); + + let _first = iter.next().unwrap(); + let second = iter.next().unwrap(); + let third = iter.next().unwrap(); + + let second_loc = second.location(); + assert_eq!(second_loc.start_line(), 2); + assert_eq!(second_loc.end_line(), 2); + assert_eq!(second_loc.start_column(), 0); + assert_eq!(second_loc.end_column(), 6); + + let third_loc = third.location(); + assert_eq!(third_loc.start_line(), 3); + assert_eq!(third_loc.end_line(), 3); + assert_eq!(third_loc.start_column(), 0); + assert_eq!(third_loc.end_column(), 5); + } + + #[test] + fn location_chop_test() { + let result = parse(b"foo"); + let mut location = result.node().as_program_node().unwrap().location(); + + assert_eq!(location.chop().as_slice(), b"fo"); + assert_eq!(location.chop().chop().chop().as_slice(), b""); + + // Check that we don't go negative. + for _ in 0..10 { + location = location.chop(); + } + assert_eq!(location.as_slice(), b""); + } + #[test] fn visitor_test() { use super::{visit_interpolated_regular_expression_node, visit_regular_expression_node, InterpolatedRegularExpressionNode, RegularExpressionNode, Visit}; @@ -721,6 +1108,55 @@ end assert_eq!(3, extractor.scopes.len()); } + #[test] + fn parse_with_options_frozen_string_literal_test() { + use super::{parse_with_options, Options}; + + let source = b"\"foo\""; + let options = Options::default().frozen_string_literal(Some(true)).build(); + let result = parse_with_options(source, &options); + + let node = result.node(); + let string = node.as_program_node().unwrap().statements().body().iter().next().unwrap(); + let string = string.as_string_node().unwrap(); + assert!(string.is_frozen()); + } + + #[test] + fn parse_with_options_filepath_test() { + use super::{parse_with_options, Options}; + + let source = b"__FILE__"; + let options = Options::default().filepath("test.rb").build(); + let result = parse_with_options(source, &options); + assert!(result.errors().next().is_none()); + } + + #[test] + fn parse_with_options_line_test() { + use super::{parse_with_options, Options}; + + let source = b"1 + 2"; + let options = Options::default().line(10).build(); + let result = parse_with_options(source, &options); + assert!(result.errors().next().is_none()); + } + + #[test] + fn parse_with_options_scopes_test() { + use super::{parse_with_options, Options, Scope}; + + let source = b"x"; + let scope = Scope::default().locals(vec![b"x".to_vec()]); + let options = Options::default().scope(scope).build(); + let result = parse_with_options(source, &options); + assert!(result.errors().next().is_none()); + + let node = result.node(); + let stmt = node.as_program_node().unwrap().statements().body().iter().next().unwrap(); + assert!(stmt.as_local_variable_read_node().is_some()); + } + #[test] fn malformed_shebang() { let source = "#!\x00"; diff --git a/rust/ruby-prism/src/node_ext.rs b/rust/ruby-prism/src/node_ext.rs new file mode 100644 index 0000000000..8e61532315 --- /dev/null +++ b/rust/ruby-prism/src/node_ext.rs @@ -0,0 +1,250 @@ +//! Node extension methods for the prism parser. +//! +//! This module provides convenience methods on AST nodes that aren't generated +//! from the config, mirroring Ruby's `node_ext.rb`. + +use std::fmt; + +use crate::{ConstantPathNode, ConstantPathTargetNode, ConstantReadNode, ConstantTargetNode, ConstantWriteNode, Node}; + +/// Errors for constant path name computation. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ConstantPathError { + /// The constant path contains dynamic parts (e.g., `var::Bar::Baz`). + DynamicParts, + /// The constant path contains missing nodes (e.g., `Foo::`). + MissingNodes, +} + +impl fmt::Display for ConstantPathError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::DynamicParts => { + write!(f, "Constant path contains dynamic parts. Cannot compute full name") + }, + Self::MissingNodes => { + write!(f, "Constant path contains missing nodes. Cannot compute full name") + }, + } + } +} + +impl std::error::Error for ConstantPathError {} + +/// Trait for nodes that can compute their full constant name. +/// +/// Implemented by constant-related nodes (`ConstantReadNode`, +/// `ConstantWriteNode`, `ConstantTargetNode`, `ConstantPathNode`, and +/// `ConstantPathTargetNode`). +pub trait FullName<'pr> { + /// Returns the list of parts for the full name of this constant. + /// + /// # Errors + /// + /// Returns [`ConstantPathError`] if the path contains dynamic parts or + /// missing nodes. + fn full_name_parts(&self) -> Result, ConstantPathError>; + + /// Returns the full name of this constant. + /// + /// # Errors + /// + /// Returns [`ConstantPathError`] if the path contains dynamic parts or + /// missing nodes. + fn full_name(&self) -> Result, ConstantPathError> { + let parts = self.full_name_parts()?; + let mut result = Vec::new(); + for (index, part) in parts.iter().enumerate() { + if index > 0 { + result.extend_from_slice(b"::"); + } + result.extend_from_slice(part); + } + Ok(result) + } +} + +/// Computes `full_name_parts` for a `Node` by dispatching to the appropriate +/// `FullName` implementation. +#[allow(clippy::option_if_let_else)] +fn full_name_parts_for_node<'pr>(node: &Node<'pr>) -> Result, ConstantPathError> { + if let Some(path_node) = node.as_constant_path_node() { + path_node.full_name_parts() + } else if let Some(read_node) = node.as_constant_read_node() { + read_node.full_name_parts() + } else { + Err(ConstantPathError::DynamicParts) + } +} + +/// Computes `full_name_parts` for a constant path node given its name and +/// parent. +fn constant_path_full_name_parts<'pr>(name: Option>, parent: Option>) -> Result, ConstantPathError> { + let name = name.ok_or(ConstantPathError::MissingNodes)?; + + let mut parts = match parent { + Some(parent) => full_name_parts_for_node(&parent)?, + None => vec![b"".as_slice()], + }; + + parts.push(name.as_slice()); + Ok(parts) +} + +/// Implements `FullName` for simple constant nodes that have a `name()` method +/// returning a single constant identifier. +macro_rules! impl_simple_full_name { + ($node_type:ident) => { + impl<'pr> FullName<'pr> for $node_type<'pr> { + fn full_name_parts(&self) -> Result, ConstantPathError> { + Ok(vec![self.name().as_slice()]) + } + } + }; +} + +impl_simple_full_name!(ConstantReadNode); +impl_simple_full_name!(ConstantWriteNode); +impl_simple_full_name!(ConstantTargetNode); + +impl<'pr> FullName<'pr> for ConstantPathNode<'pr> { + fn full_name_parts(&self) -> Result, ConstantPathError> { + constant_path_full_name_parts(self.name(), self.parent()) + } +} + +impl<'pr> FullName<'pr> for ConstantPathTargetNode<'pr> { + fn full_name_parts(&self) -> Result, ConstantPathError> { + constant_path_full_name_parts(self.name(), self.parent()) + } +} + +#[cfg(test)] +mod tests { + use super::{ConstantPathError, FullName}; + use crate::parse; + + #[test] + fn test_full_name_for_constant_read_node() { + let result = parse(b"Foo"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let constant = node.as_constant_read_node().unwrap(); + + assert_eq!(constant.full_name_parts().unwrap(), vec![b"Foo".as_slice()]); + assert_eq!(constant.full_name().unwrap(), b"Foo"); + } + + #[test] + fn test_full_name_for_constant_write_node() { + let result = parse(b"Foo = 1"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let constant = node.as_constant_write_node().unwrap(); + + assert_eq!(constant.full_name_parts().unwrap(), vec![b"Foo".as_slice()]); + assert_eq!(constant.full_name().unwrap(), b"Foo"); + } + + #[test] + fn test_full_name_for_constant_target_node() { + let result = parse(b"Foo, Bar = [1, 2]"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let multi_write = node.as_multi_write_node().unwrap(); + let target = multi_write.lefts().iter().next().unwrap(); + let constant = target.as_constant_target_node().unwrap(); + + assert_eq!(constant.full_name_parts().unwrap(), vec![b"Foo".as_slice()]); + assert_eq!(constant.full_name().unwrap(), b"Foo"); + } + + #[test] + fn test_full_name_for_constant_path() { + let result = parse(b"Foo::Bar"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let constant_path = node.as_constant_path_node().unwrap(); + + assert_eq!(constant_path.full_name_parts().unwrap(), vec![b"Foo".as_slice(), b"Bar".as_slice()]); + assert_eq!(constant_path.full_name().unwrap(), b"Foo::Bar"); + } + + #[test] + fn test_full_name_for_constant_path_with_stovetop() { + let result = parse(b"::Foo::Bar"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let constant_path = node.as_constant_path_node().unwrap(); + + assert_eq!(constant_path.full_name_parts().unwrap(), vec![b"".as_slice(), b"Foo".as_slice(), b"Bar".as_slice()]); + assert_eq!(constant_path.full_name().unwrap(), b"::Foo::Bar"); + } + + #[test] + fn test_full_name_for_constant_path_with_self() { + let source = r" +self:: + Bar::Baz:: + Qux +"; + let result = parse(source.as_bytes()); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let constant_path = node.as_constant_path_node().unwrap(); + + assert_eq!(constant_path.full_name().unwrap_err(), ConstantPathError::DynamicParts); + } + + #[test] + fn test_full_name_for_constant_path_with_variable() { + let source = r" +foo:: + Bar::Baz:: + Qux +"; + let result = parse(source.as_bytes()); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let constant_path = node.as_constant_path_node().unwrap(); + + assert_eq!(constant_path.full_name().unwrap_err(), ConstantPathError::DynamicParts); + } + + #[test] + fn test_full_name_for_constant_path_with_missing_name() { + let result = parse(b"Foo::"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let constant_path = node.as_constant_path_node().unwrap(); + + assert_eq!(constant_path.full_name().unwrap_err(), ConstantPathError::MissingNodes); + } + + #[test] + fn test_full_name_for_constant_path_target() { + let result = parse(b"Foo::Bar, Baz = [1, 2]"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let multi_write = node.as_multi_write_node().unwrap(); + let target = multi_write.lefts().iter().next().unwrap(); + let constant_path = target.as_constant_path_target_node().unwrap(); + + assert_eq!(constant_path.full_name_parts().unwrap(), vec![b"Foo".as_slice(), b"Bar".as_slice()]); + assert_eq!(constant_path.full_name().unwrap(), b"Foo::Bar"); + } + + #[test] + fn test_full_name_for_constant_path_target_with_stovetop() { + let result = parse(b"::Foo, Bar = [1, 2]"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let multi_write = node.as_multi_write_node().unwrap(); + let target = multi_write.lefts().iter().next().unwrap(); + let constant_path = target.as_constant_path_target_node().unwrap(); + + assert_eq!(constant_path.full_name_parts().unwrap(), vec![b"".as_slice(), b"Foo".as_slice()]); + assert_eq!(constant_path.full_name().unwrap(), b"::Foo"); + } + + #[test] + fn test_full_name_for_constant_path_target_with_self() { + let result = parse(b"self::Foo, Bar = [1, 2]"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let multi_write = node.as_multi_write_node().unwrap(); + let target = multi_write.lefts().iter().next().unwrap(); + let constant_path = target.as_constant_path_target_node().unwrap(); + + assert_eq!(constant_path.full_name().unwrap_err(), ConstantPathError::DynamicParts); + } +} diff --git a/rust/ruby-prism/src/parse_result/mod.rs b/rust/ruby-prism/src/parse_result/mod.rs index 33eb1ac9a0..b0e7197707 100644 --- a/rust/ruby-prism/src/parse_result/mod.rs +++ b/rust/ruby-prism/src/parse_result/mod.rs @@ -8,7 +8,7 @@ mod diagnostics; use std::ptr::NonNull; -use ruby_prism_sys::{pm_comment_t, pm_diagnostic_t, pm_location_t, pm_magic_comment_t, pm_node_destroy, pm_node_t, pm_parser_free, pm_parser_t}; +use ruby_prism_sys::{pm_arena_free, pm_arena_t, pm_comment_t, pm_diagnostic_t, pm_line_offset_list_line_column, pm_location_t, pm_magic_comment_t, pm_node_t, pm_parser_free, pm_parser_t}; pub use self::comments::{Comment, CommentType, Comments, MagicComment, MagicComments}; pub use self::diagnostics::{Diagnostic, Diagnostics}; @@ -44,6 +44,12 @@ impl<'pr> Location<'pr> { } } + /// Returns the start offset from the beginning of the parsed source. + #[must_use] + pub const fn start(&self) -> u32 { + self.start + } + /// Returns the end offset from the beginning of the parsed source. #[must_use] pub const fn end(&self) -> u32 { @@ -66,6 +72,56 @@ impl<'pr> Location<'pr> { }) } } + + /// Returns a new location that is the result of chopping off the last byte. + #[must_use] + pub const fn chop(&self) -> Self { + Location { + parser: self.parser, + start: self.start, + length: if self.length == 0 { 0 } else { self.length - 1 }, + marker: std::marker::PhantomData, + } + } +} + +impl Location<'_> { + /// Returns the line number where this location starts. + #[must_use] + pub fn start_line(&self) -> i32 { + self.line_column(self.start).0 + } + + /// Returns the column number in bytes where this location starts from the + /// start of the line. + #[must_use] + pub fn start_column(&self) -> u32 { + self.line_column(self.start).1 + } + + /// Returns the line number where this location ends. + #[must_use] + pub fn end_line(&self) -> i32 { + self.line_column(self.end()).0 + } + + /// Returns the column number in bytes where this location ends from the + /// start of the line. + #[must_use] + pub fn end_column(&self) -> u32 { + self.line_column(self.end()).1 + } + + /// Returns the line and column number for the given byte offset. + fn line_column(&self, cursor: u32) -> (i32, u32) { + // SAFETY: We read the line_offsets and start_line from the parser, + // which is valid for the lifetime of this Location. + unsafe { + let parser = self.parser.as_ptr(); + let result = pm_line_offset_list_line_column(&raw const (*parser).line_offsets, cursor, (*parser).start_line); + (result.line, result.column) + } + } } impl std::fmt::Debug for Location<'_> { @@ -89,13 +145,14 @@ impl std::fmt::Debug for Location<'_> { #[derive(Debug)] pub struct ParseResult<'pr> { source: &'pr [u8], + arena: Box, parser: NonNull, node: NonNull, } impl<'pr> ParseResult<'pr> { - pub(crate) const unsafe fn new(source: &'pr [u8], parser: NonNull, node: NonNull) -> Self { - ParseResult { source, parser, node } + pub(crate) const unsafe fn new(source: &'pr [u8], arena: Box, parser: NonNull, node: NonNull) -> Self { + ParseResult { source, arena, parser, node } } /// Returns the source string that was parsed. @@ -119,6 +176,15 @@ impl<'pr> ParseResult<'pr> { &self.source[start..end] } + /// Returns a slice containing the offsets of the start of each line in the source string + /// that was parsed. + #[must_use] + pub fn line_offsets(&self) -> &'pr [u32] { + unsafe { + let list = &(*self.parser.as_ptr()).line_offsets; + std::slice::from_raw_parts(list.offsets, list.size) + } + } /// Returns an iterator that can be used to iterate over the errors in the /// parse result. #[must_use] @@ -175,14 +241,47 @@ impl<'pr> ParseResult<'pr> { pub fn node(&self) -> Node<'_> { Node::new(self.parser, self.node.as_ptr()) } + + /// Returns true if there were no errors during parsing and false if there + /// were. + #[must_use] + pub fn is_success(&self) -> bool { + self.errors().next().is_none() + } + + /// Returns true if there were errors during parsing and false if there were + /// not. + #[must_use] + pub fn is_failure(&self) -> bool { + !self.is_success() + } } impl Drop for ParseResult<'_> { fn drop(&mut self) { unsafe { - pm_node_destroy(self.parser.as_ptr(), self.node.as_ptr()); pm_parser_free(self.parser.as_ptr()); drop(Box::from_raw(self.parser.as_ptr())); + pm_arena_free(self.arena.as_mut()); } } } + +#[cfg(test)] +mod tests { + use crate::parse; + + #[test] + fn test_is_success() { + let result = parse(b"1 + 1"); + assert!(result.is_success()); + assert!(!result.is_failure()); + } + + #[test] + fn test_is_failure() { + let result = parse(b"<>"); + assert!(result.is_failure()); + assert!(!result.is_success()); + } +} diff --git a/sig/generated/prism.rbs b/sig/generated/prism.rbs new file mode 100644 index 0000000000..4777914d3e --- /dev/null +++ b/sig/generated/prism.rbs @@ -0,0 +1,76 @@ +# Generated from lib/prism.rb with RBS::Inline + +# The Prism Ruby parser. +# +# "Parsing Ruby is suddenly manageable!" +# - You, hopefully +module Prism + # Raised when requested to parse as the currently running Ruby version but Prism has no support for it. + class CurrentVersionError < ArgumentError + # Initialize a new exception for the given ruby version string. + # -- + # : (String version) -> void + def initialize: (String version) -> void + end + + # :call-seq: + # lex_compat(source, **options) -> LexCompat::Result + # + # Returns a parse result whose value is an array of tokens that closely + # resembles the return value of Ripper.lex. + # + # For supported options, see Prism.parse. + # -- + # : (String source, **untyped options) -> LexCompat::Result + def self.lex_compat: (String source, **untyped options) -> LexCompat::Result + + # :call-seq: + # load(source, serialized, freeze) -> ParseResult + # + # Load the serialized AST using the source as a reference into a tree. + # -- + # : (String source, String serialized, ?bool freeze) -> ParseResult + def self.load: (String source, String serialized, ?bool freeze) -> ParseResult + + VERSION: String + + BACKEND: :CEXT | :FFI + + interface _Stream + def gets: (?Integer integer) -> (String | nil) + end + + def self.parse: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseResult + + def self.profile: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> void + + def self.lex: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> LexResult + + def self.parse_lex: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseLexResult + + def self.dump: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> String + + def self.parse_comments: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> Array[Comment] + + def self.parse_success?: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool + + def self.parse_failure?: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool + + def self.parse_stream: (_Stream stream, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseResult + + def self.parse_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseResult + + def self.profile_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> void + + def self.lex_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> LexResult + + def self.parse_lex_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseLexResult + + def self.dump_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> String + + def self.parse_file_comments: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> Array[Comment] + + def self.parse_file_success?: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool + + def self.parse_file_failure?: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool +end diff --git a/sig/generated/prism/compiler.rbs b/sig/generated/prism/compiler.rbs new file mode 100644 index 0000000000..c2e4db0ace --- /dev/null +++ b/sig/generated/prism/compiler.rbs @@ -0,0 +1,492 @@ +# Generated from lib/prism/compiler.rb with RBS::Inline + +module Prism + # A compiler is a visitor that returns the value of each node as it visits. + # This is as opposed to a visitor which will only walk the tree. This can be + # useful when you are trying to compile a tree into a different format. + # + # For example, to build a representation of the tree as s-expressions, you + # could write: + # + # class SExpressions < Prism::Compiler + # def visit_arguments_node(node) = [:arguments, super] + # def visit_call_node(node) = [:call, super] + # def visit_integer_node(node) = [:integer] + # def visit_program_node(node) = [:program, super] + # end + # + # Prism.parse("1 + 2").value.accept(SExpressions.new) + # # => [:program, [[[:call, [[:integer], [:arguments, [[:integer]]]]]]]] + class Compiler < Visitor + # Visit an individual node. + # -- + # : (node?) -> untyped + def visit: (node?) -> untyped + + # Visit a list of nodes. + # -- + # : (Array[node?]) -> untyped + def visit_all: (Array[node?]) -> untyped + + # Visit the child nodes of the given node. + # -- + # : (node) -> Array[untyped] + def visit_child_nodes: (node) -> Array[untyped] + + # : (AliasGlobalVariableNode) -> Array[untyped] + def visit_alias_global_variable_node: (AliasGlobalVariableNode) -> Array[untyped] + + # : (AliasMethodNode) -> Array[untyped] + def visit_alias_method_node: (AliasMethodNode) -> Array[untyped] + + # : (AlternationPatternNode) -> Array[untyped] + def visit_alternation_pattern_node: (AlternationPatternNode) -> Array[untyped] + + # : (AndNode) -> Array[untyped] + def visit_and_node: (AndNode) -> Array[untyped] + + # : (ArgumentsNode) -> Array[untyped] + def visit_arguments_node: (ArgumentsNode) -> Array[untyped] + + # : (ArrayNode) -> Array[untyped] + def visit_array_node: (ArrayNode) -> Array[untyped] + + # : (ArrayPatternNode) -> Array[untyped] + def visit_array_pattern_node: (ArrayPatternNode) -> Array[untyped] + + # : (AssocNode) -> Array[untyped] + def visit_assoc_node: (AssocNode) -> Array[untyped] + + # : (AssocSplatNode) -> Array[untyped] + def visit_assoc_splat_node: (AssocSplatNode) -> Array[untyped] + + # : (BackReferenceReadNode) -> Array[untyped] + def visit_back_reference_read_node: (BackReferenceReadNode) -> Array[untyped] + + # : (BeginNode) -> Array[untyped] + def visit_begin_node: (BeginNode) -> Array[untyped] + + # : (BlockArgumentNode) -> Array[untyped] + def visit_block_argument_node: (BlockArgumentNode) -> Array[untyped] + + # : (BlockLocalVariableNode) -> Array[untyped] + def visit_block_local_variable_node: (BlockLocalVariableNode) -> Array[untyped] + + # : (BlockNode) -> Array[untyped] + def visit_block_node: (BlockNode) -> Array[untyped] + + # : (BlockParameterNode) -> Array[untyped] + def visit_block_parameter_node: (BlockParameterNode) -> Array[untyped] + + # : (BlockParametersNode) -> Array[untyped] + def visit_block_parameters_node: (BlockParametersNode) -> Array[untyped] + + # : (BreakNode) -> Array[untyped] + def visit_break_node: (BreakNode) -> Array[untyped] + + # : (CallAndWriteNode) -> Array[untyped] + def visit_call_and_write_node: (CallAndWriteNode) -> Array[untyped] + + # : (CallNode) -> Array[untyped] + def visit_call_node: (CallNode) -> Array[untyped] + + # : (CallOperatorWriteNode) -> Array[untyped] + def visit_call_operator_write_node: (CallOperatorWriteNode) -> Array[untyped] + + # : (CallOrWriteNode) -> Array[untyped] + def visit_call_or_write_node: (CallOrWriteNode) -> Array[untyped] + + # : (CallTargetNode) -> Array[untyped] + def visit_call_target_node: (CallTargetNode) -> Array[untyped] + + # : (CapturePatternNode) -> Array[untyped] + def visit_capture_pattern_node: (CapturePatternNode) -> Array[untyped] + + # : (CaseMatchNode) -> Array[untyped] + def visit_case_match_node: (CaseMatchNode) -> Array[untyped] + + # : (CaseNode) -> Array[untyped] + def visit_case_node: (CaseNode) -> Array[untyped] + + # : (ClassNode) -> Array[untyped] + def visit_class_node: (ClassNode) -> Array[untyped] + + # : (ClassVariableAndWriteNode) -> Array[untyped] + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode) -> Array[untyped] + + # : (ClassVariableOperatorWriteNode) -> Array[untyped] + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode) -> Array[untyped] + + # : (ClassVariableOrWriteNode) -> Array[untyped] + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode) -> Array[untyped] + + # : (ClassVariableReadNode) -> Array[untyped] + def visit_class_variable_read_node: (ClassVariableReadNode) -> Array[untyped] + + # : (ClassVariableTargetNode) -> Array[untyped] + def visit_class_variable_target_node: (ClassVariableTargetNode) -> Array[untyped] + + # : (ClassVariableWriteNode) -> Array[untyped] + def visit_class_variable_write_node: (ClassVariableWriteNode) -> Array[untyped] + + # : (ConstantAndWriteNode) -> Array[untyped] + def visit_constant_and_write_node: (ConstantAndWriteNode) -> Array[untyped] + + # : (ConstantOperatorWriteNode) -> Array[untyped] + def visit_constant_operator_write_node: (ConstantOperatorWriteNode) -> Array[untyped] + + # : (ConstantOrWriteNode) -> Array[untyped] + def visit_constant_or_write_node: (ConstantOrWriteNode) -> Array[untyped] + + # : (ConstantPathAndWriteNode) -> Array[untyped] + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode) -> Array[untyped] + + # : (ConstantPathNode) -> Array[untyped] + def visit_constant_path_node: (ConstantPathNode) -> Array[untyped] + + # : (ConstantPathOperatorWriteNode) -> Array[untyped] + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode) -> Array[untyped] + + # : (ConstantPathOrWriteNode) -> Array[untyped] + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode) -> Array[untyped] + + # : (ConstantPathTargetNode) -> Array[untyped] + def visit_constant_path_target_node: (ConstantPathTargetNode) -> Array[untyped] + + # : (ConstantPathWriteNode) -> Array[untyped] + def visit_constant_path_write_node: (ConstantPathWriteNode) -> Array[untyped] + + # : (ConstantReadNode) -> Array[untyped] + def visit_constant_read_node: (ConstantReadNode) -> Array[untyped] + + # : (ConstantTargetNode) -> Array[untyped] + def visit_constant_target_node: (ConstantTargetNode) -> Array[untyped] + + # : (ConstantWriteNode) -> Array[untyped] + def visit_constant_write_node: (ConstantWriteNode) -> Array[untyped] + + # : (DefNode) -> Array[untyped] + def visit_def_node: (DefNode) -> Array[untyped] + + # : (DefinedNode) -> Array[untyped] + def visit_defined_node: (DefinedNode) -> Array[untyped] + + # : (ElseNode) -> Array[untyped] + def visit_else_node: (ElseNode) -> Array[untyped] + + # : (EmbeddedStatementsNode) -> Array[untyped] + def visit_embedded_statements_node: (EmbeddedStatementsNode) -> Array[untyped] + + # : (EmbeddedVariableNode) -> Array[untyped] + def visit_embedded_variable_node: (EmbeddedVariableNode) -> Array[untyped] + + # : (EnsureNode) -> Array[untyped] + def visit_ensure_node: (EnsureNode) -> Array[untyped] + + # : (FalseNode) -> Array[untyped] + def visit_false_node: (FalseNode) -> Array[untyped] + + # : (FindPatternNode) -> Array[untyped] + def visit_find_pattern_node: (FindPatternNode) -> Array[untyped] + + # : (FlipFlopNode) -> Array[untyped] + def visit_flip_flop_node: (FlipFlopNode) -> Array[untyped] + + # : (FloatNode) -> Array[untyped] + def visit_float_node: (FloatNode) -> Array[untyped] + + # : (ForNode) -> Array[untyped] + def visit_for_node: (ForNode) -> Array[untyped] + + # : (ForwardingArgumentsNode) -> Array[untyped] + def visit_forwarding_arguments_node: (ForwardingArgumentsNode) -> Array[untyped] + + # : (ForwardingParameterNode) -> Array[untyped] + def visit_forwarding_parameter_node: (ForwardingParameterNode) -> Array[untyped] + + # : (ForwardingSuperNode) -> Array[untyped] + def visit_forwarding_super_node: (ForwardingSuperNode) -> Array[untyped] + + # : (GlobalVariableAndWriteNode) -> Array[untyped] + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode) -> Array[untyped] + + # : (GlobalVariableOperatorWriteNode) -> Array[untyped] + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode) -> Array[untyped] + + # : (GlobalVariableOrWriteNode) -> Array[untyped] + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode) -> Array[untyped] + + # : (GlobalVariableReadNode) -> Array[untyped] + def visit_global_variable_read_node: (GlobalVariableReadNode) -> Array[untyped] + + # : (GlobalVariableTargetNode) -> Array[untyped] + def visit_global_variable_target_node: (GlobalVariableTargetNode) -> Array[untyped] + + # : (GlobalVariableWriteNode) -> Array[untyped] + def visit_global_variable_write_node: (GlobalVariableWriteNode) -> Array[untyped] + + # : (HashNode) -> Array[untyped] + def visit_hash_node: (HashNode) -> Array[untyped] + + # : (HashPatternNode) -> Array[untyped] + def visit_hash_pattern_node: (HashPatternNode) -> Array[untyped] + + # : (IfNode) -> Array[untyped] + def visit_if_node: (IfNode) -> Array[untyped] + + # : (ImaginaryNode) -> Array[untyped] + def visit_imaginary_node: (ImaginaryNode) -> Array[untyped] + + # : (ImplicitNode) -> Array[untyped] + def visit_implicit_node: (ImplicitNode) -> Array[untyped] + + # : (ImplicitRestNode) -> Array[untyped] + def visit_implicit_rest_node: (ImplicitRestNode) -> Array[untyped] + + # : (InNode) -> Array[untyped] + def visit_in_node: (InNode) -> Array[untyped] + + # : (IndexAndWriteNode) -> Array[untyped] + def visit_index_and_write_node: (IndexAndWriteNode) -> Array[untyped] + + # : (IndexOperatorWriteNode) -> Array[untyped] + def visit_index_operator_write_node: (IndexOperatorWriteNode) -> Array[untyped] + + # : (IndexOrWriteNode) -> Array[untyped] + def visit_index_or_write_node: (IndexOrWriteNode) -> Array[untyped] + + # : (IndexTargetNode) -> Array[untyped] + def visit_index_target_node: (IndexTargetNode) -> Array[untyped] + + # : (InstanceVariableAndWriteNode) -> Array[untyped] + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode) -> Array[untyped] + + # : (InstanceVariableOperatorWriteNode) -> Array[untyped] + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode) -> Array[untyped] + + # : (InstanceVariableOrWriteNode) -> Array[untyped] + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode) -> Array[untyped] + + # : (InstanceVariableReadNode) -> Array[untyped] + def visit_instance_variable_read_node: (InstanceVariableReadNode) -> Array[untyped] + + # : (InstanceVariableTargetNode) -> Array[untyped] + def visit_instance_variable_target_node: (InstanceVariableTargetNode) -> Array[untyped] + + # : (InstanceVariableWriteNode) -> Array[untyped] + def visit_instance_variable_write_node: (InstanceVariableWriteNode) -> Array[untyped] + + # : (IntegerNode) -> Array[untyped] + def visit_integer_node: (IntegerNode) -> Array[untyped] + + # : (InterpolatedMatchLastLineNode) -> Array[untyped] + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode) -> Array[untyped] + + # : (InterpolatedRegularExpressionNode) -> Array[untyped] + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode) -> Array[untyped] + + # : (InterpolatedStringNode) -> Array[untyped] + def visit_interpolated_string_node: (InterpolatedStringNode) -> Array[untyped] + + # : (InterpolatedSymbolNode) -> Array[untyped] + def visit_interpolated_symbol_node: (InterpolatedSymbolNode) -> Array[untyped] + + # : (InterpolatedXStringNode) -> Array[untyped] + def visit_interpolated_x_string_node: (InterpolatedXStringNode) -> Array[untyped] + + # : (ItLocalVariableReadNode) -> Array[untyped] + def visit_it_local_variable_read_node: (ItLocalVariableReadNode) -> Array[untyped] + + # : (ItParametersNode) -> Array[untyped] + def visit_it_parameters_node: (ItParametersNode) -> Array[untyped] + + # : (KeywordHashNode) -> Array[untyped] + def visit_keyword_hash_node: (KeywordHashNode) -> Array[untyped] + + # : (KeywordRestParameterNode) -> Array[untyped] + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode) -> Array[untyped] + + # : (LambdaNode) -> Array[untyped] + def visit_lambda_node: (LambdaNode) -> Array[untyped] + + # : (LocalVariableAndWriteNode) -> Array[untyped] + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode) -> Array[untyped] + + # : (LocalVariableOperatorWriteNode) -> Array[untyped] + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode) -> Array[untyped] + + # : (LocalVariableOrWriteNode) -> Array[untyped] + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode) -> Array[untyped] + + # : (LocalVariableReadNode) -> Array[untyped] + def visit_local_variable_read_node: (LocalVariableReadNode) -> Array[untyped] + + # : (LocalVariableTargetNode) -> Array[untyped] + def visit_local_variable_target_node: (LocalVariableTargetNode) -> Array[untyped] + + # : (LocalVariableWriteNode) -> Array[untyped] + def visit_local_variable_write_node: (LocalVariableWriteNode) -> Array[untyped] + + # : (MatchLastLineNode) -> Array[untyped] + def visit_match_last_line_node: (MatchLastLineNode) -> Array[untyped] + + # : (MatchPredicateNode) -> Array[untyped] + def visit_match_predicate_node: (MatchPredicateNode) -> Array[untyped] + + # : (MatchRequiredNode) -> Array[untyped] + def visit_match_required_node: (MatchRequiredNode) -> Array[untyped] + + # : (MatchWriteNode) -> Array[untyped] + def visit_match_write_node: (MatchWriteNode) -> Array[untyped] + + # : (MissingNode) -> Array[untyped] + def visit_missing_node: (MissingNode) -> Array[untyped] + + # : (ModuleNode) -> Array[untyped] + def visit_module_node: (ModuleNode) -> Array[untyped] + + # : (MultiTargetNode) -> Array[untyped] + def visit_multi_target_node: (MultiTargetNode) -> Array[untyped] + + # : (MultiWriteNode) -> Array[untyped] + def visit_multi_write_node: (MultiWriteNode) -> Array[untyped] + + # : (NextNode) -> Array[untyped] + def visit_next_node: (NextNode) -> Array[untyped] + + # : (NilNode) -> Array[untyped] + def visit_nil_node: (NilNode) -> Array[untyped] + + # : (NoBlockParameterNode) -> Array[untyped] + def visit_no_block_parameter_node: (NoBlockParameterNode) -> Array[untyped] + + # : (NoKeywordsParameterNode) -> Array[untyped] + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode) -> Array[untyped] + + # : (NumberedParametersNode) -> Array[untyped] + def visit_numbered_parameters_node: (NumberedParametersNode) -> Array[untyped] + + # : (NumberedReferenceReadNode) -> Array[untyped] + def visit_numbered_reference_read_node: (NumberedReferenceReadNode) -> Array[untyped] + + # : (OptionalKeywordParameterNode) -> Array[untyped] + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode) -> Array[untyped] + + # : (OptionalParameterNode) -> Array[untyped] + def visit_optional_parameter_node: (OptionalParameterNode) -> Array[untyped] + + # : (OrNode) -> Array[untyped] + def visit_or_node: (OrNode) -> Array[untyped] + + # : (ParametersNode) -> Array[untyped] + def visit_parameters_node: (ParametersNode) -> Array[untyped] + + # : (ParenthesesNode) -> Array[untyped] + def visit_parentheses_node: (ParenthesesNode) -> Array[untyped] + + # : (PinnedExpressionNode) -> Array[untyped] + def visit_pinned_expression_node: (PinnedExpressionNode) -> Array[untyped] + + # : (PinnedVariableNode) -> Array[untyped] + def visit_pinned_variable_node: (PinnedVariableNode) -> Array[untyped] + + # : (PostExecutionNode) -> Array[untyped] + def visit_post_execution_node: (PostExecutionNode) -> Array[untyped] + + # : (PreExecutionNode) -> Array[untyped] + def visit_pre_execution_node: (PreExecutionNode) -> Array[untyped] + + # : (ProgramNode) -> Array[untyped] + def visit_program_node: (ProgramNode) -> Array[untyped] + + # : (RangeNode) -> Array[untyped] + def visit_range_node: (RangeNode) -> Array[untyped] + + # : (RationalNode) -> Array[untyped] + def visit_rational_node: (RationalNode) -> Array[untyped] + + # : (RedoNode) -> Array[untyped] + def visit_redo_node: (RedoNode) -> Array[untyped] + + # : (RegularExpressionNode) -> Array[untyped] + def visit_regular_expression_node: (RegularExpressionNode) -> Array[untyped] + + # : (RequiredKeywordParameterNode) -> Array[untyped] + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode) -> Array[untyped] + + # : (RequiredParameterNode) -> Array[untyped] + def visit_required_parameter_node: (RequiredParameterNode) -> Array[untyped] + + # : (RescueModifierNode) -> Array[untyped] + def visit_rescue_modifier_node: (RescueModifierNode) -> Array[untyped] + + # : (RescueNode) -> Array[untyped] + def visit_rescue_node: (RescueNode) -> Array[untyped] + + # : (RestParameterNode) -> Array[untyped] + def visit_rest_parameter_node: (RestParameterNode) -> Array[untyped] + + # : (RetryNode) -> Array[untyped] + def visit_retry_node: (RetryNode) -> Array[untyped] + + # : (ReturnNode) -> Array[untyped] + def visit_return_node: (ReturnNode) -> Array[untyped] + + # : (SelfNode) -> Array[untyped] + def visit_self_node: (SelfNode) -> Array[untyped] + + # : (ShareableConstantNode) -> Array[untyped] + def visit_shareable_constant_node: (ShareableConstantNode) -> Array[untyped] + + # : (SingletonClassNode) -> Array[untyped] + def visit_singleton_class_node: (SingletonClassNode) -> Array[untyped] + + # : (SourceEncodingNode) -> Array[untyped] + def visit_source_encoding_node: (SourceEncodingNode) -> Array[untyped] + + # : (SourceFileNode) -> Array[untyped] + def visit_source_file_node: (SourceFileNode) -> Array[untyped] + + # : (SourceLineNode) -> Array[untyped] + def visit_source_line_node: (SourceLineNode) -> Array[untyped] + + # : (SplatNode) -> Array[untyped] + def visit_splat_node: (SplatNode) -> Array[untyped] + + # : (StatementsNode) -> Array[untyped] + def visit_statements_node: (StatementsNode) -> Array[untyped] + + # : (StringNode) -> Array[untyped] + def visit_string_node: (StringNode) -> Array[untyped] + + # : (SuperNode) -> Array[untyped] + def visit_super_node: (SuperNode) -> Array[untyped] + + # : (SymbolNode) -> Array[untyped] + def visit_symbol_node: (SymbolNode) -> Array[untyped] + + # : (TrueNode) -> Array[untyped] + def visit_true_node: (TrueNode) -> Array[untyped] + + # : (UndefNode) -> Array[untyped] + def visit_undef_node: (UndefNode) -> Array[untyped] + + # : (UnlessNode) -> Array[untyped] + def visit_unless_node: (UnlessNode) -> Array[untyped] + + # : (UntilNode) -> Array[untyped] + def visit_until_node: (UntilNode) -> Array[untyped] + + # : (WhenNode) -> Array[untyped] + def visit_when_node: (WhenNode) -> Array[untyped] + + # : (WhileNode) -> Array[untyped] + def visit_while_node: (WhileNode) -> Array[untyped] + + # : (XStringNode) -> Array[untyped] + def visit_x_string_node: (XStringNode) -> Array[untyped] + + # : (YieldNode) -> Array[untyped] + def visit_yield_node: (YieldNode) -> Array[untyped] + end +end diff --git a/sig/generated/prism/desugar_compiler.rbs b/sig/generated/prism/desugar_compiler.rbs new file mode 100644 index 0000000000..d5bb07edf1 --- /dev/null +++ b/sig/generated/prism/desugar_compiler.rbs @@ -0,0 +1,305 @@ +# Generated from lib/prism/desugar_compiler.rb with RBS::Inline + +module Prism + class DesugarAndWriteNode + include DSL + + attr_reader node: ClassVariableAndWriteNode | ConstantAndWriteNode | GlobalVariableAndWriteNode | InstanceVariableAndWriteNode | LocalVariableAndWriteNode + + attr_reader default_source: Source + + attr_reader read_class: Symbol + + attr_reader write_class: Symbol + + attr_reader arguments: Hash[Symbol, untyped] + + # : ((ClassVariableAndWriteNode | ConstantAndWriteNode | GlobalVariableAndWriteNode | InstanceVariableAndWriteNode | LocalVariableAndWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + def initialize: (ClassVariableAndWriteNode | ConstantAndWriteNode | GlobalVariableAndWriteNode | InstanceVariableAndWriteNode | LocalVariableAndWriteNode node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + + # Desugar `x &&= y` to `x && x = y` + # -- + # : () -> node + def compile: () -> node + end + + class DesugarOrWriteDefinedNode + include DSL + + attr_reader node: ClassVariableOrWriteNode | ConstantOrWriteNode | GlobalVariableOrWriteNode + + attr_reader default_source: Source + + attr_reader read_class: Symbol + + attr_reader write_class: Symbol + + attr_reader arguments: Hash[Symbol, untyped] + + # : ((ClassVariableOrWriteNode | ConstantOrWriteNode | GlobalVariableOrWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + def initialize: (ClassVariableOrWriteNode | ConstantOrWriteNode | GlobalVariableOrWriteNode node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + + # Desugar `x ||= y` to `defined?(x) ? x : x = y` + # -- + # : () -> node + def compile: () -> node + end + + class DesugarOperatorWriteNode + include DSL + + attr_reader node: ClassVariableOperatorWriteNode | ConstantOperatorWriteNode | GlobalVariableOperatorWriteNode | InstanceVariableOperatorWriteNode | LocalVariableOperatorWriteNode + + attr_reader default_source: Source + + attr_reader read_class: Symbol + + attr_reader write_class: Symbol + + attr_reader arguments: Hash[Symbol, untyped] + + # : ((ClassVariableOperatorWriteNode | ConstantOperatorWriteNode | GlobalVariableOperatorWriteNode | InstanceVariableOperatorWriteNode | LocalVariableOperatorWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + def initialize: (ClassVariableOperatorWriteNode | ConstantOperatorWriteNode | GlobalVariableOperatorWriteNode | InstanceVariableOperatorWriteNode | LocalVariableOperatorWriteNode node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + + # Desugar `x += y` to `x = x + y` + # -- + # : () -> node + def compile: () -> node + end + + class DesugarOrWriteNode + include DSL + + attr_reader node: InstanceVariableOrWriteNode | LocalVariableOrWriteNode + + attr_reader default_source: Source + + attr_reader read_class: Symbol + + attr_reader write_class: Symbol + + attr_reader arguments: Hash[Symbol, untyped] + + # : ((InstanceVariableOrWriteNode | LocalVariableOrWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + def initialize: (InstanceVariableOrWriteNode | LocalVariableOrWriteNode node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + + # Desugar `x ||= y` to `x || x = y` + # -- + # : () -> node + def compile: () -> node + end + + class ClassVariableAndWriteNode + # : () -> node + def desugar: () -> node + end + + class ClassVariableOrWriteNode + # : () -> node + def desugar: () -> node + end + + class ClassVariableOperatorWriteNode + # : () -> node + def desugar: () -> node + end + + class ConstantAndWriteNode + # : () -> node + def desugar: () -> node + end + + class ConstantOrWriteNode + # : () -> node + def desugar: () -> node + end + + class ConstantOperatorWriteNode + # : () -> node + def desugar: () -> node + end + + class GlobalVariableAndWriteNode + # : () -> node + def desugar: () -> node + end + + class GlobalVariableOrWriteNode + # : () -> node + def desugar: () -> node + end + + class GlobalVariableOperatorWriteNode + # : () -> node + def desugar: () -> node + end + + class InstanceVariableAndWriteNode + # : () -> node + def desugar: () -> node + end + + class InstanceVariableOrWriteNode + # : () -> node + def desugar: () -> node + end + + class InstanceVariableOperatorWriteNode + # : () -> node + def desugar: () -> node + end + + class LocalVariableAndWriteNode + # : () -> node + def desugar: () -> node + end + + class LocalVariableOrWriteNode + # : () -> node + def desugar: () -> node + end + + class LocalVariableOperatorWriteNode + # : () -> node + def desugar: () -> node + end + + # DesugarCompiler is a compiler that desugars Ruby code into a more primitive + # form. This is useful for consumers that want to deal with fewer node types. + class DesugarCompiler < MutationCompiler + # `@@foo &&= bar` + # + # becomes + # + # `@@foo && @@foo = bar` + # -- + # : (ClassVariableAndWriteNode node) -> node + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode node) -> node + + # `@@foo ||= bar` + # + # becomes + # + # `defined?(@@foo) ? @@foo : @@foo = bar` + # -- + # : (ClassVariableOrWriteNode node) -> node + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode node) -> node + + # `@@foo += bar` + # + # becomes + # + # `@@foo = @@foo + bar` + # -- + # : (ClassVariableOperatorWriteNode node) -> node + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode node) -> node + + # `Foo &&= bar` + # + # becomes + # + # `Foo && Foo = bar` + # -- + # : (ConstantAndWriteNode node) -> node + def visit_constant_and_write_node: (ConstantAndWriteNode node) -> node + + # `Foo ||= bar` + # + # becomes + # + # `defined?(Foo) ? Foo : Foo = bar` + # -- + # : (ConstantOrWriteNode node) -> node + def visit_constant_or_write_node: (ConstantOrWriteNode node) -> node + + # `Foo += bar` + # + # becomes + # + # `Foo = Foo + bar` + # -- + # : (ConstantOperatorWriteNode node) -> node + def visit_constant_operator_write_node: (ConstantOperatorWriteNode node) -> node + + # `$foo &&= bar` + # + # becomes + # + # `$foo && $foo = bar` + # -- + # : (GlobalVariableAndWriteNode node) -> node + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode node) -> node + + # `$foo ||= bar` + # + # becomes + # + # `defined?($foo) ? $foo : $foo = bar` + # -- + # : (GlobalVariableOrWriteNode node) -> node + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode node) -> node + + # `$foo += bar` + # + # becomes + # + # `$foo = $foo + bar` + # -- + # : (GlobalVariableOperatorWriteNode node) -> node + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode node) -> node + + # `@foo &&= bar` + # + # becomes + # + # `@foo && @foo = bar` + # -- + # : (InstanceVariableAndWriteNode node) -> node + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode node) -> node + + # `@foo ||= bar` + # + # becomes + # + # `@foo || @foo = bar` + # -- + # : (InstanceVariableOrWriteNode node) -> node + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode node) -> node + + # `@foo += bar` + # + # becomes + # + # `@foo = @foo + bar` + # -- + # : (InstanceVariableOperatorWriteNode node) -> node + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode node) -> node + + # `foo &&= bar` + # + # becomes + # + # `foo && foo = bar` + # -- + # : (LocalVariableAndWriteNode node) -> node + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode node) -> node + + # `foo ||= bar` + # + # becomes + # + # `foo || foo = bar` + # -- + # : (LocalVariableOrWriteNode node) -> node + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode node) -> node + + # `foo += bar` + # + # becomes + # + # `foo = foo + bar` + # -- + # : (LocalVariableOperatorWriteNode node) -> node + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode node) -> node + end +end diff --git a/sig/generated/prism/dispatcher.rbs b/sig/generated/prism/dispatcher.rbs new file mode 100644 index 0000000000..0463d2b0ba --- /dev/null +++ b/sig/generated/prism/dispatcher.rbs @@ -0,0 +1,1292 @@ +# Generated from lib/prism/dispatcher.rb with RBS::Inline + +module Prism + # The dispatcher class fires events for nodes that are found while walking an + # AST to all registered listeners. It's useful for performing different types + # of analysis on the AST while only having to walk the tree once. + # + # To use the dispatcher, you would first instantiate it and register listeners + # for the events you're interested in: + # + # class OctalListener + # def on_integer_node_enter(node) + # if node.octal? && !node.slice.start_with?("0o") + # warn("Octal integers should be written with the 0o prefix") + # end + # end + # end + # + # 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: + # + # result = Prism.parse("001 + 002 + 003") + # dispatcher.dispatch(result.value) + # + # Optionally, you can also use `#dispatch_once` to dispatch enter and leave + # events for a single node without recursing further down the tree. This can + # be useful in circumstances where you want to reuse the listeners you already + # have registers but want to stop walking the tree at a certain point. + # + # integer = result.value.statements.body.first.receiver.receiver + # dispatcher.dispatch_once(integer) + class Dispatcher < Visitor + # A hash mapping event names to arrays of listeners that should be notified + # when that event is fired. + attr_reader listeners: Hash[Symbol, Array[untyped]] + + # Initialize a new dispatcher. + # -- + # : () -> void + def initialize: () -> void + + # Register a listener for one or more events. + # -- + # : (untyped, *Symbol) -> void + def register: (untyped, *Symbol) -> void + + # Register all public methods of a listener that match the pattern + # `on__(enter|leave)`. + # -- + # : (untyped) -> void + def register_public_methods: (untyped) -> void + + # Register a listener for the given events. + # -- + # : (untyped, Array[Symbol]) -> void + private def register_events: (untyped, Array[Symbol]) -> void + + # Walks `root` dispatching events to all registered listeners. + alias dispatch visit + + # Dispatches a single event for `node` to all registered listeners. + # -- + # : (node node) -> void + def dispatch_once: (node node) -> void + + # : (AliasGlobalVariableNode node) -> void + def visit_alias_global_variable_node: (AliasGlobalVariableNode node) -> void + + # : (AliasMethodNode node) -> void + def visit_alias_method_node: (AliasMethodNode node) -> void + + # : (AlternationPatternNode node) -> void + def visit_alternation_pattern_node: (AlternationPatternNode node) -> void + + # : (AndNode node) -> void + def visit_and_node: (AndNode node) -> void + + # : (ArgumentsNode node) -> void + def visit_arguments_node: (ArgumentsNode node) -> void + + # : (ArrayNode node) -> void + def visit_array_node: (ArrayNode node) -> void + + # : (ArrayPatternNode node) -> void + def visit_array_pattern_node: (ArrayPatternNode node) -> void + + # : (AssocNode node) -> void + def visit_assoc_node: (AssocNode node) -> void + + # : (AssocSplatNode node) -> void + def visit_assoc_splat_node: (AssocSplatNode node) -> void + + # : (BackReferenceReadNode node) -> void + def visit_back_reference_read_node: (BackReferenceReadNode node) -> void + + # : (BeginNode node) -> void + def visit_begin_node: (BeginNode node) -> void + + # : (BlockArgumentNode node) -> void + def visit_block_argument_node: (BlockArgumentNode node) -> void + + # : (BlockLocalVariableNode node) -> void + def visit_block_local_variable_node: (BlockLocalVariableNode node) -> void + + # : (BlockNode node) -> void + def visit_block_node: (BlockNode node) -> void + + # : (BlockParameterNode node) -> void + def visit_block_parameter_node: (BlockParameterNode node) -> void + + # : (BlockParametersNode node) -> void + def visit_block_parameters_node: (BlockParametersNode node) -> void + + # : (BreakNode node) -> void + def visit_break_node: (BreakNode node) -> void + + # : (CallAndWriteNode node) -> void + def visit_call_and_write_node: (CallAndWriteNode node) -> void + + # : (CallNode node) -> void + def visit_call_node: (CallNode node) -> void + + # : (CallOperatorWriteNode node) -> void + def visit_call_operator_write_node: (CallOperatorWriteNode node) -> void + + # : (CallOrWriteNode node) -> void + def visit_call_or_write_node: (CallOrWriteNode node) -> void + + # : (CallTargetNode node) -> void + def visit_call_target_node: (CallTargetNode node) -> void + + # : (CapturePatternNode node) -> void + def visit_capture_pattern_node: (CapturePatternNode node) -> void + + # : (CaseMatchNode node) -> void + def visit_case_match_node: (CaseMatchNode node) -> void + + # : (CaseNode node) -> void + def visit_case_node: (CaseNode node) -> void + + # : (ClassNode node) -> void + def visit_class_node: (ClassNode node) -> void + + # : (ClassVariableAndWriteNode node) -> void + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode node) -> void + + # : (ClassVariableOperatorWriteNode node) -> void + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode node) -> void + + # : (ClassVariableOrWriteNode node) -> void + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode node) -> void + + # : (ClassVariableReadNode node) -> void + def visit_class_variable_read_node: (ClassVariableReadNode node) -> void + + # : (ClassVariableTargetNode node) -> void + def visit_class_variable_target_node: (ClassVariableTargetNode node) -> void + + # : (ClassVariableWriteNode node) -> void + def visit_class_variable_write_node: (ClassVariableWriteNode node) -> void + + # : (ConstantAndWriteNode node) -> void + def visit_constant_and_write_node: (ConstantAndWriteNode node) -> void + + # : (ConstantOperatorWriteNode node) -> void + def visit_constant_operator_write_node: (ConstantOperatorWriteNode node) -> void + + # : (ConstantOrWriteNode node) -> void + def visit_constant_or_write_node: (ConstantOrWriteNode node) -> void + + # : (ConstantPathAndWriteNode node) -> void + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode node) -> void + + # : (ConstantPathNode node) -> void + def visit_constant_path_node: (ConstantPathNode node) -> void + + # : (ConstantPathOperatorWriteNode node) -> void + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode node) -> void + + # : (ConstantPathOrWriteNode node) -> void + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode node) -> void + + # : (ConstantPathTargetNode node) -> void + def visit_constant_path_target_node: (ConstantPathTargetNode node) -> void + + # : (ConstantPathWriteNode node) -> void + def visit_constant_path_write_node: (ConstantPathWriteNode node) -> void + + # : (ConstantReadNode node) -> void + def visit_constant_read_node: (ConstantReadNode node) -> void + + # : (ConstantTargetNode node) -> void + def visit_constant_target_node: (ConstantTargetNode node) -> void + + # : (ConstantWriteNode node) -> void + def visit_constant_write_node: (ConstantWriteNode node) -> void + + # : (DefNode node) -> void + def visit_def_node: (DefNode node) -> void + + # : (DefinedNode node) -> void + def visit_defined_node: (DefinedNode node) -> void + + # : (ElseNode node) -> void + def visit_else_node: (ElseNode node) -> void + + # : (EmbeddedStatementsNode node) -> void + def visit_embedded_statements_node: (EmbeddedStatementsNode node) -> void + + # : (EmbeddedVariableNode node) -> void + def visit_embedded_variable_node: (EmbeddedVariableNode node) -> void + + # : (EnsureNode node) -> void + def visit_ensure_node: (EnsureNode node) -> void + + # : (FalseNode node) -> void + def visit_false_node: (FalseNode node) -> void + + # : (FindPatternNode node) -> void + def visit_find_pattern_node: (FindPatternNode node) -> void + + # : (FlipFlopNode node) -> void + def visit_flip_flop_node: (FlipFlopNode node) -> void + + # : (FloatNode node) -> void + def visit_float_node: (FloatNode node) -> void + + # : (ForNode node) -> void + def visit_for_node: (ForNode node) -> void + + # : (ForwardingArgumentsNode node) -> void + def visit_forwarding_arguments_node: (ForwardingArgumentsNode node) -> void + + # : (ForwardingParameterNode node) -> void + def visit_forwarding_parameter_node: (ForwardingParameterNode node) -> void + + # : (ForwardingSuperNode node) -> void + def visit_forwarding_super_node: (ForwardingSuperNode node) -> void + + # : (GlobalVariableAndWriteNode node) -> void + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode node) -> void + + # : (GlobalVariableOperatorWriteNode node) -> void + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode node) -> void + + # : (GlobalVariableOrWriteNode node) -> void + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode node) -> void + + # : (GlobalVariableReadNode node) -> void + def visit_global_variable_read_node: (GlobalVariableReadNode node) -> void + + # : (GlobalVariableTargetNode node) -> void + def visit_global_variable_target_node: (GlobalVariableTargetNode node) -> void + + # : (GlobalVariableWriteNode node) -> void + def visit_global_variable_write_node: (GlobalVariableWriteNode node) -> void + + # : (HashNode node) -> void + def visit_hash_node: (HashNode node) -> void + + # : (HashPatternNode node) -> void + def visit_hash_pattern_node: (HashPatternNode node) -> void + + # : (IfNode node) -> void + def visit_if_node: (IfNode node) -> void + + # : (ImaginaryNode node) -> void + def visit_imaginary_node: (ImaginaryNode node) -> void + + # : (ImplicitNode node) -> void + def visit_implicit_node: (ImplicitNode node) -> void + + # : (ImplicitRestNode node) -> void + def visit_implicit_rest_node: (ImplicitRestNode node) -> void + + # : (InNode node) -> void + def visit_in_node: (InNode node) -> void + + # : (IndexAndWriteNode node) -> void + def visit_index_and_write_node: (IndexAndWriteNode node) -> void + + # : (IndexOperatorWriteNode node) -> void + def visit_index_operator_write_node: (IndexOperatorWriteNode node) -> void + + # : (IndexOrWriteNode node) -> void + def visit_index_or_write_node: (IndexOrWriteNode node) -> void + + # : (IndexTargetNode node) -> void + def visit_index_target_node: (IndexTargetNode node) -> void + + # : (InstanceVariableAndWriteNode node) -> void + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode node) -> void + + # : (InstanceVariableOperatorWriteNode node) -> void + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode node) -> void + + # : (InstanceVariableOrWriteNode node) -> void + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode node) -> void + + # : (InstanceVariableReadNode node) -> void + def visit_instance_variable_read_node: (InstanceVariableReadNode node) -> void + + # : (InstanceVariableTargetNode node) -> void + def visit_instance_variable_target_node: (InstanceVariableTargetNode node) -> void + + # : (InstanceVariableWriteNode node) -> void + def visit_instance_variable_write_node: (InstanceVariableWriteNode node) -> void + + # : (IntegerNode node) -> void + def visit_integer_node: (IntegerNode node) -> void + + # : (InterpolatedMatchLastLineNode node) -> void + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode node) -> void + + # : (InterpolatedRegularExpressionNode node) -> void + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode node) -> void + + # : (InterpolatedStringNode node) -> void + def visit_interpolated_string_node: (InterpolatedStringNode node) -> void + + # : (InterpolatedSymbolNode node) -> void + def visit_interpolated_symbol_node: (InterpolatedSymbolNode node) -> void + + # : (InterpolatedXStringNode node) -> void + def visit_interpolated_x_string_node: (InterpolatedXStringNode node) -> void + + # : (ItLocalVariableReadNode node) -> void + def visit_it_local_variable_read_node: (ItLocalVariableReadNode node) -> void + + # : (ItParametersNode node) -> void + def visit_it_parameters_node: (ItParametersNode node) -> void + + # : (KeywordHashNode node) -> void + def visit_keyword_hash_node: (KeywordHashNode node) -> void + + # : (KeywordRestParameterNode node) -> void + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode node) -> void + + # : (LambdaNode node) -> void + def visit_lambda_node: (LambdaNode node) -> void + + # : (LocalVariableAndWriteNode node) -> void + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode node) -> void + + # : (LocalVariableOperatorWriteNode node) -> void + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode node) -> void + + # : (LocalVariableOrWriteNode node) -> void + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode node) -> void + + # : (LocalVariableReadNode node) -> void + def visit_local_variable_read_node: (LocalVariableReadNode node) -> void + + # : (LocalVariableTargetNode node) -> void + def visit_local_variable_target_node: (LocalVariableTargetNode node) -> void + + # : (LocalVariableWriteNode node) -> void + def visit_local_variable_write_node: (LocalVariableWriteNode node) -> void + + # : (MatchLastLineNode node) -> void + def visit_match_last_line_node: (MatchLastLineNode node) -> void + + # : (MatchPredicateNode node) -> void + def visit_match_predicate_node: (MatchPredicateNode node) -> void + + # : (MatchRequiredNode node) -> void + def visit_match_required_node: (MatchRequiredNode node) -> void + + # : (MatchWriteNode node) -> void + def visit_match_write_node: (MatchWriteNode node) -> void + + # : (MissingNode node) -> void + def visit_missing_node: (MissingNode node) -> void + + # : (ModuleNode node) -> void + def visit_module_node: (ModuleNode node) -> void + + # : (MultiTargetNode node) -> void + def visit_multi_target_node: (MultiTargetNode node) -> void + + # : (MultiWriteNode node) -> void + def visit_multi_write_node: (MultiWriteNode node) -> void + + # : (NextNode node) -> void + def visit_next_node: (NextNode node) -> void + + # : (NilNode node) -> void + def visit_nil_node: (NilNode node) -> void + + # : (NoBlockParameterNode node) -> void + def visit_no_block_parameter_node: (NoBlockParameterNode node) -> void + + # : (NoKeywordsParameterNode node) -> void + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode node) -> void + + # : (NumberedParametersNode node) -> void + def visit_numbered_parameters_node: (NumberedParametersNode node) -> void + + # : (NumberedReferenceReadNode node) -> void + def visit_numbered_reference_read_node: (NumberedReferenceReadNode node) -> void + + # : (OptionalKeywordParameterNode node) -> void + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode node) -> void + + # : (OptionalParameterNode node) -> void + def visit_optional_parameter_node: (OptionalParameterNode node) -> void + + # : (OrNode node) -> void + def visit_or_node: (OrNode node) -> void + + # : (ParametersNode node) -> void + def visit_parameters_node: (ParametersNode node) -> void + + # : (ParenthesesNode node) -> void + def visit_parentheses_node: (ParenthesesNode node) -> void + + # : (PinnedExpressionNode node) -> void + def visit_pinned_expression_node: (PinnedExpressionNode node) -> void + + # : (PinnedVariableNode node) -> void + def visit_pinned_variable_node: (PinnedVariableNode node) -> void + + # : (PostExecutionNode node) -> void + def visit_post_execution_node: (PostExecutionNode node) -> void + + # : (PreExecutionNode node) -> void + def visit_pre_execution_node: (PreExecutionNode node) -> void + + # : (ProgramNode node) -> void + def visit_program_node: (ProgramNode node) -> void + + # : (RangeNode node) -> void + def visit_range_node: (RangeNode node) -> void + + # : (RationalNode node) -> void + def visit_rational_node: (RationalNode node) -> void + + # : (RedoNode node) -> void + def visit_redo_node: (RedoNode node) -> void + + # : (RegularExpressionNode node) -> void + def visit_regular_expression_node: (RegularExpressionNode node) -> void + + # : (RequiredKeywordParameterNode node) -> void + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode node) -> void + + # : (RequiredParameterNode node) -> void + def visit_required_parameter_node: (RequiredParameterNode node) -> void + + # : (RescueModifierNode node) -> void + def visit_rescue_modifier_node: (RescueModifierNode node) -> void + + # : (RescueNode node) -> void + def visit_rescue_node: (RescueNode node) -> void + + # : (RestParameterNode node) -> void + def visit_rest_parameter_node: (RestParameterNode node) -> void + + # : (RetryNode node) -> void + def visit_retry_node: (RetryNode node) -> void + + # : (ReturnNode node) -> void + def visit_return_node: (ReturnNode node) -> void + + # : (SelfNode node) -> void + def visit_self_node: (SelfNode node) -> void + + # : (ShareableConstantNode node) -> void + def visit_shareable_constant_node: (ShareableConstantNode node) -> void + + # : (SingletonClassNode node) -> void + def visit_singleton_class_node: (SingletonClassNode node) -> void + + # : (SourceEncodingNode node) -> void + def visit_source_encoding_node: (SourceEncodingNode node) -> void + + # : (SourceFileNode node) -> void + def visit_source_file_node: (SourceFileNode node) -> void + + # : (SourceLineNode node) -> void + def visit_source_line_node: (SourceLineNode node) -> void + + # : (SplatNode node) -> void + def visit_splat_node: (SplatNode node) -> void + + # : (StatementsNode node) -> void + def visit_statements_node: (StatementsNode node) -> void + + # : (StringNode node) -> void + def visit_string_node: (StringNode node) -> void + + # : (SuperNode node) -> void + def visit_super_node: (SuperNode node) -> void + + # : (SymbolNode node) -> void + def visit_symbol_node: (SymbolNode node) -> void + + # : (TrueNode node) -> void + def visit_true_node: (TrueNode node) -> void + + # : (UndefNode node) -> void + def visit_undef_node: (UndefNode node) -> void + + # : (UnlessNode node) -> void + def visit_unless_node: (UnlessNode node) -> void + + # : (UntilNode node) -> void + def visit_until_node: (UntilNode node) -> void + + # : (WhenNode node) -> void + def visit_when_node: (WhenNode node) -> void + + # : (WhileNode node) -> void + def visit_while_node: (WhileNode node) -> void + + # : (XStringNode node) -> void + def visit_x_string_node: (XStringNode node) -> void + + # : (YieldNode node) -> void + def visit_yield_node: (YieldNode node) -> void + + class DispatchOnce < Visitor + attr_reader listeners: Hash[Symbol, Array[untyped]] + + # : (Hash[Symbol, Array[untyped]] listeners) -> void + def initialize: (Hash[Symbol, Array[untyped]] listeners) -> void + + # Dispatch enter and leave events for AliasGlobalVariableNode nodes. + # -- + # : (AliasGlobalVariableNode node) -> void + def visit_alias_global_variable_node: (AliasGlobalVariableNode node) -> void + + # Dispatch enter and leave events for AliasMethodNode nodes. + # -- + # : (AliasMethodNode node) -> void + def visit_alias_method_node: (AliasMethodNode node) -> void + + # Dispatch enter and leave events for AlternationPatternNode nodes. + # -- + # : (AlternationPatternNode node) -> void + def visit_alternation_pattern_node: (AlternationPatternNode node) -> void + + # Dispatch enter and leave events for AndNode nodes. + # -- + # : (AndNode node) -> void + def visit_and_node: (AndNode node) -> void + + # Dispatch enter and leave events for ArgumentsNode nodes. + # -- + # : (ArgumentsNode node) -> void + def visit_arguments_node: (ArgumentsNode node) -> void + + # Dispatch enter and leave events for ArrayNode nodes. + # -- + # : (ArrayNode node) -> void + def visit_array_node: (ArrayNode node) -> void + + # Dispatch enter and leave events for ArrayPatternNode nodes. + # -- + # : (ArrayPatternNode node) -> void + def visit_array_pattern_node: (ArrayPatternNode node) -> void + + # Dispatch enter and leave events for AssocNode nodes. + # -- + # : (AssocNode node) -> void + def visit_assoc_node: (AssocNode node) -> void + + # Dispatch enter and leave events for AssocSplatNode nodes. + # -- + # : (AssocSplatNode node) -> void + def visit_assoc_splat_node: (AssocSplatNode node) -> void + + # Dispatch enter and leave events for BackReferenceReadNode nodes. + # -- + # : (BackReferenceReadNode node) -> void + def visit_back_reference_read_node: (BackReferenceReadNode node) -> void + + # Dispatch enter and leave events for BeginNode nodes. + # -- + # : (BeginNode node) -> void + def visit_begin_node: (BeginNode node) -> void + + # Dispatch enter and leave events for BlockArgumentNode nodes. + # -- + # : (BlockArgumentNode node) -> void + def visit_block_argument_node: (BlockArgumentNode node) -> void + + # Dispatch enter and leave events for BlockLocalVariableNode nodes. + # -- + # : (BlockLocalVariableNode node) -> void + def visit_block_local_variable_node: (BlockLocalVariableNode node) -> void + + # Dispatch enter and leave events for BlockNode nodes. + # -- + # : (BlockNode node) -> void + def visit_block_node: (BlockNode node) -> void + + # Dispatch enter and leave events for BlockParameterNode nodes. + # -- + # : (BlockParameterNode node) -> void + def visit_block_parameter_node: (BlockParameterNode node) -> void + + # Dispatch enter and leave events for BlockParametersNode nodes. + # -- + # : (BlockParametersNode node) -> void + def visit_block_parameters_node: (BlockParametersNode node) -> void + + # Dispatch enter and leave events for BreakNode nodes. + # -- + # : (BreakNode node) -> void + def visit_break_node: (BreakNode node) -> void + + # Dispatch enter and leave events for CallAndWriteNode nodes. + # -- + # : (CallAndWriteNode node) -> void + def visit_call_and_write_node: (CallAndWriteNode node) -> void + + # Dispatch enter and leave events for CallNode nodes. + # -- + # : (CallNode node) -> void + def visit_call_node: (CallNode node) -> void + + # Dispatch enter and leave events for CallOperatorWriteNode nodes. + # -- + # : (CallOperatorWriteNode node) -> void + def visit_call_operator_write_node: (CallOperatorWriteNode node) -> void + + # Dispatch enter and leave events for CallOrWriteNode nodes. + # -- + # : (CallOrWriteNode node) -> void + def visit_call_or_write_node: (CallOrWriteNode node) -> void + + # Dispatch enter and leave events for CallTargetNode nodes. + # -- + # : (CallTargetNode node) -> void + def visit_call_target_node: (CallTargetNode node) -> void + + # Dispatch enter and leave events for CapturePatternNode nodes. + # -- + # : (CapturePatternNode node) -> void + def visit_capture_pattern_node: (CapturePatternNode node) -> void + + # Dispatch enter and leave events for CaseMatchNode nodes. + # -- + # : (CaseMatchNode node) -> void + def visit_case_match_node: (CaseMatchNode node) -> void + + # Dispatch enter and leave events for CaseNode nodes. + # -- + # : (CaseNode node) -> void + def visit_case_node: (CaseNode node) -> void + + # Dispatch enter and leave events for ClassNode nodes. + # -- + # : (ClassNode node) -> void + def visit_class_node: (ClassNode node) -> void + + # Dispatch enter and leave events for ClassVariableAndWriteNode nodes. + # -- + # : (ClassVariableAndWriteNode node) -> void + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode node) -> void + + # Dispatch enter and leave events for ClassVariableOperatorWriteNode nodes. + # -- + # : (ClassVariableOperatorWriteNode node) -> void + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode node) -> void + + # Dispatch enter and leave events for ClassVariableOrWriteNode nodes. + # -- + # : (ClassVariableOrWriteNode node) -> void + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode node) -> void + + # Dispatch enter and leave events for ClassVariableReadNode nodes. + # -- + # : (ClassVariableReadNode node) -> void + def visit_class_variable_read_node: (ClassVariableReadNode node) -> void + + # Dispatch enter and leave events for ClassVariableTargetNode nodes. + # -- + # : (ClassVariableTargetNode node) -> void + def visit_class_variable_target_node: (ClassVariableTargetNode node) -> void + + # Dispatch enter and leave events for ClassVariableWriteNode nodes. + # -- + # : (ClassVariableWriteNode node) -> void + def visit_class_variable_write_node: (ClassVariableWriteNode node) -> void + + # Dispatch enter and leave events for ConstantAndWriteNode nodes. + # -- + # : (ConstantAndWriteNode node) -> void + def visit_constant_and_write_node: (ConstantAndWriteNode node) -> void + + # Dispatch enter and leave events for ConstantOperatorWriteNode nodes. + # -- + # : (ConstantOperatorWriteNode node) -> void + def visit_constant_operator_write_node: (ConstantOperatorWriteNode node) -> void + + # Dispatch enter and leave events for ConstantOrWriteNode nodes. + # -- + # : (ConstantOrWriteNode node) -> void + def visit_constant_or_write_node: (ConstantOrWriteNode node) -> void + + # Dispatch enter and leave events for ConstantPathAndWriteNode nodes. + # -- + # : (ConstantPathAndWriteNode node) -> void + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode node) -> void + + # Dispatch enter and leave events for ConstantPathNode nodes. + # -- + # : (ConstantPathNode node) -> void + def visit_constant_path_node: (ConstantPathNode node) -> void + + # Dispatch enter and leave events for ConstantPathOperatorWriteNode nodes. + # -- + # : (ConstantPathOperatorWriteNode node) -> void + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode node) -> void + + # Dispatch enter and leave events for ConstantPathOrWriteNode nodes. + # -- + # : (ConstantPathOrWriteNode node) -> void + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode node) -> void + + # Dispatch enter and leave events for ConstantPathTargetNode nodes. + # -- + # : (ConstantPathTargetNode node) -> void + def visit_constant_path_target_node: (ConstantPathTargetNode node) -> void + + # Dispatch enter and leave events for ConstantPathWriteNode nodes. + # -- + # : (ConstantPathWriteNode node) -> void + def visit_constant_path_write_node: (ConstantPathWriteNode node) -> void + + # Dispatch enter and leave events for ConstantReadNode nodes. + # -- + # : (ConstantReadNode node) -> void + def visit_constant_read_node: (ConstantReadNode node) -> void + + # Dispatch enter and leave events for ConstantTargetNode nodes. + # -- + # : (ConstantTargetNode node) -> void + def visit_constant_target_node: (ConstantTargetNode node) -> void + + # Dispatch enter and leave events for ConstantWriteNode nodes. + # -- + # : (ConstantWriteNode node) -> void + def visit_constant_write_node: (ConstantWriteNode node) -> void + + # Dispatch enter and leave events for DefNode nodes. + # -- + # : (DefNode node) -> void + def visit_def_node: (DefNode node) -> void + + # Dispatch enter and leave events for DefinedNode nodes. + # -- + # : (DefinedNode node) -> void + def visit_defined_node: (DefinedNode node) -> void + + # Dispatch enter and leave events for ElseNode nodes. + # -- + # : (ElseNode node) -> void + def visit_else_node: (ElseNode node) -> void + + # Dispatch enter and leave events for EmbeddedStatementsNode nodes. + # -- + # : (EmbeddedStatementsNode node) -> void + def visit_embedded_statements_node: (EmbeddedStatementsNode node) -> void + + # Dispatch enter and leave events for EmbeddedVariableNode nodes. + # -- + # : (EmbeddedVariableNode node) -> void + def visit_embedded_variable_node: (EmbeddedVariableNode node) -> void + + # Dispatch enter and leave events for EnsureNode nodes. + # -- + # : (EnsureNode node) -> void + def visit_ensure_node: (EnsureNode node) -> void + + # Dispatch enter and leave events for FalseNode nodes. + # -- + # : (FalseNode node) -> void + def visit_false_node: (FalseNode node) -> void + + # Dispatch enter and leave events for FindPatternNode nodes. + # -- + # : (FindPatternNode node) -> void + def visit_find_pattern_node: (FindPatternNode node) -> void + + # Dispatch enter and leave events for FlipFlopNode nodes. + # -- + # : (FlipFlopNode node) -> void + def visit_flip_flop_node: (FlipFlopNode node) -> void + + # Dispatch enter and leave events for FloatNode nodes. + # -- + # : (FloatNode node) -> void + def visit_float_node: (FloatNode node) -> void + + # Dispatch enter and leave events for ForNode nodes. + # -- + # : (ForNode node) -> void + def visit_for_node: (ForNode node) -> void + + # Dispatch enter and leave events for ForwardingArgumentsNode nodes. + # -- + # : (ForwardingArgumentsNode node) -> void + def visit_forwarding_arguments_node: (ForwardingArgumentsNode node) -> void + + # Dispatch enter and leave events for ForwardingParameterNode nodes. + # -- + # : (ForwardingParameterNode node) -> void + def visit_forwarding_parameter_node: (ForwardingParameterNode node) -> void + + # Dispatch enter and leave events for ForwardingSuperNode nodes. + # -- + # : (ForwardingSuperNode node) -> void + def visit_forwarding_super_node: (ForwardingSuperNode node) -> void + + # Dispatch enter and leave events for GlobalVariableAndWriteNode nodes. + # -- + # : (GlobalVariableAndWriteNode node) -> void + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode node) -> void + + # Dispatch enter and leave events for GlobalVariableOperatorWriteNode nodes. + # -- + # : (GlobalVariableOperatorWriteNode node) -> void + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode node) -> void + + # Dispatch enter and leave events for GlobalVariableOrWriteNode nodes. + # -- + # : (GlobalVariableOrWriteNode node) -> void + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode node) -> void + + # Dispatch enter and leave events for GlobalVariableReadNode nodes. + # -- + # : (GlobalVariableReadNode node) -> void + def visit_global_variable_read_node: (GlobalVariableReadNode node) -> void + + # Dispatch enter and leave events for GlobalVariableTargetNode nodes. + # -- + # : (GlobalVariableTargetNode node) -> void + def visit_global_variable_target_node: (GlobalVariableTargetNode node) -> void + + # Dispatch enter and leave events for GlobalVariableWriteNode nodes. + # -- + # : (GlobalVariableWriteNode node) -> void + def visit_global_variable_write_node: (GlobalVariableWriteNode node) -> void + + # Dispatch enter and leave events for HashNode nodes. + # -- + # : (HashNode node) -> void + def visit_hash_node: (HashNode node) -> void + + # Dispatch enter and leave events for HashPatternNode nodes. + # -- + # : (HashPatternNode node) -> void + def visit_hash_pattern_node: (HashPatternNode node) -> void + + # Dispatch enter and leave events for IfNode nodes. + # -- + # : (IfNode node) -> void + def visit_if_node: (IfNode node) -> void + + # Dispatch enter and leave events for ImaginaryNode nodes. + # -- + # : (ImaginaryNode node) -> void + def visit_imaginary_node: (ImaginaryNode node) -> void + + # Dispatch enter and leave events for ImplicitNode nodes. + # -- + # : (ImplicitNode node) -> void + def visit_implicit_node: (ImplicitNode node) -> void + + # Dispatch enter and leave events for ImplicitRestNode nodes. + # -- + # : (ImplicitRestNode node) -> void + def visit_implicit_rest_node: (ImplicitRestNode node) -> void + + # Dispatch enter and leave events for InNode nodes. + # -- + # : (InNode node) -> void + def visit_in_node: (InNode node) -> void + + # Dispatch enter and leave events for IndexAndWriteNode nodes. + # -- + # : (IndexAndWriteNode node) -> void + def visit_index_and_write_node: (IndexAndWriteNode node) -> void + + # Dispatch enter and leave events for IndexOperatorWriteNode nodes. + # -- + # : (IndexOperatorWriteNode node) -> void + def visit_index_operator_write_node: (IndexOperatorWriteNode node) -> void + + # Dispatch enter and leave events for IndexOrWriteNode nodes. + # -- + # : (IndexOrWriteNode node) -> void + def visit_index_or_write_node: (IndexOrWriteNode node) -> void + + # Dispatch enter and leave events for IndexTargetNode nodes. + # -- + # : (IndexTargetNode node) -> void + def visit_index_target_node: (IndexTargetNode node) -> void + + # Dispatch enter and leave events for InstanceVariableAndWriteNode nodes. + # -- + # : (InstanceVariableAndWriteNode node) -> void + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode node) -> void + + # Dispatch enter and leave events for InstanceVariableOperatorWriteNode nodes. + # -- + # : (InstanceVariableOperatorWriteNode node) -> void + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode node) -> void + + # Dispatch enter and leave events for InstanceVariableOrWriteNode nodes. + # -- + # : (InstanceVariableOrWriteNode node) -> void + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode node) -> void + + # Dispatch enter and leave events for InstanceVariableReadNode nodes. + # -- + # : (InstanceVariableReadNode node) -> void + def visit_instance_variable_read_node: (InstanceVariableReadNode node) -> void + + # Dispatch enter and leave events for InstanceVariableTargetNode nodes. + # -- + # : (InstanceVariableTargetNode node) -> void + def visit_instance_variable_target_node: (InstanceVariableTargetNode node) -> void + + # Dispatch enter and leave events for InstanceVariableWriteNode nodes. + # -- + # : (InstanceVariableWriteNode node) -> void + def visit_instance_variable_write_node: (InstanceVariableWriteNode node) -> void + + # Dispatch enter and leave events for IntegerNode nodes. + # -- + # : (IntegerNode node) -> void + def visit_integer_node: (IntegerNode node) -> void + + # Dispatch enter and leave events for InterpolatedMatchLastLineNode nodes. + # -- + # : (InterpolatedMatchLastLineNode node) -> void + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode node) -> void + + # Dispatch enter and leave events for InterpolatedRegularExpressionNode nodes. + # -- + # : (InterpolatedRegularExpressionNode node) -> void + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode node) -> void + + # Dispatch enter and leave events for InterpolatedStringNode nodes. + # -- + # : (InterpolatedStringNode node) -> void + def visit_interpolated_string_node: (InterpolatedStringNode node) -> void + + # Dispatch enter and leave events for InterpolatedSymbolNode nodes. + # -- + # : (InterpolatedSymbolNode node) -> void + def visit_interpolated_symbol_node: (InterpolatedSymbolNode node) -> void + + # Dispatch enter and leave events for InterpolatedXStringNode nodes. + # -- + # : (InterpolatedXStringNode node) -> void + def visit_interpolated_x_string_node: (InterpolatedXStringNode node) -> void + + # Dispatch enter and leave events for ItLocalVariableReadNode nodes. + # -- + # : (ItLocalVariableReadNode node) -> void + def visit_it_local_variable_read_node: (ItLocalVariableReadNode node) -> void + + # Dispatch enter and leave events for ItParametersNode nodes. + # -- + # : (ItParametersNode node) -> void + def visit_it_parameters_node: (ItParametersNode node) -> void + + # Dispatch enter and leave events for KeywordHashNode nodes. + # -- + # : (KeywordHashNode node) -> void + def visit_keyword_hash_node: (KeywordHashNode node) -> void + + # Dispatch enter and leave events for KeywordRestParameterNode nodes. + # -- + # : (KeywordRestParameterNode node) -> void + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode node) -> void + + # Dispatch enter and leave events for LambdaNode nodes. + # -- + # : (LambdaNode node) -> void + def visit_lambda_node: (LambdaNode node) -> void + + # Dispatch enter and leave events for LocalVariableAndWriteNode nodes. + # -- + # : (LocalVariableAndWriteNode node) -> void + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode node) -> void + + # Dispatch enter and leave events for LocalVariableOperatorWriteNode nodes. + # -- + # : (LocalVariableOperatorWriteNode node) -> void + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode node) -> void + + # Dispatch enter and leave events for LocalVariableOrWriteNode nodes. + # -- + # : (LocalVariableOrWriteNode node) -> void + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode node) -> void + + # Dispatch enter and leave events for LocalVariableReadNode nodes. + # -- + # : (LocalVariableReadNode node) -> void + def visit_local_variable_read_node: (LocalVariableReadNode node) -> void + + # Dispatch enter and leave events for LocalVariableTargetNode nodes. + # -- + # : (LocalVariableTargetNode node) -> void + def visit_local_variable_target_node: (LocalVariableTargetNode node) -> void + + # Dispatch enter and leave events for LocalVariableWriteNode nodes. + # -- + # : (LocalVariableWriteNode node) -> void + def visit_local_variable_write_node: (LocalVariableWriteNode node) -> void + + # Dispatch enter and leave events for MatchLastLineNode nodes. + # -- + # : (MatchLastLineNode node) -> void + def visit_match_last_line_node: (MatchLastLineNode node) -> void + + # Dispatch enter and leave events for MatchPredicateNode nodes. + # -- + # : (MatchPredicateNode node) -> void + def visit_match_predicate_node: (MatchPredicateNode node) -> void + + # Dispatch enter and leave events for MatchRequiredNode nodes. + # -- + # : (MatchRequiredNode node) -> void + def visit_match_required_node: (MatchRequiredNode node) -> void + + # Dispatch enter and leave events for MatchWriteNode nodes. + # -- + # : (MatchWriteNode node) -> void + def visit_match_write_node: (MatchWriteNode node) -> void + + # Dispatch enter and leave events for MissingNode nodes. + # -- + # : (MissingNode node) -> void + def visit_missing_node: (MissingNode node) -> void + + # Dispatch enter and leave events for ModuleNode nodes. + # -- + # : (ModuleNode node) -> void + def visit_module_node: (ModuleNode node) -> void + + # Dispatch enter and leave events for MultiTargetNode nodes. + # -- + # : (MultiTargetNode node) -> void + def visit_multi_target_node: (MultiTargetNode node) -> void + + # Dispatch enter and leave events for MultiWriteNode nodes. + # -- + # : (MultiWriteNode node) -> void + def visit_multi_write_node: (MultiWriteNode node) -> void + + # Dispatch enter and leave events for NextNode nodes. + # -- + # : (NextNode node) -> void + def visit_next_node: (NextNode node) -> void + + # Dispatch enter and leave events for NilNode nodes. + # -- + # : (NilNode node) -> void + def visit_nil_node: (NilNode node) -> void + + # Dispatch enter and leave events for NoBlockParameterNode nodes. + # -- + # : (NoBlockParameterNode node) -> void + def visit_no_block_parameter_node: (NoBlockParameterNode node) -> void + + # Dispatch enter and leave events for NoKeywordsParameterNode nodes. + # -- + # : (NoKeywordsParameterNode node) -> void + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode node) -> void + + # Dispatch enter and leave events for NumberedParametersNode nodes. + # -- + # : (NumberedParametersNode node) -> void + def visit_numbered_parameters_node: (NumberedParametersNode node) -> void + + # Dispatch enter and leave events for NumberedReferenceReadNode nodes. + # -- + # : (NumberedReferenceReadNode node) -> void + def visit_numbered_reference_read_node: (NumberedReferenceReadNode node) -> void + + # Dispatch enter and leave events for OptionalKeywordParameterNode nodes. + # -- + # : (OptionalKeywordParameterNode node) -> void + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode node) -> void + + # Dispatch enter and leave events for OptionalParameterNode nodes. + # -- + # : (OptionalParameterNode node) -> void + def visit_optional_parameter_node: (OptionalParameterNode node) -> void + + # Dispatch enter and leave events for OrNode nodes. + # -- + # : (OrNode node) -> void + def visit_or_node: (OrNode node) -> void + + # Dispatch enter and leave events for ParametersNode nodes. + # -- + # : (ParametersNode node) -> void + def visit_parameters_node: (ParametersNode node) -> void + + # Dispatch enter and leave events for ParenthesesNode nodes. + # -- + # : (ParenthesesNode node) -> void + def visit_parentheses_node: (ParenthesesNode node) -> void + + # Dispatch enter and leave events for PinnedExpressionNode nodes. + # -- + # : (PinnedExpressionNode node) -> void + def visit_pinned_expression_node: (PinnedExpressionNode node) -> void + + # Dispatch enter and leave events for PinnedVariableNode nodes. + # -- + # : (PinnedVariableNode node) -> void + def visit_pinned_variable_node: (PinnedVariableNode node) -> void + + # Dispatch enter and leave events for PostExecutionNode nodes. + # -- + # : (PostExecutionNode node) -> void + def visit_post_execution_node: (PostExecutionNode node) -> void + + # Dispatch enter and leave events for PreExecutionNode nodes. + # -- + # : (PreExecutionNode node) -> void + def visit_pre_execution_node: (PreExecutionNode node) -> void + + # Dispatch enter and leave events for ProgramNode nodes. + # -- + # : (ProgramNode node) -> void + def visit_program_node: (ProgramNode node) -> void + + # Dispatch enter and leave events for RangeNode nodes. + # -- + # : (RangeNode node) -> void + def visit_range_node: (RangeNode node) -> void + + # Dispatch enter and leave events for RationalNode nodes. + # -- + # : (RationalNode node) -> void + def visit_rational_node: (RationalNode node) -> void + + # Dispatch enter and leave events for RedoNode nodes. + # -- + # : (RedoNode node) -> void + def visit_redo_node: (RedoNode node) -> void + + # Dispatch enter and leave events for RegularExpressionNode nodes. + # -- + # : (RegularExpressionNode node) -> void + def visit_regular_expression_node: (RegularExpressionNode node) -> void + + # Dispatch enter and leave events for RequiredKeywordParameterNode nodes. + # -- + # : (RequiredKeywordParameterNode node) -> void + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode node) -> void + + # Dispatch enter and leave events for RequiredParameterNode nodes. + # -- + # : (RequiredParameterNode node) -> void + def visit_required_parameter_node: (RequiredParameterNode node) -> void + + # Dispatch enter and leave events for RescueModifierNode nodes. + # -- + # : (RescueModifierNode node) -> void + def visit_rescue_modifier_node: (RescueModifierNode node) -> void + + # Dispatch enter and leave events for RescueNode nodes. + # -- + # : (RescueNode node) -> void + def visit_rescue_node: (RescueNode node) -> void + + # Dispatch enter and leave events for RestParameterNode nodes. + # -- + # : (RestParameterNode node) -> void + def visit_rest_parameter_node: (RestParameterNode node) -> void + + # Dispatch enter and leave events for RetryNode nodes. + # -- + # : (RetryNode node) -> void + def visit_retry_node: (RetryNode node) -> void + + # Dispatch enter and leave events for ReturnNode nodes. + # -- + # : (ReturnNode node) -> void + def visit_return_node: (ReturnNode node) -> void + + # Dispatch enter and leave events for SelfNode nodes. + # -- + # : (SelfNode node) -> void + def visit_self_node: (SelfNode node) -> void + + # Dispatch enter and leave events for ShareableConstantNode nodes. + # -- + # : (ShareableConstantNode node) -> void + def visit_shareable_constant_node: (ShareableConstantNode node) -> void + + # Dispatch enter and leave events for SingletonClassNode nodes. + # -- + # : (SingletonClassNode node) -> void + def visit_singleton_class_node: (SingletonClassNode node) -> void + + # Dispatch enter and leave events for SourceEncodingNode nodes. + # -- + # : (SourceEncodingNode node) -> void + def visit_source_encoding_node: (SourceEncodingNode node) -> void + + # Dispatch enter and leave events for SourceFileNode nodes. + # -- + # : (SourceFileNode node) -> void + def visit_source_file_node: (SourceFileNode node) -> void + + # Dispatch enter and leave events for SourceLineNode nodes. + # -- + # : (SourceLineNode node) -> void + def visit_source_line_node: (SourceLineNode node) -> void + + # Dispatch enter and leave events for SplatNode nodes. + # -- + # : (SplatNode node) -> void + def visit_splat_node: (SplatNode node) -> void + + # Dispatch enter and leave events for StatementsNode nodes. + # -- + # : (StatementsNode node) -> void + def visit_statements_node: (StatementsNode node) -> void + + # Dispatch enter and leave events for StringNode nodes. + # -- + # : (StringNode node) -> void + def visit_string_node: (StringNode node) -> void + + # Dispatch enter and leave events for SuperNode nodes. + # -- + # : (SuperNode node) -> void + def visit_super_node: (SuperNode node) -> void + + # Dispatch enter and leave events for SymbolNode nodes. + # -- + # : (SymbolNode node) -> void + def visit_symbol_node: (SymbolNode node) -> void + + # Dispatch enter and leave events for TrueNode nodes. + # -- + # : (TrueNode node) -> void + def visit_true_node: (TrueNode node) -> void + + # Dispatch enter and leave events for UndefNode nodes. + # -- + # : (UndefNode node) -> void + def visit_undef_node: (UndefNode node) -> void + + # Dispatch enter and leave events for UnlessNode nodes. + # -- + # : (UnlessNode node) -> void + def visit_unless_node: (UnlessNode node) -> void + + # Dispatch enter and leave events for UntilNode nodes. + # -- + # : (UntilNode node) -> void + def visit_until_node: (UntilNode node) -> void + + # Dispatch enter and leave events for WhenNode nodes. + # -- + # : (WhenNode node) -> void + def visit_when_node: (WhenNode node) -> void + + # Dispatch enter and leave events for WhileNode nodes. + # -- + # : (WhileNode node) -> void + def visit_while_node: (WhileNode node) -> void + + # Dispatch enter and leave events for XStringNode nodes. + # -- + # : (XStringNode node) -> void + def visit_x_string_node: (XStringNode node) -> void + + # Dispatch enter and leave events for YieldNode nodes. + # -- + # : (YieldNode node) -> void + def visit_yield_node: (YieldNode node) -> void + end + end +end diff --git a/sig/generated/prism/dot_visitor.rbs b/sig/generated/prism/dot_visitor.rbs new file mode 100644 index 0000000000..2cbc0ee31b --- /dev/null +++ b/sig/generated/prism/dot_visitor.rbs @@ -0,0 +1,635 @@ +# Generated from lib/prism/dot_visitor.rb with RBS::Inline + +module Prism + # This visitor provides the ability to call Node#to_dot, which converts a + # subtree into a graphviz dot graph. + class DotVisitor < Visitor + class Field + # :nodoc: + attr_reader name: String + + attr_reader value: String? + + attr_reader port: bool + + # : (String name, String? value, bool port) -> void + def initialize: (String name, String? value, bool port) -> void + + # : () -> String + def to_dot: () -> String + end + + class Table + # :nodoc: + attr_reader name: String + + attr_reader fields: Array[Field] + + # : (String name) -> void + def initialize: (String name) -> void + + # : (String name, ?String? value, ?port: bool) -> void + def field: (String name, ?String? value, ?port: bool) -> void + + # : () -> String + def to_dot: () -> String + end + + class Digraph + # :nodoc: + attr_reader nodes: Array[String] + + # :nodoc: + attr_reader waypoints: Array[String] + + # :nodoc: + attr_reader edges: Array[String] + + # : () -> void + def initialize: () -> void + + # : (String value) -> void + def node: (String value) -> void + + # : (String value) -> void + def waypoint: (String value) -> void + + # : (String value) -> void + def edge: (String value) -> void + + # : () -> String + def to_dot: () -> String + end + + # The digraph that is being built. + attr_reader digraph: Digraph + + # Initialize a new dot visitor. + # -- + # : () -> void + def initialize: () -> void + + # Convert this visitor into a graphviz dot graph string. + # -- + # : () -> String + def to_dot: () -> String + + # : (AliasGlobalVariableNode) -> void + def visit_alias_global_variable_node: (AliasGlobalVariableNode) -> void + + # : (AliasMethodNode) -> void + def visit_alias_method_node: (AliasMethodNode) -> void + + # : (AlternationPatternNode) -> void + def visit_alternation_pattern_node: (AlternationPatternNode) -> void + + # : (AndNode) -> void + def visit_and_node: (AndNode) -> void + + # : (ArgumentsNode) -> void + def visit_arguments_node: (ArgumentsNode) -> void + + # : (ArrayNode) -> void + def visit_array_node: (ArrayNode) -> void + + # : (ArrayPatternNode) -> void + def visit_array_pattern_node: (ArrayPatternNode) -> void + + # : (AssocNode) -> void + def visit_assoc_node: (AssocNode) -> void + + # : (AssocSplatNode) -> void + def visit_assoc_splat_node: (AssocSplatNode) -> void + + # : (BackReferenceReadNode) -> void + def visit_back_reference_read_node: (BackReferenceReadNode) -> void + + # : (BeginNode) -> void + def visit_begin_node: (BeginNode) -> void + + # : (BlockArgumentNode) -> void + def visit_block_argument_node: (BlockArgumentNode) -> void + + # : (BlockLocalVariableNode) -> void + def visit_block_local_variable_node: (BlockLocalVariableNode) -> void + + # : (BlockNode) -> void + def visit_block_node: (BlockNode) -> void + + # : (BlockParameterNode) -> void + def visit_block_parameter_node: (BlockParameterNode) -> void + + # : (BlockParametersNode) -> void + def visit_block_parameters_node: (BlockParametersNode) -> void + + # : (BreakNode) -> void + def visit_break_node: (BreakNode) -> void + + # : (CallAndWriteNode) -> void + def visit_call_and_write_node: (CallAndWriteNode) -> void + + # : (CallNode) -> void + def visit_call_node: (CallNode) -> void + + # : (CallOperatorWriteNode) -> void + def visit_call_operator_write_node: (CallOperatorWriteNode) -> void + + # : (CallOrWriteNode) -> void + def visit_call_or_write_node: (CallOrWriteNode) -> void + + # : (CallTargetNode) -> void + def visit_call_target_node: (CallTargetNode) -> void + + # : (CapturePatternNode) -> void + def visit_capture_pattern_node: (CapturePatternNode) -> void + + # : (CaseMatchNode) -> void + def visit_case_match_node: (CaseMatchNode) -> void + + # : (CaseNode) -> void + def visit_case_node: (CaseNode) -> void + + # : (ClassNode) -> void + def visit_class_node: (ClassNode) -> void + + # : (ClassVariableAndWriteNode) -> void + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode) -> void + + # : (ClassVariableOperatorWriteNode) -> void + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode) -> void + + # : (ClassVariableOrWriteNode) -> void + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode) -> void + + # : (ClassVariableReadNode) -> void + def visit_class_variable_read_node: (ClassVariableReadNode) -> void + + # : (ClassVariableTargetNode) -> void + def visit_class_variable_target_node: (ClassVariableTargetNode) -> void + + # : (ClassVariableWriteNode) -> void + def visit_class_variable_write_node: (ClassVariableWriteNode) -> void + + # : (ConstantAndWriteNode) -> void + def visit_constant_and_write_node: (ConstantAndWriteNode) -> void + + # : (ConstantOperatorWriteNode) -> void + def visit_constant_operator_write_node: (ConstantOperatorWriteNode) -> void + + # : (ConstantOrWriteNode) -> void + def visit_constant_or_write_node: (ConstantOrWriteNode) -> void + + # : (ConstantPathAndWriteNode) -> void + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode) -> void + + # : (ConstantPathNode) -> void + def visit_constant_path_node: (ConstantPathNode) -> void + + # : (ConstantPathOperatorWriteNode) -> void + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode) -> void + + # : (ConstantPathOrWriteNode) -> void + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode) -> void + + # : (ConstantPathTargetNode) -> void + def visit_constant_path_target_node: (ConstantPathTargetNode) -> void + + # : (ConstantPathWriteNode) -> void + def visit_constant_path_write_node: (ConstantPathWriteNode) -> void + + # : (ConstantReadNode) -> void + def visit_constant_read_node: (ConstantReadNode) -> void + + # : (ConstantTargetNode) -> void + def visit_constant_target_node: (ConstantTargetNode) -> void + + # : (ConstantWriteNode) -> void + def visit_constant_write_node: (ConstantWriteNode) -> void + + # : (DefNode) -> void + def visit_def_node: (DefNode) -> void + + # : (DefinedNode) -> void + def visit_defined_node: (DefinedNode) -> void + + # : (ElseNode) -> void + def visit_else_node: (ElseNode) -> void + + # : (EmbeddedStatementsNode) -> void + def visit_embedded_statements_node: (EmbeddedStatementsNode) -> void + + # : (EmbeddedVariableNode) -> void + def visit_embedded_variable_node: (EmbeddedVariableNode) -> void + + # : (EnsureNode) -> void + def visit_ensure_node: (EnsureNode) -> void + + # : (FalseNode) -> void + def visit_false_node: (FalseNode) -> void + + # : (FindPatternNode) -> void + def visit_find_pattern_node: (FindPatternNode) -> void + + # : (FlipFlopNode) -> void + def visit_flip_flop_node: (FlipFlopNode) -> void + + # : (FloatNode) -> void + def visit_float_node: (FloatNode) -> void + + # : (ForNode) -> void + def visit_for_node: (ForNode) -> void + + # : (ForwardingArgumentsNode) -> void + def visit_forwarding_arguments_node: (ForwardingArgumentsNode) -> void + + # : (ForwardingParameterNode) -> void + def visit_forwarding_parameter_node: (ForwardingParameterNode) -> void + + # : (ForwardingSuperNode) -> void + def visit_forwarding_super_node: (ForwardingSuperNode) -> void + + # : (GlobalVariableAndWriteNode) -> void + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode) -> void + + # : (GlobalVariableOperatorWriteNode) -> void + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode) -> void + + # : (GlobalVariableOrWriteNode) -> void + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode) -> void + + # : (GlobalVariableReadNode) -> void + def visit_global_variable_read_node: (GlobalVariableReadNode) -> void + + # : (GlobalVariableTargetNode) -> void + def visit_global_variable_target_node: (GlobalVariableTargetNode) -> void + + # : (GlobalVariableWriteNode) -> void + def visit_global_variable_write_node: (GlobalVariableWriteNode) -> void + + # : (HashNode) -> void + def visit_hash_node: (HashNode) -> void + + # : (HashPatternNode) -> void + def visit_hash_pattern_node: (HashPatternNode) -> void + + # : (IfNode) -> void + def visit_if_node: (IfNode) -> void + + # : (ImaginaryNode) -> void + def visit_imaginary_node: (ImaginaryNode) -> void + + # : (ImplicitNode) -> void + def visit_implicit_node: (ImplicitNode) -> void + + # : (ImplicitRestNode) -> void + def visit_implicit_rest_node: (ImplicitRestNode) -> void + + # : (InNode) -> void + def visit_in_node: (InNode) -> void + + # : (IndexAndWriteNode) -> void + def visit_index_and_write_node: (IndexAndWriteNode) -> void + + # : (IndexOperatorWriteNode) -> void + def visit_index_operator_write_node: (IndexOperatorWriteNode) -> void + + # : (IndexOrWriteNode) -> void + def visit_index_or_write_node: (IndexOrWriteNode) -> void + + # : (IndexTargetNode) -> void + def visit_index_target_node: (IndexTargetNode) -> void + + # : (InstanceVariableAndWriteNode) -> void + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode) -> void + + # : (InstanceVariableOperatorWriteNode) -> void + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode) -> void + + # : (InstanceVariableOrWriteNode) -> void + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode) -> void + + # : (InstanceVariableReadNode) -> void + def visit_instance_variable_read_node: (InstanceVariableReadNode) -> void + + # : (InstanceVariableTargetNode) -> void + def visit_instance_variable_target_node: (InstanceVariableTargetNode) -> void + + # : (InstanceVariableWriteNode) -> void + def visit_instance_variable_write_node: (InstanceVariableWriteNode) -> void + + # : (IntegerNode) -> void + def visit_integer_node: (IntegerNode) -> void + + # : (InterpolatedMatchLastLineNode) -> void + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode) -> void + + # : (InterpolatedRegularExpressionNode) -> void + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode) -> void + + # : (InterpolatedStringNode) -> void + def visit_interpolated_string_node: (InterpolatedStringNode) -> void + + # : (InterpolatedSymbolNode) -> void + def visit_interpolated_symbol_node: (InterpolatedSymbolNode) -> void + + # : (InterpolatedXStringNode) -> void + def visit_interpolated_x_string_node: (InterpolatedXStringNode) -> void + + # : (ItLocalVariableReadNode) -> void + def visit_it_local_variable_read_node: (ItLocalVariableReadNode) -> void + + # : (ItParametersNode) -> void + def visit_it_parameters_node: (ItParametersNode) -> void + + # : (KeywordHashNode) -> void + def visit_keyword_hash_node: (KeywordHashNode) -> void + + # : (KeywordRestParameterNode) -> void + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode) -> void + + # : (LambdaNode) -> void + def visit_lambda_node: (LambdaNode) -> void + + # : (LocalVariableAndWriteNode) -> void + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode) -> void + + # : (LocalVariableOperatorWriteNode) -> void + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode) -> void + + # : (LocalVariableOrWriteNode) -> void + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode) -> void + + # : (LocalVariableReadNode) -> void + def visit_local_variable_read_node: (LocalVariableReadNode) -> void + + # : (LocalVariableTargetNode) -> void + def visit_local_variable_target_node: (LocalVariableTargetNode) -> void + + # : (LocalVariableWriteNode) -> void + def visit_local_variable_write_node: (LocalVariableWriteNode) -> void + + # : (MatchLastLineNode) -> void + def visit_match_last_line_node: (MatchLastLineNode) -> void + + # : (MatchPredicateNode) -> void + def visit_match_predicate_node: (MatchPredicateNode) -> void + + # : (MatchRequiredNode) -> void + def visit_match_required_node: (MatchRequiredNode) -> void + + # : (MatchWriteNode) -> void + def visit_match_write_node: (MatchWriteNode) -> void + + # : (MissingNode) -> void + def visit_missing_node: (MissingNode) -> void + + # : (ModuleNode) -> void + def visit_module_node: (ModuleNode) -> void + + # : (MultiTargetNode) -> void + def visit_multi_target_node: (MultiTargetNode) -> void + + # : (MultiWriteNode) -> void + def visit_multi_write_node: (MultiWriteNode) -> void + + # : (NextNode) -> void + def visit_next_node: (NextNode) -> void + + # : (NilNode) -> void + def visit_nil_node: (NilNode) -> void + + # : (NoBlockParameterNode) -> void + def visit_no_block_parameter_node: (NoBlockParameterNode) -> void + + # : (NoKeywordsParameterNode) -> void + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode) -> void + + # : (NumberedParametersNode) -> void + def visit_numbered_parameters_node: (NumberedParametersNode) -> void + + # : (NumberedReferenceReadNode) -> void + def visit_numbered_reference_read_node: (NumberedReferenceReadNode) -> void + + # : (OptionalKeywordParameterNode) -> void + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode) -> void + + # : (OptionalParameterNode) -> void + def visit_optional_parameter_node: (OptionalParameterNode) -> void + + # : (OrNode) -> void + def visit_or_node: (OrNode) -> void + + # : (ParametersNode) -> void + def visit_parameters_node: (ParametersNode) -> void + + # : (ParenthesesNode) -> void + def visit_parentheses_node: (ParenthesesNode) -> void + + # : (PinnedExpressionNode) -> void + def visit_pinned_expression_node: (PinnedExpressionNode) -> void + + # : (PinnedVariableNode) -> void + def visit_pinned_variable_node: (PinnedVariableNode) -> void + + # : (PostExecutionNode) -> void + def visit_post_execution_node: (PostExecutionNode) -> void + + # : (PreExecutionNode) -> void + def visit_pre_execution_node: (PreExecutionNode) -> void + + # : (ProgramNode) -> void + def visit_program_node: (ProgramNode) -> void + + # : (RangeNode) -> void + def visit_range_node: (RangeNode) -> void + + # : (RationalNode) -> void + def visit_rational_node: (RationalNode) -> void + + # : (RedoNode) -> void + def visit_redo_node: (RedoNode) -> void + + # : (RegularExpressionNode) -> void + def visit_regular_expression_node: (RegularExpressionNode) -> void + + # : (RequiredKeywordParameterNode) -> void + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode) -> void + + # : (RequiredParameterNode) -> void + def visit_required_parameter_node: (RequiredParameterNode) -> void + + # : (RescueModifierNode) -> void + def visit_rescue_modifier_node: (RescueModifierNode) -> void + + # : (RescueNode) -> void + def visit_rescue_node: (RescueNode) -> void + + # : (RestParameterNode) -> void + def visit_rest_parameter_node: (RestParameterNode) -> void + + # : (RetryNode) -> void + def visit_retry_node: (RetryNode) -> void + + # : (ReturnNode) -> void + def visit_return_node: (ReturnNode) -> void + + # : (SelfNode) -> void + def visit_self_node: (SelfNode) -> void + + # : (ShareableConstantNode) -> void + def visit_shareable_constant_node: (ShareableConstantNode) -> void + + # : (SingletonClassNode) -> void + def visit_singleton_class_node: (SingletonClassNode) -> void + + # : (SourceEncodingNode) -> void + def visit_source_encoding_node: (SourceEncodingNode) -> void + + # : (SourceFileNode) -> void + def visit_source_file_node: (SourceFileNode) -> void + + # : (SourceLineNode) -> void + def visit_source_line_node: (SourceLineNode) -> void + + # : (SplatNode) -> void + def visit_splat_node: (SplatNode) -> void + + # : (StatementsNode) -> void + def visit_statements_node: (StatementsNode) -> void + + # : (StringNode) -> void + def visit_string_node: (StringNode) -> void + + # : (SuperNode) -> void + def visit_super_node: (SuperNode) -> void + + # : (SymbolNode) -> void + def visit_symbol_node: (SymbolNode) -> void + + # : (TrueNode) -> void + def visit_true_node: (TrueNode) -> void + + # : (UndefNode) -> void + def visit_undef_node: (UndefNode) -> void + + # : (UnlessNode) -> void + def visit_unless_node: (UnlessNode) -> void + + # : (UntilNode) -> void + def visit_until_node: (UntilNode) -> void + + # : (WhenNode) -> void + def visit_when_node: (WhenNode) -> void + + # : (WhileNode) -> void + def visit_while_node: (WhileNode) -> void + + # : (XStringNode) -> void + def visit_x_string_node: (XStringNode) -> void + + # : (YieldNode) -> void + def visit_yield_node: (YieldNode) -> void + + private + + # Generate a unique node ID for a node throughout the digraph. + # -- + # : (node) -> String + def node_id: (node) -> String + + # Inspect a location to display the start and end line and columns in bytes. + # -- + # : (Location) -> String + def location_inspect: (Location) -> String + + # Inspect a node that has arguments_node_flags flags to display the flags as a + # comma-separated list. + # -- + # : (ArgumentsNode node) -> String + def arguments_node_flags_inspect: (ArgumentsNode node) -> String + + # Inspect a node that has array_node_flags flags to display the flags as a + # comma-separated list. + # -- + # : (ArrayNode node) -> String + def array_node_flags_inspect: (ArrayNode node) -> String + + # Inspect a node that has call_node_flags flags to display the flags as a + # comma-separated list. + # -- + # : (CallAndWriteNode | CallNode | CallOperatorWriteNode | CallOrWriteNode | CallTargetNode | IndexAndWriteNode | IndexOperatorWriteNode | IndexOrWriteNode | IndexTargetNode node) -> String + def call_node_flags_inspect: (CallAndWriteNode | CallNode | CallOperatorWriteNode | CallOrWriteNode | CallTargetNode | IndexAndWriteNode | IndexOperatorWriteNode | IndexOrWriteNode | IndexTargetNode node) -> String + + # Inspect a node that has encoding_flags flags to display the flags as a + # comma-separated list. + # -- + # : (XStringNode node) -> String + def encoding_flags_inspect: (XStringNode node) -> String + + # Inspect a node that has integer_base_flags flags to display the flags as a + # comma-separated list. + # -- + # : (IntegerNode | RationalNode node) -> String + def integer_base_flags_inspect: (IntegerNode | RationalNode node) -> String + + # Inspect a node that has interpolated_string_node_flags flags to display the flags as a + # comma-separated list. + # -- + # : (InterpolatedStringNode node) -> String + def interpolated_string_node_flags_inspect: (InterpolatedStringNode node) -> String + + # Inspect a node that has keyword_hash_node_flags flags to display the flags as a + # comma-separated list. + # -- + # : (KeywordHashNode node) -> String + def keyword_hash_node_flags_inspect: (KeywordHashNode node) -> String + + # Inspect a node that has loop_flags flags to display the flags as a + # comma-separated list. + # -- + # : (UntilNode | WhileNode node) -> String + def loop_flags_inspect: (UntilNode | WhileNode node) -> String + + # Inspect a node that has parameter_flags flags to display the flags as a + # comma-separated list. + # -- + # : (BlockLocalVariableNode | BlockParameterNode | KeywordRestParameterNode | OptionalKeywordParameterNode | OptionalParameterNode | RequiredKeywordParameterNode | RequiredParameterNode | RestParameterNode node) -> String + def parameter_flags_inspect: (BlockLocalVariableNode | BlockParameterNode | KeywordRestParameterNode | OptionalKeywordParameterNode | OptionalParameterNode | RequiredKeywordParameterNode | RequiredParameterNode | RestParameterNode node) -> String + + # Inspect a node that has parentheses_node_flags flags to display the flags as a + # comma-separated list. + # -- + # : (ParenthesesNode node) -> String + def parentheses_node_flags_inspect: (ParenthesesNode node) -> String + + # Inspect a node that has range_flags flags to display the flags as a + # comma-separated list. + # -- + # : (FlipFlopNode | RangeNode node) -> String + def range_flags_inspect: (FlipFlopNode | RangeNode node) -> String + + # Inspect a node that has regular_expression_flags flags to display the flags as a + # comma-separated list. + # -- + # : (InterpolatedMatchLastLineNode | InterpolatedRegularExpressionNode | MatchLastLineNode | RegularExpressionNode node) -> String + def regular_expression_flags_inspect: (InterpolatedMatchLastLineNode | InterpolatedRegularExpressionNode | MatchLastLineNode | RegularExpressionNode node) -> String + + # Inspect a node that has shareable_constant_node_flags flags to display the flags as a + # comma-separated list. + # -- + # : (ShareableConstantNode node) -> String + def shareable_constant_node_flags_inspect: (ShareableConstantNode node) -> String + + # Inspect a node that has string_flags flags to display the flags as a + # comma-separated list. + # -- + # : (SourceFileNode | StringNode node) -> String + def string_flags_inspect: (SourceFileNode | StringNode node) -> String + + # Inspect a node that has symbol_flags flags to display the flags as a + # comma-separated list. + # -- + # : (SymbolNode node) -> String + def symbol_flags_inspect: (SymbolNode node) -> String + end +end diff --git a/sig/generated/prism/dsl.rbs b/sig/generated/prism/dsl.rbs new file mode 100644 index 0000000000..4b09efccd3 --- /dev/null +++ b/sig/generated/prism/dsl.rbs @@ -0,0 +1,921 @@ +# Generated from lib/prism/dsl.rb with RBS::Inline + +module Prism + # The DSL module provides a set of methods that can be used to create prism + # nodes in a more concise manner. For example, instead of writing: + # + # source = Prism::Source.for("[1]", 1, []) + # + # Prism::ArrayNode.new( + # source, + # 0, + # Prism::Location.new(source, 0, 3), + # 0, + # [ + # Prism::IntegerNode.new( + # source, + # 0, + # Prism::Location.new(source, 1, 1), + # Prism::IntegerBaseFlags::DECIMAL, + # 1 + # ) + # ], + # Prism::Location.new(source, 0, 1), + # Prism::Location.new(source, 2, 1) + # ) + # + # you could instead write: + # + # class Builder + # include Prism::DSL + # + # attr_reader :default_source + # + # def initialize + # @default_source = source("[1]") + # end + # + # 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 + # Create a new Source object. + # -- + # : (String string) -> Source + def source: (String string) -> Source + + # Create a new Location object. + # -- + # : (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location + def location: (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location + + # Create a new AliasGlobalVariableNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode), ?old_name: (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode), ?keyword_loc: Location) -> AliasGlobalVariableNode + def alias_global_variable_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode, ?old_name: GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode, ?keyword_loc: Location) -> AliasGlobalVariableNode + + # Create a new AliasMethodNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: (SymbolNode | InterpolatedSymbolNode), ?old_name: (SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode), ?keyword_loc: Location) -> AliasMethodNode + def alias_method_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: SymbolNode | InterpolatedSymbolNode, ?old_name: SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode, ?keyword_loc: Location) -> AliasMethodNode + + # Create a new AlternationPatternNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AlternationPatternNode + def alternation_pattern_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AlternationPatternNode + + # Create a new AndNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AndNode + def and_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AndNode + + # Create a new ArgumentsNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: Array[Prism::node]) -> ArgumentsNode + def arguments_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: Array[Prism::node]) -> ArgumentsNode + + # Create a new ArrayNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayNode + def array_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayNode + + # Create a new ArrayPatternNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?requireds: Array[Prism::node], ?rest: Prism::node?, ?posts: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayPatternNode + def array_pattern_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?requireds: Array[Prism::node], ?rest: Prism::node?, ?posts: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayPatternNode + + # Create a new AssocNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?key: Prism::node, ?value: Prism::node, ?operator_loc: Location?) -> AssocNode + def assoc_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?key: Prism::node, ?value: Prism::node, ?operator_loc: Location?) -> AssocNode + + # Create a new AssocSplatNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node?, ?operator_loc: Location) -> AssocSplatNode + def assoc_splat_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node?, ?operator_loc: Location) -> AssocSplatNode + + # Create a new BackReferenceReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BackReferenceReadNode + def back_reference_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BackReferenceReadNode + + # Create a new BeginNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?begin_keyword_loc: Location?, ?statements: StatementsNode?, ?rescue_clause: RescueNode?, ?else_clause: ElseNode?, ?ensure_clause: EnsureNode?, ?end_keyword_loc: Location?) -> BeginNode + def begin_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?begin_keyword_loc: Location?, ?statements: StatementsNode?, ?rescue_clause: RescueNode?, ?else_clause: ElseNode?, ?ensure_clause: EnsureNode?, ?end_keyword_loc: Location?) -> BeginNode + + # Create a new BlockArgumentNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node?, ?operator_loc: Location) -> BlockArgumentNode + def block_argument_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node?, ?operator_loc: Location) -> BlockArgumentNode + + # Create a new BlockLocalVariableNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BlockLocalVariableNode + def block_local_variable_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BlockLocalVariableNode + + # Create a new BlockNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?, ?opening_loc: Location, ?closing_loc: Location) -> BlockNode + def block_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?, ?opening_loc: Location, ?closing_loc: Location) -> BlockNode + + # Create a new BlockParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> BlockParameterNode + def block_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> BlockParameterNode + + # Create a new BlockParametersNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?parameters: ParametersNode?, ?locals: Array[BlockLocalVariableNode], ?opening_loc: Location?, ?closing_loc: Location?) -> BlockParametersNode + def block_parameters_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?parameters: ParametersNode?, ?locals: Array[BlockLocalVariableNode], ?opening_loc: Location?, ?closing_loc: Location?) -> BlockParametersNode + + # Create a new BreakNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> BreakNode + def break_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> BreakNode + + # Create a new CallAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallAndWriteNode + def call_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallAndWriteNode + + # Create a new CallNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?name: Symbol, ?message_loc: Location?, ?opening_loc: Location?, ?arguments: ArgumentsNode?, ?closing_loc: Location?, ?equal_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> CallNode + def call_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?name: Symbol, ?message_loc: Location?, ?opening_loc: Location?, ?arguments: ArgumentsNode?, ?closing_loc: Location?, ?equal_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> CallNode + + # Create a new CallOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> CallOperatorWriteNode + def call_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> CallOperatorWriteNode + + # Create a new CallOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallOrWriteNode + def call_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallOrWriteNode + + # Create a new CallTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?call_operator_loc: Location, ?name: Symbol, ?message_loc: Location) -> CallTargetNode + def call_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?call_operator_loc: Location, ?name: Symbol, ?message_loc: Location) -> CallTargetNode + + # Create a new CapturePatternNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?target: LocalVariableTargetNode, ?operator_loc: Location) -> CapturePatternNode + def capture_pattern_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?target: LocalVariableTargetNode, ?operator_loc: Location) -> CapturePatternNode + + # Create a new CaseMatchNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[InNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseMatchNode + def case_match_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[InNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseMatchNode + + # Create a new CaseNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[WhenNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseNode + def case_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[WhenNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseNode + + # Create a new ClassNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?constant_path: (ConstantReadNode | ConstantPathNode | CallNode), ?inheritance_operator_loc: Location?, ?superclass: Prism::node?, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ClassNode + def class_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?constant_path: ConstantReadNode | ConstantPathNode | CallNode, ?inheritance_operator_loc: Location?, ?superclass: Prism::node?, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ClassNode + + # Create a new ClassVariableAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableAndWriteNode + def class_variable_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableAndWriteNode + + # Create a new ClassVariableOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ClassVariableOperatorWriteNode + def class_variable_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ClassVariableOperatorWriteNode + + # Create a new ClassVariableOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableOrWriteNode + def class_variable_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableOrWriteNode + + # Create a new ClassVariableReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableReadNode + def class_variable_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableReadNode + + # Create a new ClassVariableTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableTargetNode + def class_variable_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableTargetNode + + # Create a new ClassVariableWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ClassVariableWriteNode + def class_variable_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ClassVariableWriteNode + + # Create a new ConstantAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantAndWriteNode + def constant_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantAndWriteNode + + # Create a new ConstantOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantOperatorWriteNode + def constant_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantOperatorWriteNode + + # Create a new ConstantOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantOrWriteNode + def constant_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantOrWriteNode + + # Create a new ConstantPathAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathAndWriteNode + def constant_path_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathAndWriteNode + + # Create a new ConstantPathNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathNode + def constant_path_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathNode + + # Create a new ConstantPathOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantPathOperatorWriteNode + def constant_path_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantPathOperatorWriteNode + + # Create a new ConstantPathOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathOrWriteNode + def constant_path_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathOrWriteNode + + # Create a new ConstantPathTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathTargetNode + def constant_path_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathTargetNode + + # Create a new ConstantPathWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathWriteNode + def constant_path_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathWriteNode + + # Create a new ConstantReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantReadNode + def constant_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantReadNode + + # Create a new ConstantTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantTargetNode + def constant_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantTargetNode + + # Create a new ConstantWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ConstantWriteNode + def constant_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ConstantWriteNode + + # Create a new DefNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?receiver: Prism::node?, ?parameters: ParametersNode?, ?body: (StatementsNode | BeginNode)?, ?locals: Array[Symbol], ?def_keyword_loc: Location, ?operator_loc: Location?, ?lparen_loc: Location?, ?rparen_loc: Location?, ?equal_loc: Location?, ?end_keyword_loc: Location?) -> DefNode + def def_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?receiver: Prism::node?, ?parameters: ParametersNode?, ?body: (StatementsNode | BeginNode)?, ?locals: Array[Symbol], ?def_keyword_loc: Location, ?operator_loc: Location?, ?lparen_loc: Location?, ?rparen_loc: Location?, ?equal_loc: Location?, ?end_keyword_loc: Location?) -> DefNode + + # Create a new DefinedNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?lparen_loc: Location?, ?value: Prism::node, ?rparen_loc: Location?, ?keyword_loc: Location) -> DefinedNode + def defined_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?lparen_loc: Location?, ?value: Prism::node, ?rparen_loc: Location?, ?keyword_loc: Location) -> DefinedNode + + # Create a new ElseNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?else_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location?) -> ElseNode + def else_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?else_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location?) -> ElseNode + + # Create a new EmbeddedStatementsNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?statements: StatementsNode?, ?closing_loc: Location) -> EmbeddedStatementsNode + def embedded_statements_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?statements: StatementsNode?, ?closing_loc: Location) -> EmbeddedStatementsNode + + # Create a new EmbeddedVariableNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?variable: (InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode)) -> EmbeddedVariableNode + def embedded_variable_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?variable: InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) -> EmbeddedVariableNode + + # Create a new EnsureNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?ensure_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location) -> EnsureNode + def ensure_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?ensure_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location) -> EnsureNode + + # Create a new FalseNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> FalseNode + def false_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> FalseNode + + # Create a new FindPatternNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?left: SplatNode, ?requireds: Array[Prism::node], ?right: (SplatNode | MissingNode), ?opening_loc: Location?, ?closing_loc: Location?) -> FindPatternNode + def find_pattern_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?left: SplatNode, ?requireds: Array[Prism::node], ?right: SplatNode | MissingNode, ?opening_loc: Location?, ?closing_loc: Location?) -> FindPatternNode + + # Create a new FlipFlopNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> FlipFlopNode + def flip_flop_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> FlipFlopNode + + # Create a new FloatNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Float) -> FloatNode + def float_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Float) -> FloatNode + + # Create a new ForNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?index: (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode), ?collection: Prism::node, ?statements: StatementsNode?, ?for_keyword_loc: Location, ?in_keyword_loc: Location, ?do_keyword_loc: Location?, ?end_keyword_loc: Location) -> ForNode + def for_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?index: LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode, ?collection: Prism::node, ?statements: StatementsNode?, ?for_keyword_loc: Location, ?in_keyword_loc: Location, ?do_keyword_loc: Location?, ?end_keyword_loc: Location) -> ForNode + + # Create a new ForwardingArgumentsNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ForwardingArgumentsNode + def forwarding_arguments_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ForwardingArgumentsNode + + # Create a new ForwardingParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ForwardingParameterNode + def forwarding_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ForwardingParameterNode + + # Create a new ForwardingSuperNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?block: BlockNode?) -> ForwardingSuperNode + def forwarding_super_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?block: BlockNode?) -> ForwardingSuperNode + + # Create a new GlobalVariableAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableAndWriteNode + def global_variable_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableAndWriteNode + + # Create a new GlobalVariableOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> GlobalVariableOperatorWriteNode + def global_variable_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> GlobalVariableOperatorWriteNode + + # Create a new GlobalVariableOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableOrWriteNode + def global_variable_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableOrWriteNode + + # Create a new GlobalVariableReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableReadNode + def global_variable_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableReadNode + + # Create a new GlobalVariableTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableTargetNode + def global_variable_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableTargetNode + + # Create a new GlobalVariableWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> GlobalVariableWriteNode + def global_variable_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> GlobalVariableWriteNode + + # Create a new HashNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?elements: Array[AssocNode | AssocSplatNode], ?closing_loc: Location) -> HashNode + def hash_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?elements: Array[AssocNode | AssocSplatNode], ?closing_loc: Location) -> HashNode + + # Create a new HashPatternNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?elements: Array[AssocNode], ?rest: (AssocSplatNode | NoKeywordsParameterNode)?, ?opening_loc: Location?, ?closing_loc: Location?) -> HashPatternNode + def hash_pattern_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?elements: Array[AssocNode], ?rest: (AssocSplatNode | NoKeywordsParameterNode)?, ?opening_loc: Location?, ?closing_loc: Location?) -> HashPatternNode + + # Create a new IfNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?if_keyword_loc: Location?, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: (ElseNode | IfNode)?, ?end_keyword_loc: Location?) -> IfNode + def if_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?if_keyword_loc: Location?, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: (ElseNode | IfNode)?, ?end_keyword_loc: Location?) -> IfNode + + # Create a new ImaginaryNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?numeric: (FloatNode | IntegerNode | RationalNode)) -> ImaginaryNode + def imaginary_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?numeric: FloatNode | IntegerNode | RationalNode) -> ImaginaryNode + + # Create a new ImplicitNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: (LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode)) -> ImplicitNode + def implicit_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode) -> ImplicitNode + + # Create a new ImplicitRestNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ImplicitRestNode + def implicit_rest_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ImplicitRestNode + + # Create a new InNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?pattern: Prism::node, ?statements: StatementsNode?, ?in_loc: Location, ?then_loc: Location?) -> InNode + def in_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?pattern: Prism::node, ?statements: StatementsNode?, ?in_loc: Location, ?then_loc: Location?) -> InNode + + # Create a new IndexAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexAndWriteNode + def index_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexAndWriteNode + + # Create a new IndexOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> IndexOperatorWriteNode + def index_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> IndexOperatorWriteNode + + # Create a new IndexOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexOrWriteNode + def index_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexOrWriteNode + + # Create a new IndexTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?) -> IndexTargetNode + def index_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?) -> IndexTargetNode + + # Create a new InstanceVariableAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableAndWriteNode + def instance_variable_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableAndWriteNode + + # Create a new InstanceVariableOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> InstanceVariableOperatorWriteNode + def instance_variable_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> InstanceVariableOperatorWriteNode + + # Create a new InstanceVariableOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableOrWriteNode + def instance_variable_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableOrWriteNode + + # Create a new InstanceVariableReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableReadNode + def instance_variable_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableReadNode + + # Create a new InstanceVariableTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableTargetNode + def instance_variable_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableTargetNode + + # Create a new InstanceVariableWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> InstanceVariableWriteNode + def instance_variable_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> InstanceVariableWriteNode + + # Create a new IntegerNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Integer) -> IntegerNode + def integer_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Integer) -> IntegerNode + + # Create a new InterpolatedMatchLastLineNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedMatchLastLineNode + def interpolated_match_last_line_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedMatchLastLineNode + + # Create a new InterpolatedRegularExpressionNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedRegularExpressionNode + def interpolated_regular_expression_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedRegularExpressionNode + + # Create a new InterpolatedStringNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode], ?closing_loc: Location?) -> InterpolatedStringNode + def interpolated_string_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode], ?closing_loc: Location?) -> InterpolatedStringNode + + # Create a new InterpolatedSymbolNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location?) -> InterpolatedSymbolNode + def interpolated_symbol_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location?) -> InterpolatedSymbolNode + + # Create a new InterpolatedXStringNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedXStringNode + def interpolated_x_string_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedXStringNode + + # Create a new ItLocalVariableReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ItLocalVariableReadNode + def it_local_variable_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ItLocalVariableReadNode + + # Create a new ItParametersNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ItParametersNode + def it_parameters_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ItParametersNode + + # Create a new KeywordHashNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[AssocNode | AssocSplatNode]) -> KeywordHashNode + def keyword_hash_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[AssocNode | AssocSplatNode]) -> KeywordHashNode + + # Create a new KeywordRestParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> KeywordRestParameterNode + def keyword_rest_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> KeywordRestParameterNode + + # Create a new LambdaNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?operator_loc: Location, ?opening_loc: Location, ?closing_loc: Location, ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?) -> LambdaNode + def lambda_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?operator_loc: Location, ?opening_loc: Location, ?closing_loc: Location, ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?) -> LambdaNode + + # Create a new LocalVariableAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableAndWriteNode + def local_variable_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableAndWriteNode + + # Create a new LocalVariableOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?binary_operator: Symbol, ?depth: Integer) -> LocalVariableOperatorWriteNode + def local_variable_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?binary_operator: Symbol, ?depth: Integer) -> LocalVariableOperatorWriteNode + + # Create a new LocalVariableOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableOrWriteNode + def local_variable_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableOrWriteNode + + # Create a new LocalVariableReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableReadNode + def local_variable_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableReadNode + + # Create a new LocalVariableTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableTargetNode + def local_variable_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableTargetNode + + # Create a new LocalVariableWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> LocalVariableWriteNode + def local_variable_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> LocalVariableWriteNode + + # Create a new MatchLastLineNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> MatchLastLineNode + def match_last_line_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> MatchLastLineNode + + # Create a new MatchPredicateNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchPredicateNode + def match_predicate_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchPredicateNode + + # Create a new MatchRequiredNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchRequiredNode + def match_required_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchRequiredNode + + # Create a new MatchWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?call: CallNode, ?targets: Array[LocalVariableTargetNode]) -> MatchWriteNode + def match_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?call: CallNode, ?targets: Array[LocalVariableTargetNode]) -> MatchWriteNode + + # Create a new MissingNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> MissingNode + def missing_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> MissingNode + + # Create a new ModuleNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?module_keyword_loc: Location, ?constant_path: (ConstantReadNode | ConstantPathNode | MissingNode), ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ModuleNode + def module_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?module_keyword_loc: Location, ?constant_path: ConstantReadNode | ConstantPathNode | MissingNode, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ModuleNode + + # Create a new MultiTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?) -> MultiTargetNode + def multi_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?) -> MultiTargetNode + + # Create a new MultiWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?, ?operator_loc: Location, ?value: Prism::node) -> MultiWriteNode + def multi_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?, ?operator_loc: Location, ?value: Prism::node) -> MultiWriteNode + + # Create a new NextNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> NextNode + def next_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> NextNode + + # Create a new NilNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> NilNode + def nil_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> NilNode + + # Create a new NoBlockParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoBlockParameterNode + def no_block_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoBlockParameterNode + + # Create a new NoKeywordsParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoKeywordsParameterNode + def no_keywords_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoKeywordsParameterNode + + # Create a new NumberedParametersNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?maximum: Integer) -> NumberedParametersNode + def numbered_parameters_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?maximum: Integer) -> NumberedParametersNode + + # Create a new NumberedReferenceReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?number: Integer) -> NumberedReferenceReadNode + def numbered_reference_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?number: Integer) -> NumberedReferenceReadNode + + # Create a new OptionalKeywordParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node) -> OptionalKeywordParameterNode + def optional_keyword_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node) -> OptionalKeywordParameterNode + + # Create a new OptionalParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> OptionalParameterNode + def optional_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> OptionalParameterNode + + # Create a new OrNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> OrNode + def or_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> OrNode + + # Create a new ParametersNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?requireds: Array[RequiredParameterNode | MultiTargetNode], ?optionals: Array[OptionalParameterNode], ?rest: (RestParameterNode | ImplicitRestNode)?, ?posts: Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode], ?keywords: Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode], ?keyword_rest: (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)?, ?block: (BlockParameterNode | NoBlockParameterNode)?) -> ParametersNode + def parameters_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?requireds: Array[RequiredParameterNode | MultiTargetNode], ?optionals: Array[OptionalParameterNode], ?rest: (RestParameterNode | ImplicitRestNode)?, ?posts: Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode], ?keywords: Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode], ?keyword_rest: (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)?, ?block: (BlockParameterNode | NoBlockParameterNode)?) -> ParametersNode + + # Create a new ParenthesesNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Prism::node?, ?opening_loc: Location, ?closing_loc: Location) -> ParenthesesNode + def parentheses_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Prism::node?, ?opening_loc: Location, ?closing_loc: Location) -> ParenthesesNode + + # Create a new PinnedExpressionNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?operator_loc: Location, ?lparen_loc: Location, ?rparen_loc: Location) -> PinnedExpressionNode + def pinned_expression_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?operator_loc: Location, ?lparen_loc: Location, ?rparen_loc: Location) -> PinnedExpressionNode + + # Create a new PinnedVariableNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?variable: (LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode), ?operator_loc: Location) -> PinnedVariableNode + def pinned_variable_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?variable: LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode, ?operator_loc: Location) -> PinnedVariableNode + + # Create a new PostExecutionNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PostExecutionNode + def post_execution_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PostExecutionNode + + # Create a new PreExecutionNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PreExecutionNode + def pre_execution_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PreExecutionNode + + # Create a new ProgramNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?statements: StatementsNode) -> ProgramNode + def program_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?statements: StatementsNode) -> ProgramNode + + # Create a new RangeNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> RangeNode + def range_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> RangeNode + + # Create a new RationalNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?numerator: Integer, ?denominator: Integer) -> RationalNode + def rational_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?numerator: Integer, ?denominator: Integer) -> RationalNode + + # Create a new RedoNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> RedoNode + def redo_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> RedoNode + + # Create a new RegularExpressionNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> RegularExpressionNode + def regular_expression_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> RegularExpressionNode + + # Create a new RequiredKeywordParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location) -> RequiredKeywordParameterNode + def required_keyword_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location) -> RequiredKeywordParameterNode + + # Create a new RequiredParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> RequiredParameterNode + def required_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> RequiredParameterNode + + # Create a new RescueModifierNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?keyword_loc: Location, ?rescue_expression: Prism::node) -> RescueModifierNode + def rescue_modifier_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?keyword_loc: Location, ?rescue_expression: Prism::node) -> RescueModifierNode + + # Create a new RescueNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?exceptions: Array[Prism::node], ?operator_loc: Location?, ?reference: (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)?, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: RescueNode?) -> RescueNode + def rescue_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?exceptions: Array[Prism::node], ?operator_loc: Location?, ?reference: (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)?, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: RescueNode?) -> RescueNode + + # Create a new RestParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> RestParameterNode + def rest_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> RestParameterNode + + # Create a new RetryNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> RetryNode + def retry_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> RetryNode + + # Create a new ReturnNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?arguments: ArgumentsNode?) -> ReturnNode + def return_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?arguments: ArgumentsNode?) -> ReturnNode + + # Create a new SelfNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> SelfNode + def self_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> SelfNode + + # Create a new ShareableConstantNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?write: (ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode)) -> ShareableConstantNode + def shareable_constant_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?write: ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode) -> ShareableConstantNode + + # Create a new SingletonClassNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?operator_loc: Location, ?expression: Prism::node, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location) -> SingletonClassNode + def singleton_class_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?operator_loc: Location, ?expression: Prism::node, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location) -> SingletonClassNode + + # Create a new SourceEncodingNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> SourceEncodingNode + def source_encoding_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> SourceEncodingNode + + # Create a new SourceFileNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?filepath: String) -> SourceFileNode + def source_file_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?filepath: String) -> SourceFileNode + + # Create a new SourceLineNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> SourceLineNode + def source_line_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> SourceLineNode + + # Create a new SplatNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?expression: Prism::node?) -> SplatNode + def splat_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?expression: Prism::node?) -> SplatNode + + # Create a new StatementsNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Array[Prism::node]) -> StatementsNode + def statements_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Array[Prism::node]) -> StatementsNode + + # Create a new StringNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?content_loc: Location, ?closing_loc: Location?, ?unescaped: String) -> StringNode + def string_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?content_loc: Location, ?closing_loc: Location?, ?unescaped: String) -> StringNode + + # Create a new SuperNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> SuperNode + def super_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> SuperNode + + # Create a new SymbolNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?value_loc: Location?, ?closing_loc: Location?, ?unescaped: String) -> SymbolNode + def symbol_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?value_loc: Location?, ?closing_loc: Location?, ?unescaped: String) -> SymbolNode + + # Create a new TrueNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> TrueNode + def true_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> TrueNode + + # Create a new UndefNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?names: Array[SymbolNode | InterpolatedSymbolNode], ?keyword_loc: Location) -> UndefNode + def undef_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?names: Array[SymbolNode | InterpolatedSymbolNode], ?keyword_loc: Location) -> UndefNode + + # Create a new UnlessNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?else_clause: ElseNode?, ?end_keyword_loc: Location?) -> UnlessNode + def unless_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?else_clause: ElseNode?, ?end_keyword_loc: Location?) -> UnlessNode + + # Create a new UntilNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> UntilNode + def until_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> UntilNode + + # Create a new WhenNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?conditions: Array[Prism::node], ?then_keyword_loc: Location?, ?statements: StatementsNode?) -> WhenNode + def when_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?conditions: Array[Prism::node], ?then_keyword_loc: Location?, ?statements: StatementsNode?) -> WhenNode + + # Create a new WhileNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> WhileNode + def while_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> WhileNode + + # Create a new XStringNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> XStringNode + def x_string_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> XStringNode + + # Create a new YieldNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?) -> YieldNode + def yield_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?) -> YieldNode + + # Retrieve the value of one of the ArgumentsNodeFlags flags. + # -- + # : (Symbol name) -> Integer + def arguments_node_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the ArrayNodeFlags flags. + # -- + # : (Symbol name) -> Integer + def array_node_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the CallNodeFlags flags. + # -- + # : (Symbol name) -> Integer + def call_node_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the EncodingFlags flags. + # -- + # : (Symbol name) -> Integer + def encoding_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the IntegerBaseFlags flags. + # -- + # : (Symbol name) -> Integer + def integer_base_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the InterpolatedStringNodeFlags flags. + # -- + # : (Symbol name) -> Integer + def interpolated_string_node_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the KeywordHashNodeFlags flags. + # -- + # : (Symbol name) -> Integer + def keyword_hash_node_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the LoopFlags flags. + # -- + # : (Symbol name) -> Integer + def loop_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the ParameterFlags flags. + # -- + # : (Symbol name) -> Integer + def parameter_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the ParenthesesNodeFlags flags. + # -- + # : (Symbol name) -> Integer + def parentheses_node_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the RangeFlags flags. + # -- + # : (Symbol name) -> Integer + def range_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the RegularExpressionFlags flags. + # -- + # : (Symbol name) -> Integer + def regular_expression_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the ShareableConstantNodeFlags flags. + # -- + # : (Symbol name) -> Integer + def shareable_constant_node_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the StringFlags flags. + # -- + # : (Symbol name) -> Integer + def string_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the SymbolFlags flags. + # -- + # : (Symbol name) -> Integer + def symbol_flag: (Symbol name) -> Integer + + private + + # The default source object that gets attached to nodes and locations if no + # source is specified. + # -- + # : () -> Source + def default_source: () -> Source + + # The default location object that gets attached to nodes if no location is + # specified, which uses the given source. + # -- + # : () -> Location + def default_location: () -> Location + + # The default node that gets attached to nodes if no node is specified for a + # required node field. + # -- + # : (Source source, Location location) -> node + def default_node: (Source source, Location location) -> node + end +end diff --git a/sig/generated/prism/inspect_visitor.rbs b/sig/generated/prism/inspect_visitor.rbs new file mode 100644 index 0000000000..1219427ceb --- /dev/null +++ b/sig/generated/prism/inspect_visitor.rbs @@ -0,0 +1,509 @@ +# Generated from lib/prism/inspect_visitor.rb with RBS::Inline + +module Prism + # This visitor is responsible for composing the strings that get returned by + # the various #inspect methods defined on each of the nodes. + class InspectVisitor < Visitor + # Most of the time, we can simply pass down the indent to the next node. + # However, when we are inside a list we want some extra special formatting + # when we hit an element in that list. In this case, we have a special + # command that replaces the subsequent indent with the given value. + class Replace + # :nodoc: + attr_reader value: String + + # : (String value) -> void + def initialize: (String value) -> void + end + + # The current prefix string. + # :stopdoc: + attr_reader indent: String + + # The list of commands that we need to execute in order to compose the + # final string. + # : stopdoc: + attr_reader commands: Array[[ String | node | Replace, String ]] + + # : (?String indent) -> void + def initialize: (?String indent) -> void + + # Compose an inspect string for the given node. + # -- + # : (node node) -> String + def self.compose: (node node) -> String + + # Compose the final string. + # -- + # : () -> String + def compose: () -> String + + # : (AliasGlobalVariableNode node) -> void + def visit_alias_global_variable_node: (AliasGlobalVariableNode node) -> void + + # : (AliasMethodNode node) -> void + def visit_alias_method_node: (AliasMethodNode node) -> void + + # : (AlternationPatternNode node) -> void + def visit_alternation_pattern_node: (AlternationPatternNode node) -> void + + # : (AndNode node) -> void + def visit_and_node: (AndNode node) -> void + + # : (ArgumentsNode node) -> void + def visit_arguments_node: (ArgumentsNode node) -> void + + # : (ArrayNode node) -> void + def visit_array_node: (ArrayNode node) -> void + + # : (ArrayPatternNode node) -> void + def visit_array_pattern_node: (ArrayPatternNode node) -> void + + # : (AssocNode node) -> void + def visit_assoc_node: (AssocNode node) -> void + + # : (AssocSplatNode node) -> void + def visit_assoc_splat_node: (AssocSplatNode node) -> void + + # : (BackReferenceReadNode node) -> void + def visit_back_reference_read_node: (BackReferenceReadNode node) -> void + + # : (BeginNode node) -> void + def visit_begin_node: (BeginNode node) -> void + + # : (BlockArgumentNode node) -> void + def visit_block_argument_node: (BlockArgumentNode node) -> void + + # : (BlockLocalVariableNode node) -> void + def visit_block_local_variable_node: (BlockLocalVariableNode node) -> void + + # : (BlockNode node) -> void + def visit_block_node: (BlockNode node) -> void + + # : (BlockParameterNode node) -> void + def visit_block_parameter_node: (BlockParameterNode node) -> void + + # : (BlockParametersNode node) -> void + def visit_block_parameters_node: (BlockParametersNode node) -> void + + # : (BreakNode node) -> void + def visit_break_node: (BreakNode node) -> void + + # : (CallAndWriteNode node) -> void + def visit_call_and_write_node: (CallAndWriteNode node) -> void + + # : (CallNode node) -> void + def visit_call_node: (CallNode node) -> void + + # : (CallOperatorWriteNode node) -> void + def visit_call_operator_write_node: (CallOperatorWriteNode node) -> void + + # : (CallOrWriteNode node) -> void + def visit_call_or_write_node: (CallOrWriteNode node) -> void + + # : (CallTargetNode node) -> void + def visit_call_target_node: (CallTargetNode node) -> void + + # : (CapturePatternNode node) -> void + def visit_capture_pattern_node: (CapturePatternNode node) -> void + + # : (CaseMatchNode node) -> void + def visit_case_match_node: (CaseMatchNode node) -> void + + # : (CaseNode node) -> void + def visit_case_node: (CaseNode node) -> void + + # : (ClassNode node) -> void + def visit_class_node: (ClassNode node) -> void + + # : (ClassVariableAndWriteNode node) -> void + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode node) -> void + + # : (ClassVariableOperatorWriteNode node) -> void + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode node) -> void + + # : (ClassVariableOrWriteNode node) -> void + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode node) -> void + + # : (ClassVariableReadNode node) -> void + def visit_class_variable_read_node: (ClassVariableReadNode node) -> void + + # : (ClassVariableTargetNode node) -> void + def visit_class_variable_target_node: (ClassVariableTargetNode node) -> void + + # : (ClassVariableWriteNode node) -> void + def visit_class_variable_write_node: (ClassVariableWriteNode node) -> void + + # : (ConstantAndWriteNode node) -> void + def visit_constant_and_write_node: (ConstantAndWriteNode node) -> void + + # : (ConstantOperatorWriteNode node) -> void + def visit_constant_operator_write_node: (ConstantOperatorWriteNode node) -> void + + # : (ConstantOrWriteNode node) -> void + def visit_constant_or_write_node: (ConstantOrWriteNode node) -> void + + # : (ConstantPathAndWriteNode node) -> void + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode node) -> void + + # : (ConstantPathNode node) -> void + def visit_constant_path_node: (ConstantPathNode node) -> void + + # : (ConstantPathOperatorWriteNode node) -> void + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode node) -> void + + # : (ConstantPathOrWriteNode node) -> void + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode node) -> void + + # : (ConstantPathTargetNode node) -> void + def visit_constant_path_target_node: (ConstantPathTargetNode node) -> void + + # : (ConstantPathWriteNode node) -> void + def visit_constant_path_write_node: (ConstantPathWriteNode node) -> void + + # : (ConstantReadNode node) -> void + def visit_constant_read_node: (ConstantReadNode node) -> void + + # : (ConstantTargetNode node) -> void + def visit_constant_target_node: (ConstantTargetNode node) -> void + + # : (ConstantWriteNode node) -> void + def visit_constant_write_node: (ConstantWriteNode node) -> void + + # : (DefNode node) -> void + def visit_def_node: (DefNode node) -> void + + # : (DefinedNode node) -> void + def visit_defined_node: (DefinedNode node) -> void + + # : (ElseNode node) -> void + def visit_else_node: (ElseNode node) -> void + + # : (EmbeddedStatementsNode node) -> void + def visit_embedded_statements_node: (EmbeddedStatementsNode node) -> void + + # : (EmbeddedVariableNode node) -> void + def visit_embedded_variable_node: (EmbeddedVariableNode node) -> void + + # : (EnsureNode node) -> void + def visit_ensure_node: (EnsureNode node) -> void + + # : (FalseNode node) -> void + def visit_false_node: (FalseNode node) -> void + + # : (FindPatternNode node) -> void + def visit_find_pattern_node: (FindPatternNode node) -> void + + # : (FlipFlopNode node) -> void + def visit_flip_flop_node: (FlipFlopNode node) -> void + + # : (FloatNode node) -> void + def visit_float_node: (FloatNode node) -> void + + # : (ForNode node) -> void + def visit_for_node: (ForNode node) -> void + + # : (ForwardingArgumentsNode node) -> void + def visit_forwarding_arguments_node: (ForwardingArgumentsNode node) -> void + + # : (ForwardingParameterNode node) -> void + def visit_forwarding_parameter_node: (ForwardingParameterNode node) -> void + + # : (ForwardingSuperNode node) -> void + def visit_forwarding_super_node: (ForwardingSuperNode node) -> void + + # : (GlobalVariableAndWriteNode node) -> void + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode node) -> void + + # : (GlobalVariableOperatorWriteNode node) -> void + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode node) -> void + + # : (GlobalVariableOrWriteNode node) -> void + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode node) -> void + + # : (GlobalVariableReadNode node) -> void + def visit_global_variable_read_node: (GlobalVariableReadNode node) -> void + + # : (GlobalVariableTargetNode node) -> void + def visit_global_variable_target_node: (GlobalVariableTargetNode node) -> void + + # : (GlobalVariableWriteNode node) -> void + def visit_global_variable_write_node: (GlobalVariableWriteNode node) -> void + + # : (HashNode node) -> void + def visit_hash_node: (HashNode node) -> void + + # : (HashPatternNode node) -> void + def visit_hash_pattern_node: (HashPatternNode node) -> void + + # : (IfNode node) -> void + def visit_if_node: (IfNode node) -> void + + # : (ImaginaryNode node) -> void + def visit_imaginary_node: (ImaginaryNode node) -> void + + # : (ImplicitNode node) -> void + def visit_implicit_node: (ImplicitNode node) -> void + + # : (ImplicitRestNode node) -> void + def visit_implicit_rest_node: (ImplicitRestNode node) -> void + + # : (InNode node) -> void + def visit_in_node: (InNode node) -> void + + # : (IndexAndWriteNode node) -> void + def visit_index_and_write_node: (IndexAndWriteNode node) -> void + + # : (IndexOperatorWriteNode node) -> void + def visit_index_operator_write_node: (IndexOperatorWriteNode node) -> void + + # : (IndexOrWriteNode node) -> void + def visit_index_or_write_node: (IndexOrWriteNode node) -> void + + # : (IndexTargetNode node) -> void + def visit_index_target_node: (IndexTargetNode node) -> void + + # : (InstanceVariableAndWriteNode node) -> void + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode node) -> void + + # : (InstanceVariableOperatorWriteNode node) -> void + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode node) -> void + + # : (InstanceVariableOrWriteNode node) -> void + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode node) -> void + + # : (InstanceVariableReadNode node) -> void + def visit_instance_variable_read_node: (InstanceVariableReadNode node) -> void + + # : (InstanceVariableTargetNode node) -> void + def visit_instance_variable_target_node: (InstanceVariableTargetNode node) -> void + + # : (InstanceVariableWriteNode node) -> void + def visit_instance_variable_write_node: (InstanceVariableWriteNode node) -> void + + # : (IntegerNode node) -> void + def visit_integer_node: (IntegerNode node) -> void + + # : (InterpolatedMatchLastLineNode node) -> void + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode node) -> void + + # : (InterpolatedRegularExpressionNode node) -> void + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode node) -> void + + # : (InterpolatedStringNode node) -> void + def visit_interpolated_string_node: (InterpolatedStringNode node) -> void + + # : (InterpolatedSymbolNode node) -> void + def visit_interpolated_symbol_node: (InterpolatedSymbolNode node) -> void + + # : (InterpolatedXStringNode node) -> void + def visit_interpolated_x_string_node: (InterpolatedXStringNode node) -> void + + # : (ItLocalVariableReadNode node) -> void + def visit_it_local_variable_read_node: (ItLocalVariableReadNode node) -> void + + # : (ItParametersNode node) -> void + def visit_it_parameters_node: (ItParametersNode node) -> void + + # : (KeywordHashNode node) -> void + def visit_keyword_hash_node: (KeywordHashNode node) -> void + + # : (KeywordRestParameterNode node) -> void + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode node) -> void + + # : (LambdaNode node) -> void + def visit_lambda_node: (LambdaNode node) -> void + + # : (LocalVariableAndWriteNode node) -> void + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode node) -> void + + # : (LocalVariableOperatorWriteNode node) -> void + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode node) -> void + + # : (LocalVariableOrWriteNode node) -> void + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode node) -> void + + # : (LocalVariableReadNode node) -> void + def visit_local_variable_read_node: (LocalVariableReadNode node) -> void + + # : (LocalVariableTargetNode node) -> void + def visit_local_variable_target_node: (LocalVariableTargetNode node) -> void + + # : (LocalVariableWriteNode node) -> void + def visit_local_variable_write_node: (LocalVariableWriteNode node) -> void + + # : (MatchLastLineNode node) -> void + def visit_match_last_line_node: (MatchLastLineNode node) -> void + + # : (MatchPredicateNode node) -> void + def visit_match_predicate_node: (MatchPredicateNode node) -> void + + # : (MatchRequiredNode node) -> void + def visit_match_required_node: (MatchRequiredNode node) -> void + + # : (MatchWriteNode node) -> void + def visit_match_write_node: (MatchWriteNode node) -> void + + # : (MissingNode node) -> void + def visit_missing_node: (MissingNode node) -> void + + # : (ModuleNode node) -> void + def visit_module_node: (ModuleNode node) -> void + + # : (MultiTargetNode node) -> void + def visit_multi_target_node: (MultiTargetNode node) -> void + + # : (MultiWriteNode node) -> void + def visit_multi_write_node: (MultiWriteNode node) -> void + + # : (NextNode node) -> void + def visit_next_node: (NextNode node) -> void + + # : (NilNode node) -> void + def visit_nil_node: (NilNode node) -> void + + # : (NoBlockParameterNode node) -> void + def visit_no_block_parameter_node: (NoBlockParameterNode node) -> void + + # : (NoKeywordsParameterNode node) -> void + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode node) -> void + + # : (NumberedParametersNode node) -> void + def visit_numbered_parameters_node: (NumberedParametersNode node) -> void + + # : (NumberedReferenceReadNode node) -> void + def visit_numbered_reference_read_node: (NumberedReferenceReadNode node) -> void + + # : (OptionalKeywordParameterNode node) -> void + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode node) -> void + + # : (OptionalParameterNode node) -> void + def visit_optional_parameter_node: (OptionalParameterNode node) -> void + + # : (OrNode node) -> void + def visit_or_node: (OrNode node) -> void + + # : (ParametersNode node) -> void + def visit_parameters_node: (ParametersNode node) -> void + + # : (ParenthesesNode node) -> void + def visit_parentheses_node: (ParenthesesNode node) -> void + + # : (PinnedExpressionNode node) -> void + def visit_pinned_expression_node: (PinnedExpressionNode node) -> void + + # : (PinnedVariableNode node) -> void + def visit_pinned_variable_node: (PinnedVariableNode node) -> void + + # : (PostExecutionNode node) -> void + def visit_post_execution_node: (PostExecutionNode node) -> void + + # : (PreExecutionNode node) -> void + def visit_pre_execution_node: (PreExecutionNode node) -> void + + # : (ProgramNode node) -> void + def visit_program_node: (ProgramNode node) -> void + + # : (RangeNode node) -> void + def visit_range_node: (RangeNode node) -> void + + # : (RationalNode node) -> void + def visit_rational_node: (RationalNode node) -> void + + # : (RedoNode node) -> void + def visit_redo_node: (RedoNode node) -> void + + # : (RegularExpressionNode node) -> void + def visit_regular_expression_node: (RegularExpressionNode node) -> void + + # : (RequiredKeywordParameterNode node) -> void + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode node) -> void + + # : (RequiredParameterNode node) -> void + def visit_required_parameter_node: (RequiredParameterNode node) -> void + + # : (RescueModifierNode node) -> void + def visit_rescue_modifier_node: (RescueModifierNode node) -> void + + # : (RescueNode node) -> void + def visit_rescue_node: (RescueNode node) -> void + + # : (RestParameterNode node) -> void + def visit_rest_parameter_node: (RestParameterNode node) -> void + + # : (RetryNode node) -> void + def visit_retry_node: (RetryNode node) -> void + + # : (ReturnNode node) -> void + def visit_return_node: (ReturnNode node) -> void + + # : (SelfNode node) -> void + def visit_self_node: (SelfNode node) -> void + + # : (ShareableConstantNode node) -> void + def visit_shareable_constant_node: (ShareableConstantNode node) -> void + + # : (SingletonClassNode node) -> void + def visit_singleton_class_node: (SingletonClassNode node) -> void + + # : (SourceEncodingNode node) -> void + def visit_source_encoding_node: (SourceEncodingNode node) -> void + + # : (SourceFileNode node) -> void + def visit_source_file_node: (SourceFileNode node) -> void + + # : (SourceLineNode node) -> void + def visit_source_line_node: (SourceLineNode node) -> void + + # : (SplatNode node) -> void + def visit_splat_node: (SplatNode node) -> void + + # : (StatementsNode node) -> void + def visit_statements_node: (StatementsNode node) -> void + + # : (StringNode node) -> void + def visit_string_node: (StringNode node) -> void + + # : (SuperNode node) -> void + def visit_super_node: (SuperNode node) -> void + + # : (SymbolNode node) -> void + def visit_symbol_node: (SymbolNode node) -> void + + # : (TrueNode node) -> void + def visit_true_node: (TrueNode node) -> void + + # : (UndefNode node) -> void + def visit_undef_node: (UndefNode node) -> void + + # : (UnlessNode node) -> void + def visit_unless_node: (UnlessNode node) -> void + + # : (UntilNode node) -> void + def visit_until_node: (UntilNode node) -> void + + # : (WhenNode node) -> void + def visit_when_node: (WhenNode node) -> void + + # : (WhileNode node) -> void + def visit_while_node: (WhileNode node) -> void + + # : (XStringNode node) -> void + def visit_x_string_node: (XStringNode node) -> void + + # : (YieldNode node) -> void + def visit_yield_node: (YieldNode node) -> void + + private + + # Compose a header for the given node. + # -- + # : (String name, node node) -> String + def inspect_node: (String name, node node) -> String + + # Compose a string representing the given inner location field. + # -- + # : (Location? location) -> String + def inspect_location: (Location? location) -> String + end +end diff --git a/sig/generated/prism/lex_compat.rbs b/sig/generated/prism/lex_compat.rbs new file mode 100644 index 0000000000..707a96b9a8 --- /dev/null +++ b/sig/generated/prism/lex_compat.rbs @@ -0,0 +1,160 @@ +# Generated from lib/prism/lex_compat.rb with RBS::Inline + +module Prism + module Translation + class Ripper + EXPR_NONE: Integer + EXPR_BEG: Integer + EXPR_MID: Integer + EXPR_END: Integer + EXPR_CLASS: Integer + EXPR_VALUE: Integer + EXPR_ARG: Integer + EXPR_CMDARG: Integer + EXPR_ENDARG: Integer + EXPR_ENDFN: Integer + + class Lexer < Ripper + class State + def self.[]: (Integer value) -> State + end + end + end + end + + # This class is responsible for lexing the source using prism and then + # converting those tokens to be compatible with Ripper. In the vast majority + # of cases, this is a one-to-one mapping of the token type. Everything else + # generally lines up. However, there are a few cases that require special + # handling. + class LexCompat + # A token produced by the Ripper lexer that Prism is replicating. + type lex_compat_token = [ [ Integer, Integer ], Symbol, String, untyped ] + + # A result class specialized for holding tokens produced by the lexer. + class Result < Prism::Result + # The list of tokens that were produced by the lexer. + attr_reader value: Array[lex_compat_token] + + # Create a new lex compat result object with the given values. + # -- + # : (Array[lex_compat_token] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize: (Array[lex_compat_token] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + + # Implement the hash pattern matching interface for Result. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + end + + # This is a mapping of prism token types to Ripper token types. This is a + # many-to-one mapping because we split up our token types, whereas Ripper + # tends to group them. + RIPPER: untyped + + # A heredoc in this case is a list of tokens that belong to the body of the + # heredoc that should be appended onto the list of tokens when the heredoc + # closes. + module Heredoc + # Heredocs that are no dash or tilde heredocs are just a list of tokens. + # We need to keep them around so that we can insert them in the correct + # order back into the token stream and set the state of the last token to + # the state that the heredoc was opened in. + class PlainHeredoc + # :nodoc: + attr_reader tokens: Array[lex_compat_token] + + # : () -> void + def initialize: () -> void + + # : (lex_compat_token token) -> void + def <<: (lex_compat_token token) -> void + + # : () -> Array[lex_compat_token] + def to_a: () -> Array[lex_compat_token] + end + + # Dash heredocs are a little more complicated. They are a list of tokens + # that need to be split on "\\\n" to mimic Ripper's behavior. We also need + # to keep track of the state that the heredoc was opened in. + class DashHeredoc + # :nodoc: + attr_reader split: bool + + attr_reader tokens: Array[lex_compat_token] + + # : (bool split) -> void + def initialize: (bool split) -> void + + # : (lex_compat_token token) -> void + def <<: (lex_compat_token token) -> void + + # : () -> Array[lex_compat_token] + def to_a: () -> Array[lex_compat_token] + end + + # Heredocs that are dedenting heredocs are a little more complicated. + # Ripper outputs on_ignored_sp tokens for the whitespace that is being + # removed from the output. prism only modifies the node itself and keeps + # the token the same. This simplifies prism, but makes comparing against + # Ripper much harder because there is a length mismatch. + # + # Fortunately, we already have to pull out the heredoc tokens in order to + # insert them into the stream in the correct order. As such, we can do + # some extra manipulation on the tokens to make them match Ripper's + # output by mirroring the dedent logic that Ripper uses. + class DedentingHeredoc + # :nodoc: + TAB_WIDTH: ::Integer + + attr_reader tokens: Array[lex_compat_token] + + attr_reader dedent_next: bool + + attr_reader dedent: Integer? + + attr_reader embexpr_balance: Integer + + @ended_on_newline: bool + + # : () -> void + def initialize: () -> void + + # As tokens are coming in, we track the minimum amount of common leading + # whitespace on plain string content tokens. This allows us to later + # remove that amount of whitespace from the beginning of each line. + # + # : (lex_compat_token token) -> void + def <<: (lex_compat_token token) -> void + + # : () -> Array[lex_compat_token] + def to_a: () -> Array[lex_compat_token] + end + + # Here we will split between the two types of heredocs and return the + # object that will store their tokens. + # -- + # : (lex_compat_token opening) -> (PlainHeredoc | DashHeredoc | DedentingHeredoc) + def self.build: (lex_compat_token opening) -> (PlainHeredoc | DashHeredoc | DedentingHeredoc) + end + + # In previous versions of Ruby, Ripper wouldn't flush the bom before the + # first token, so we had to have a hack in place to account for that. + BOM_FLUSHED: untyped + + attr_reader options: Hash[Symbol, untyped] + + @source: String + + # : (String source, **untyped options) -> void + def initialize: (String source, **untyped options) -> void + + # : () -> Result + def result: () -> Result + + private + + # : (Array[lex_compat_token] tokens, Source source, Location? data_loc, bool bom, Token? eof_token) -> Array[lex_compat_token] + def post_process_tokens: (Array[lex_compat_token] tokens, Source source, Location? data_loc, bool bom, Token? eof_token) -> Array[lex_compat_token] + end +end diff --git a/sig/generated/prism/mutation_compiler.rbs b/sig/generated/prism/mutation_compiler.rbs new file mode 100644 index 0000000000..e79f254372 --- /dev/null +++ b/sig/generated/prism/mutation_compiler.rbs @@ -0,0 +1,464 @@ +# Generated from lib/prism/mutation_compiler.rb with RBS::Inline + +module Prism + # This visitor walks through the tree and copies each node as it is being + # visited. This is useful for consumers that want to mutate the tree, as you + # can change subtrees in place without effecting the rest of the tree. + class MutationCompiler < Compiler + # : (AliasGlobalVariableNode) -> node? + def visit_alias_global_variable_node: (AliasGlobalVariableNode) -> node? + + # : (AliasMethodNode) -> node? + def visit_alias_method_node: (AliasMethodNode) -> node? + + # : (AlternationPatternNode) -> node? + def visit_alternation_pattern_node: (AlternationPatternNode) -> node? + + # : (AndNode) -> node? + def visit_and_node: (AndNode) -> node? + + # : (ArgumentsNode) -> node? + def visit_arguments_node: (ArgumentsNode) -> node? + + # : (ArrayNode) -> node? + def visit_array_node: (ArrayNode) -> node? + + # : (ArrayPatternNode) -> node? + def visit_array_pattern_node: (ArrayPatternNode) -> node? + + # : (AssocNode) -> node? + def visit_assoc_node: (AssocNode) -> node? + + # : (AssocSplatNode) -> node? + def visit_assoc_splat_node: (AssocSplatNode) -> node? + + # : (BackReferenceReadNode) -> node? + def visit_back_reference_read_node: (BackReferenceReadNode) -> node? + + # : (BeginNode) -> node? + def visit_begin_node: (BeginNode) -> node? + + # : (BlockArgumentNode) -> node? + def visit_block_argument_node: (BlockArgumentNode) -> node? + + # : (BlockLocalVariableNode) -> node? + def visit_block_local_variable_node: (BlockLocalVariableNode) -> node? + + # : (BlockNode) -> node? + def visit_block_node: (BlockNode) -> node? + + # : (BlockParameterNode) -> node? + def visit_block_parameter_node: (BlockParameterNode) -> node? + + # : (BlockParametersNode) -> node? + def visit_block_parameters_node: (BlockParametersNode) -> node? + + # : (BreakNode) -> node? + def visit_break_node: (BreakNode) -> node? + + # : (CallAndWriteNode) -> node? + def visit_call_and_write_node: (CallAndWriteNode) -> node? + + # : (CallNode) -> node? + def visit_call_node: (CallNode) -> node? + + # : (CallOperatorWriteNode) -> node? + def visit_call_operator_write_node: (CallOperatorWriteNode) -> node? + + # : (CallOrWriteNode) -> node? + def visit_call_or_write_node: (CallOrWriteNode) -> node? + + # : (CallTargetNode) -> node? + def visit_call_target_node: (CallTargetNode) -> node? + + # : (CapturePatternNode) -> node? + def visit_capture_pattern_node: (CapturePatternNode) -> node? + + # : (CaseMatchNode) -> node? + def visit_case_match_node: (CaseMatchNode) -> node? + + # : (CaseNode) -> node? + def visit_case_node: (CaseNode) -> node? + + # : (ClassNode) -> node? + def visit_class_node: (ClassNode) -> node? + + # : (ClassVariableAndWriteNode) -> node? + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode) -> node? + + # : (ClassVariableOperatorWriteNode) -> node? + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode) -> node? + + # : (ClassVariableOrWriteNode) -> node? + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode) -> node? + + # : (ClassVariableReadNode) -> node? + def visit_class_variable_read_node: (ClassVariableReadNode) -> node? + + # : (ClassVariableTargetNode) -> node? + def visit_class_variable_target_node: (ClassVariableTargetNode) -> node? + + # : (ClassVariableWriteNode) -> node? + def visit_class_variable_write_node: (ClassVariableWriteNode) -> node? + + # : (ConstantAndWriteNode) -> node? + def visit_constant_and_write_node: (ConstantAndWriteNode) -> node? + + # : (ConstantOperatorWriteNode) -> node? + def visit_constant_operator_write_node: (ConstantOperatorWriteNode) -> node? + + # : (ConstantOrWriteNode) -> node? + def visit_constant_or_write_node: (ConstantOrWriteNode) -> node? + + # : (ConstantPathAndWriteNode) -> node? + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode) -> node? + + # : (ConstantPathNode) -> node? + def visit_constant_path_node: (ConstantPathNode) -> node? + + # : (ConstantPathOperatorWriteNode) -> node? + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode) -> node? + + # : (ConstantPathOrWriteNode) -> node? + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode) -> node? + + # : (ConstantPathTargetNode) -> node? + def visit_constant_path_target_node: (ConstantPathTargetNode) -> node? + + # : (ConstantPathWriteNode) -> node? + def visit_constant_path_write_node: (ConstantPathWriteNode) -> node? + + # : (ConstantReadNode) -> node? + def visit_constant_read_node: (ConstantReadNode) -> node? + + # : (ConstantTargetNode) -> node? + def visit_constant_target_node: (ConstantTargetNode) -> node? + + # : (ConstantWriteNode) -> node? + def visit_constant_write_node: (ConstantWriteNode) -> node? + + # : (DefNode) -> node? + def visit_def_node: (DefNode) -> node? + + # : (DefinedNode) -> node? + def visit_defined_node: (DefinedNode) -> node? + + # : (ElseNode) -> node? + def visit_else_node: (ElseNode) -> node? + + # : (EmbeddedStatementsNode) -> node? + def visit_embedded_statements_node: (EmbeddedStatementsNode) -> node? + + # : (EmbeddedVariableNode) -> node? + def visit_embedded_variable_node: (EmbeddedVariableNode) -> node? + + # : (EnsureNode) -> node? + def visit_ensure_node: (EnsureNode) -> node? + + # : (FalseNode) -> node? + def visit_false_node: (FalseNode) -> node? + + # : (FindPatternNode) -> node? + def visit_find_pattern_node: (FindPatternNode) -> node? + + # : (FlipFlopNode) -> node? + def visit_flip_flop_node: (FlipFlopNode) -> node? + + # : (FloatNode) -> node? + def visit_float_node: (FloatNode) -> node? + + # : (ForNode) -> node? + def visit_for_node: (ForNode) -> node? + + # : (ForwardingArgumentsNode) -> node? + def visit_forwarding_arguments_node: (ForwardingArgumentsNode) -> node? + + # : (ForwardingParameterNode) -> node? + def visit_forwarding_parameter_node: (ForwardingParameterNode) -> node? + + # : (ForwardingSuperNode) -> node? + def visit_forwarding_super_node: (ForwardingSuperNode) -> node? + + # : (GlobalVariableAndWriteNode) -> node? + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode) -> node? + + # : (GlobalVariableOperatorWriteNode) -> node? + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode) -> node? + + # : (GlobalVariableOrWriteNode) -> node? + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode) -> node? + + # : (GlobalVariableReadNode) -> node? + def visit_global_variable_read_node: (GlobalVariableReadNode) -> node? + + # : (GlobalVariableTargetNode) -> node? + def visit_global_variable_target_node: (GlobalVariableTargetNode) -> node? + + # : (GlobalVariableWriteNode) -> node? + def visit_global_variable_write_node: (GlobalVariableWriteNode) -> node? + + # : (HashNode) -> node? + def visit_hash_node: (HashNode) -> node? + + # : (HashPatternNode) -> node? + def visit_hash_pattern_node: (HashPatternNode) -> node? + + # : (IfNode) -> node? + def visit_if_node: (IfNode) -> node? + + # : (ImaginaryNode) -> node? + def visit_imaginary_node: (ImaginaryNode) -> node? + + # : (ImplicitNode) -> node? + def visit_implicit_node: (ImplicitNode) -> node? + + # : (ImplicitRestNode) -> node? + def visit_implicit_rest_node: (ImplicitRestNode) -> node? + + # : (InNode) -> node? + def visit_in_node: (InNode) -> node? + + # : (IndexAndWriteNode) -> node? + def visit_index_and_write_node: (IndexAndWriteNode) -> node? + + # : (IndexOperatorWriteNode) -> node? + def visit_index_operator_write_node: (IndexOperatorWriteNode) -> node? + + # : (IndexOrWriteNode) -> node? + def visit_index_or_write_node: (IndexOrWriteNode) -> node? + + # : (IndexTargetNode) -> node? + def visit_index_target_node: (IndexTargetNode) -> node? + + # : (InstanceVariableAndWriteNode) -> node? + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode) -> node? + + # : (InstanceVariableOperatorWriteNode) -> node? + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode) -> node? + + # : (InstanceVariableOrWriteNode) -> node? + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode) -> node? + + # : (InstanceVariableReadNode) -> node? + def visit_instance_variable_read_node: (InstanceVariableReadNode) -> node? + + # : (InstanceVariableTargetNode) -> node? + def visit_instance_variable_target_node: (InstanceVariableTargetNode) -> node? + + # : (InstanceVariableWriteNode) -> node? + def visit_instance_variable_write_node: (InstanceVariableWriteNode) -> node? + + # : (IntegerNode) -> node? + def visit_integer_node: (IntegerNode) -> node? + + # : (InterpolatedMatchLastLineNode) -> node? + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode) -> node? + + # : (InterpolatedRegularExpressionNode) -> node? + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode) -> node? + + # : (InterpolatedStringNode) -> node? + def visit_interpolated_string_node: (InterpolatedStringNode) -> node? + + # : (InterpolatedSymbolNode) -> node? + def visit_interpolated_symbol_node: (InterpolatedSymbolNode) -> node? + + # : (InterpolatedXStringNode) -> node? + def visit_interpolated_x_string_node: (InterpolatedXStringNode) -> node? + + # : (ItLocalVariableReadNode) -> node? + def visit_it_local_variable_read_node: (ItLocalVariableReadNode) -> node? + + # : (ItParametersNode) -> node? + def visit_it_parameters_node: (ItParametersNode) -> node? + + # : (KeywordHashNode) -> node? + def visit_keyword_hash_node: (KeywordHashNode) -> node? + + # : (KeywordRestParameterNode) -> node? + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode) -> node? + + # : (LambdaNode) -> node? + def visit_lambda_node: (LambdaNode) -> node? + + # : (LocalVariableAndWriteNode) -> node? + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode) -> node? + + # : (LocalVariableOperatorWriteNode) -> node? + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode) -> node? + + # : (LocalVariableOrWriteNode) -> node? + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode) -> node? + + # : (LocalVariableReadNode) -> node? + def visit_local_variable_read_node: (LocalVariableReadNode) -> node? + + # : (LocalVariableTargetNode) -> node? + def visit_local_variable_target_node: (LocalVariableTargetNode) -> node? + + # : (LocalVariableWriteNode) -> node? + def visit_local_variable_write_node: (LocalVariableWriteNode) -> node? + + # : (MatchLastLineNode) -> node? + def visit_match_last_line_node: (MatchLastLineNode) -> node? + + # : (MatchPredicateNode) -> node? + def visit_match_predicate_node: (MatchPredicateNode) -> node? + + # : (MatchRequiredNode) -> node? + def visit_match_required_node: (MatchRequiredNode) -> node? + + # : (MatchWriteNode) -> node? + def visit_match_write_node: (MatchWriteNode) -> node? + + # : (MissingNode) -> node? + def visit_missing_node: (MissingNode) -> node? + + # : (ModuleNode) -> node? + def visit_module_node: (ModuleNode) -> node? + + # : (MultiTargetNode) -> node? + def visit_multi_target_node: (MultiTargetNode) -> node? + + # : (MultiWriteNode) -> node? + def visit_multi_write_node: (MultiWriteNode) -> node? + + # : (NextNode) -> node? + def visit_next_node: (NextNode) -> node? + + # : (NilNode) -> node? + def visit_nil_node: (NilNode) -> node? + + # : (NoBlockParameterNode) -> node? + def visit_no_block_parameter_node: (NoBlockParameterNode) -> node? + + # : (NoKeywordsParameterNode) -> node? + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode) -> node? + + # : (NumberedParametersNode) -> node? + def visit_numbered_parameters_node: (NumberedParametersNode) -> node? + + # : (NumberedReferenceReadNode) -> node? + def visit_numbered_reference_read_node: (NumberedReferenceReadNode) -> node? + + # : (OptionalKeywordParameterNode) -> node? + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode) -> node? + + # : (OptionalParameterNode) -> node? + def visit_optional_parameter_node: (OptionalParameterNode) -> node? + + # : (OrNode) -> node? + def visit_or_node: (OrNode) -> node? + + # : (ParametersNode) -> node? + def visit_parameters_node: (ParametersNode) -> node? + + # : (ParenthesesNode) -> node? + def visit_parentheses_node: (ParenthesesNode) -> node? + + # : (PinnedExpressionNode) -> node? + def visit_pinned_expression_node: (PinnedExpressionNode) -> node? + + # : (PinnedVariableNode) -> node? + def visit_pinned_variable_node: (PinnedVariableNode) -> node? + + # : (PostExecutionNode) -> node? + def visit_post_execution_node: (PostExecutionNode) -> node? + + # : (PreExecutionNode) -> node? + def visit_pre_execution_node: (PreExecutionNode) -> node? + + # : (ProgramNode) -> node? + def visit_program_node: (ProgramNode) -> node? + + # : (RangeNode) -> node? + def visit_range_node: (RangeNode) -> node? + + # : (RationalNode) -> node? + def visit_rational_node: (RationalNode) -> node? + + # : (RedoNode) -> node? + def visit_redo_node: (RedoNode) -> node? + + # : (RegularExpressionNode) -> node? + def visit_regular_expression_node: (RegularExpressionNode) -> node? + + # : (RequiredKeywordParameterNode) -> node? + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode) -> node? + + # : (RequiredParameterNode) -> node? + def visit_required_parameter_node: (RequiredParameterNode) -> node? + + # : (RescueModifierNode) -> node? + def visit_rescue_modifier_node: (RescueModifierNode) -> node? + + # : (RescueNode) -> node? + def visit_rescue_node: (RescueNode) -> node? + + # : (RestParameterNode) -> node? + def visit_rest_parameter_node: (RestParameterNode) -> node? + + # : (RetryNode) -> node? + def visit_retry_node: (RetryNode) -> node? + + # : (ReturnNode) -> node? + def visit_return_node: (ReturnNode) -> node? + + # : (SelfNode) -> node? + def visit_self_node: (SelfNode) -> node? + + # : (ShareableConstantNode) -> node? + def visit_shareable_constant_node: (ShareableConstantNode) -> node? + + # : (SingletonClassNode) -> node? + def visit_singleton_class_node: (SingletonClassNode) -> node? + + # : (SourceEncodingNode) -> node? + def visit_source_encoding_node: (SourceEncodingNode) -> node? + + # : (SourceFileNode) -> node? + def visit_source_file_node: (SourceFileNode) -> node? + + # : (SourceLineNode) -> node? + def visit_source_line_node: (SourceLineNode) -> node? + + # : (SplatNode) -> node? + def visit_splat_node: (SplatNode) -> node? + + # : (StatementsNode) -> node? + def visit_statements_node: (StatementsNode) -> node? + + # : (StringNode) -> node? + def visit_string_node: (StringNode) -> node? + + # : (SuperNode) -> node? + def visit_super_node: (SuperNode) -> node? + + # : (SymbolNode) -> node? + def visit_symbol_node: (SymbolNode) -> node? + + # : (TrueNode) -> node? + def visit_true_node: (TrueNode) -> node? + + # : (UndefNode) -> node? + def visit_undef_node: (UndefNode) -> node? + + # : (UnlessNode) -> node? + def visit_unless_node: (UnlessNode) -> node? + + # : (UntilNode) -> node? + def visit_until_node: (UntilNode) -> node? + + # : (WhenNode) -> node? + def visit_when_node: (WhenNode) -> node? + + # : (WhileNode) -> node? + def visit_while_node: (WhileNode) -> node? + + # : (XStringNode) -> node? + def visit_x_string_node: (XStringNode) -> node? + + # : (YieldNode) -> node? + def visit_yield_node: (YieldNode) -> node? + end +end diff --git a/sig/generated/prism/node.rbs b/sig/generated/prism/node.rbs new file mode 100644 index 0000000000..94b8967bd4 --- /dev/null +++ b/sig/generated/prism/node.rbs @@ -0,0 +1,20895 @@ +# Generated from lib/prism/node.rb with RBS::Inline + +module Prism + interface _Repository + def enter: (Integer node_id, Symbol field_name) -> Relocation::Entry + end + + interface _Node + def deconstruct: () -> Array[Prism::node?] + + def inspect: () -> String + end + + type node = Node & _Node + + # This represents a node in the tree. It is the parent class of all of the + # various node types. + class Node + # A pointer to the source that this node was created from. + # :stopdoc: + attr_reader source: 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: Integer + + @location: Location | Integer + + # Save this node using a saved source so that it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save: (_Repository repository) -> Relocation::Entry + + # A Location instance that represents the location of this node in the + # source. + # -- + # : () -> Location + def location: () -> Location + + # Save the location using a saved source so that it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_location: (_Repository repository) -> Relocation::Entry + + # Delegates to [`start_line`](rdoc-ref:Location#start_line) of the associated location object. + # -- + # : () -> Integer + def start_line: () -> Integer + + # Delegates to [`end_line`](rdoc-ref:Location#end_line) of the associated location object. + # -- + # : () -> Integer + def end_line: () -> Integer + + # Delegates to [`start_offset`](rdoc-ref:Location#start_offset) of the associated location object. + # -- + # : () -> Integer + def start_offset: () -> Integer + + # Delegates to [`end_offset`](rdoc-ref:Location#end_offset) of the associated location object. + # -- + # : () -> Integer + def end_offset: () -> Integer + + # Delegates to [`start_character_offset`](rdoc-ref:Location#start_character_offset) + # of the associated location object. + # -- + # : () -> Integer + def start_character_offset: () -> Integer + + # Delegates to [`end_character_offset`](rdoc-ref:Location#end_character_offset) + # of the associated location object. + # -- + # : () -> Integer + def end_character_offset: () -> Integer + + # Delegates to [`cached_start_code_units_offset`](rdoc-ref:Location#cached_start_code_units_offset) + # of the associated location object. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_start_code_units_offset: (_CodeUnitsCache cache) -> Integer + + # Delegates to [`cached_end_code_units_offset`](rdoc-ref:Location#cached_end_code_units_offset) + # of the associated location object. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_end_code_units_offset: (_CodeUnitsCache cache) -> Integer + + # Delegates to [`start_column`](rdoc-ref:Location#start_column) of the associated location object. + # -- + # : () -> Integer + def start_column: () -> Integer + + # Delegates to [`end_column`](rdoc-ref:Location#end_column) of the associated location object. + # -- + # : () -> Integer + def end_column: () -> Integer + + # Delegates to [`start_character_column`](rdoc-ref:Location#start_character_column) + # of the associated location object. + # -- + # : () -> Integer + def start_character_column: () -> Integer + + # Delegates to [`end_character_column`](rdoc-ref:Location#end_character_column) + # of the associated location object. + # -- + # : () -> Integer + def end_character_column: () -> Integer + + # Delegates to [`cached_start_code_units_column`](rdoc-ref:Location#cached_start_code_units_column) + # of the associated location object. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_start_code_units_column: (_CodeUnitsCache cache) -> Integer + + # Delegates to [`cached_end_code_units_column`](rdoc-ref:Location#cached_end_code_units_column) + # of the associated location object. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_end_code_units_column: (_CodeUnitsCache cache) -> Integer + + # Delegates to [`leading_comments`](rdoc-ref:Location#leading_comments) of the associated location object. + # -- + # : () -> Array[Comment] + def leading_comments: () -> Array[Comment] + + # Delegates to [`trailing_comments`](rdoc-ref:Location#trailing_comments) of the associated location object. + # -- + # : () -> Array[Comment] + def trailing_comments: () -> Array[Comment] + + # Delegates to [`comments`](rdoc-ref:Location#comments) of the associated location object. + # -- + # : () -> Array[Comment] + def comments: () -> Array[Comment] + + # Returns all of the lines of the source code associated with this node. + # -- + # : () -> Array[String] + def source_lines: () -> Array[String] + + # An alias for source_lines, used to mimic the API from + # RubyVM::AbstractSyntaxTree to make it easier to migrate. + alias script_lines source_lines + + # Slice the location of the node from the source. + # -- + # : () -> String + def slice: () -> String + + # Slice the location of the node from the source, starting at the beginning + # of the line that the location starts on, ending at the end of the line + # that the location ends on. + # -- + # : () -> String + def slice_lines: () -> String + + # An bitset of flags for this node. There are certain flags that are common + # for all nodes, and then some nodes have specific flags. + # :stopdoc: + attr_reader flags: Integer + + # Returns true if the node has the newline flag set. + # -- + # : () -> bool + def newline?: () -> bool + + # Returns true if the node has the static literal flag set. + # -- + # : () -> bool + def static_literal?: () -> bool + + # Similar to inspect, but respects the current level of indentation given by + # the pretty print object. + # -- + # : (PP q) -> void + def pretty_print: (PP q) -> void + + # Convert this node into a graphviz dot graph string. + # -- + # : () -> String + def to_dot: () -> String + + # Returns a list of nodes that are descendants of this node that contain the + # given line and column. This is useful for locating a node that is selected + # based on the line and column of the source code. + # + # Important to note is that the column given to this method should be in + # bytes, as opposed to characters or code units. + # -- + # : (Integer line, Integer column) -> Array[node] + def tunnel: (Integer line, Integer column) -> Array[node] + + # Returns the first node that matches the given block when visited in a + # breadth-first search. This is useful for finding a node that matches a + # particular condition. + # + # node.breadth_first_search { |node| node.node_id == node_id } + # -- + # : () { (node) -> bool } -> node? + def breadth_first_search: () { (node) -> bool } -> node? + + alias find breadth_first_search + + # Returns all of the nodes that match the given block when visited in a + # breadth-first search. This is useful for finding all nodes that match a + # particular condition. + # + # node.breadth_first_search_all { |node| node.is_a?(Prism::CallNode) } + # -- + # : () { (node) -> bool } -> Array[node] + def breadth_first_search_all: () { (node) -> bool } -> Array[node] + + alias find_all breadth_first_search_all + + # 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. + # -- + # : () -> Array[Reflection::Field] + def self.fields: () -> Array[Reflection::Field] + + # Accepts a visitor and calls back into the specialized visit function. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # Returns an array of child nodes, including `nil`s in the place of optional + # nodes that were not present. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + alias deconstruct child_nodes + + # With a block given, yields each child node. Without a block, returns + # an enumerator that contains each child node. Excludes any `nil`s in + # the place of optional nodes that were not present. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # Returns an array of child nodes, excluding any `nil`s in the place of + # optional nodes that were not present. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # Returns an array of child nodes and locations that could potentially have + # comments attached to them. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # Returns a string representation of the node. + # -- + # : () -> String + def inspect: () -> String + + # 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. + # -- + # : () -> Symbol + def type: () -> Symbol + + # 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. + # -- + # : () -> Symbol + def self.type: () -> Symbol + end + + # Represents the use of the `alias` keyword to alias a global variable. + # + # alias $foo $bar + # ^^^^^^^^^^^^^^^ + class AliasGlobalVariableNode < Node + @keyword_loc: Location + + @old_name: GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode + + @new_name: GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode + + # Initialize a new AliasGlobalVariableNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) new_name, (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode) old_name, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode new_name, GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode old_name, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> AliasGlobalVariableNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode), ?old_name: (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode), ?keyword_loc: Location) -> AliasGlobalVariableNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode, ?old_name: GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode, ?keyword_loc: Location) -> AliasGlobalVariableNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :alias_global_variable_node + def type: () -> :alias_global_variable_node + + # See `Node.type`. + # -- + # : () -> :alias_global_variable_node + def self.type: () -> :alias_global_variable_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # new_name -> GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode + # + # Represents the new name of the global variable that can be used after aliasing. + # + # alias $foo $bar + # ^^^^ + # -- + # : () -> (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) + def new_name: () -> (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) + + # :call-seq: + # old_name -> GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode + # + # Represents the old name of the global variable that can be used before aliasing. + # + # alias $foo $bar + # ^^^^ + # -- + # : () -> (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode) + def old_name: () -> (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode) + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # The Location of the `alias` keyword. + # + # alias $foo $bar + # ^^^^^ + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `alias` keyword to alias a method. + # + # alias foo bar + # ^^^^^^^^^^^^^ + class AliasMethodNode < Node + @keyword_loc: Location + + @old_name: SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode + + @new_name: SymbolNode | InterpolatedSymbolNode + + # Initialize a new AliasMethodNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (SymbolNode | InterpolatedSymbolNode) new_name, (SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode) old_name, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, SymbolNode | InterpolatedSymbolNode new_name, SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode old_name, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> AliasMethodNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: (SymbolNode | InterpolatedSymbolNode), ?old_name: (SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode), ?keyword_loc: Location) -> AliasMethodNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: SymbolNode | InterpolatedSymbolNode, ?old_name: SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode, ?keyword_loc: Location) -> AliasMethodNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :alias_method_node + def type: () -> :alias_method_node + + # See `Node.type`. + # -- + # : () -> :alias_method_node + def self.type: () -> :alias_method_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # new_name -> SymbolNode | InterpolatedSymbolNode + # + # Represents the new name of the method that will be aliased. + # + # alias foo bar + # ^^^ + # + # alias :foo :bar + # ^^^^ + # + # alias :"#{foo}" :"#{bar}" + # ^^^^^^^^^ + # -- + # : () -> (SymbolNode | InterpolatedSymbolNode) + def new_name: () -> (SymbolNode | InterpolatedSymbolNode) + + # :call-seq: + # old_name -> SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode + # + # Represents the old name of the method that will be aliased. + # + # alias foo bar + # ^^^ + # + # alias :foo :bar + # ^^^^ + # + # alias :"#{foo}" :"#{bar}" + # ^^^^^^^^^ + # -- + # : () -> (SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode) + def old_name: () -> (SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode) + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Represents the Location of the `alias` keyword. + # + # alias foo bar + # ^^^^^ + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an alternation pattern in pattern matching. + # + # foo => bar | baz + # ^^^^^^^^^ + class AlternationPatternNode < Node + @operator_loc: Location + + @right: Prism::node + + @left: Prism::node + + # Initialize a new AlternationPatternNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node left, Prism::node right, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node left, Prism::node right, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> AlternationPatternNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AlternationPatternNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AlternationPatternNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :alternation_pattern_node + def type: () -> :alternation_pattern_node + + # See `Node.type`. + # -- + # : () -> :alternation_pattern_node + def self.type: () -> :alternation_pattern_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # left -> Node + # + # Represents the left side of the expression. + # + # foo => bar | baz + # ^^^ + # -- + # : () -> Prism::node + def left: () -> Prism::node + + # :call-seq: + # right -> Node + # + # Represents the right side of the expression. + # + # foo => bar | baz + # ^^^ + # -- + # : () -> Prism::node + def right: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Represents the alternation operator Location. + # + # foo => bar | baz + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `&&` operator or the `and` keyword. + # + # left and right + # ^^^^^^^^^^^^^^ + class AndNode < Node + @operator_loc: Location + + @right: Prism::node + + @left: Prism::node + + # Initialize a new AndNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node left, Prism::node right, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node left, Prism::node right, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> AndNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AndNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AndNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :and_node + def type: () -> :and_node + + # See `Node.type`. + # -- + # : () -> :and_node + def self.type: () -> :and_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # left -> Node + # + # 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). + # + # left and right + # ^^^^ + # + # 1 && 2 + # ^ + # -- + # : () -> Prism::node + def left: () -> Prism::node + + # :call-seq: + # right -> Node + # + # Represents the right side of the expression. + # + # left && right + # ^^^^^ + # + # 1 and 2 + # ^ + # -- + # : () -> Prism::node + def right: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `and` keyword or the `&&` operator. + # + # left and right + # ^^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a set of arguments to a method or a keyword. + # + # return foo, bar, baz + # ^^^^^^^^^^^^^ + class ArgumentsNode < Node + @arguments: Array[Prism::node] + + # Initialize a new ArgumentsNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Prism::node] arguments) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Prism::node] arguments) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ArgumentsNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: Array[Prism::node]) -> ArgumentsNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: Array[Prism::node]) -> ArgumentsNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :arguments_node + def type: () -> :arguments_node + + # See `Node.type`. + # -- + # : () -> :arguments_node + def self.type: () -> :arguments_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # if the arguments contain forwarding + # -- + # : () -> bool + def contains_forwarding?: () -> bool + + # :category: Flags + # if the arguments contain keywords + # -- + # : () -> bool + def contains_keywords?: () -> bool + + # :category: Flags + # if the arguments contain a keyword splat + # -- + # : () -> bool + def contains_keyword_splat?: () -> bool + + # :category: Flags + # if the arguments contain a splat + # -- + # : () -> bool + def contains_splat?: () -> bool + + # :category: Flags + # if the arguments contain multiple splats + # -- + # : () -> bool + def contains_multiple_splats?: () -> bool + + # :call-seq: + # arguments -> Array[Node] + # + # The list of arguments, if present. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo(bar, baz) + # ^^^^^^^^ + # -- + # : () -> Array[Prism::node] + def arguments: () -> Array[Prism::node] + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an array literal. This can be a regular array using brackets or a special array using % like %w or %i. + # + # [1, 2, 3] + # ^^^^^^^^^ + class ArrayNode < Node + @closing_loc: Location? + + @opening_loc: Location? + + @elements: Array[Prism::node] + + # Initialize a new ArrayNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Prism::node] elements, Location? opening_loc, Location? closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Prism::node] elements, Location? opening_loc, Location? closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ArrayNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :array_node + def type: () -> :array_node + + # See `Node.type`. + # -- + # : () -> :array_node + def self.type: () -> :array_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # if array contains splat nodes + # -- + # : () -> bool + def contains_splat?: () -> bool + + # :call-seq: + # elements -> Array[Node] + # + # 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. + # -- + # : () -> Array[Prism::node] + def elements: () -> Array[Prism::node] + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Represents the optional source Location for the opening token. + # + # [1,2,3] # "[" + # %w[foo bar baz] # "%w[" + # %I(apple orange banana) # "%I(" + # foo = 1, 2, 3 # nil + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Represents the optional source Location for the closing token. + # + # [1,2,3] # "]" + # %w[foo bar baz] # "]" + # %I(apple orange banana) # ")" + # foo = 1, 2, 3 # nil + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an array pattern in pattern matching. + # + # foo in 1, 2 + # ^^^^ + # + # foo in [1, 2] + # ^^^^^^ + # + # foo in *bar + # ^^^^ + # + # foo in Bar[] + # ^^^^^ + # + # foo in Bar[1, 2, 3] + # ^^^^^^^^^^^^ + class ArrayPatternNode < Node + @closing_loc: Location? + + @opening_loc: Location? + + @posts: Array[Prism::node] + + @rest: Prism::node? + + @requireds: Array[Prism::node] + + @constant: (ConstantPathNode | ConstantReadNode)? + + # Initialize a new ArrayPatternNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (ConstantPathNode | ConstantReadNode)? constant, Array[Prism::node] requireds, Prism::node? rest, Array[Prism::node] posts, Location? opening_loc, Location? closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, (ConstantPathNode | ConstantReadNode)? constant, Array[Prism::node] requireds, Prism::node? rest, Array[Prism::node] posts, Location? opening_loc, Location? closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ArrayPatternNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?requireds: Array[Prism::node], ?rest: Prism::node?, ?posts: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayPatternNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?requireds: Array[Prism::node], ?rest: Prism::node?, ?posts: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayPatternNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :array_pattern_node + def type: () -> :array_pattern_node + + # See `Node.type`. + # -- + # : () -> :array_pattern_node + def self.type: () -> :array_pattern_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # constant -> ConstantPathNode | ConstantReadNode | nil + # + # Represents the optional constant preceding the Array + # + # foo in Bar[] + # ^^^ + # + # foo in Bar[1, 2, 3] + # ^^^ + # + # foo in Bar::Baz[1, 2, 3] + # ^^^^^^^^ + # -- + # : () -> (ConstantPathNode | ConstantReadNode)? + def constant: () -> (ConstantPathNode | ConstantReadNode)? + + # :call-seq: + # requireds -> Array[Node] + # + # Represents the required elements of the array pattern. + # + # foo in [1, 2] + # ^ ^ + # -- + # : () -> Array[Prism::node] + def requireds: () -> Array[Prism::node] + + # :call-seq: + # rest -> Node | nil + # + # Represents the rest element of the array pattern. + # + # foo in *bar + # ^^^^ + # -- + # : () -> Prism::node? + def rest: () -> Prism::node? + + # :call-seq: + # posts -> Array[Node] + # + # Represents the elements after the rest element of the array pattern. + # + # foo in *bar, baz + # ^^^ + # -- + # : () -> Array[Prism::node] + def posts: () -> Array[Prism::node] + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Represents the opening Location of the array pattern. + # + # foo in [1, 2] + # ^ + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Represents the closing Location of the array pattern. + # + # foo in [1, 2] + # ^ + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a hash key/value pair. + # + # { a => b } + # ^^^^^^ + class AssocNode < Node + @operator_loc: Location? + + @value: Prism::node + + @key: Prism::node + + # Initialize a new AssocNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node key, Prism::node value, Location? operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node key, Prism::node value, Location? operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> AssocNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?key: Prism::node, ?value: Prism::node, ?operator_loc: Location?) -> AssocNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?key: Prism::node, ?value: Prism::node, ?operator_loc: Location?) -> AssocNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :assoc_node + def type: () -> :assoc_node + + # See `Node.type`. + # -- + # : () -> :assoc_node + def self.type: () -> :assoc_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # key -> Node + # + # 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). + # + # { a: b } + # ^ + # + # { foo => bar } + # ^^^ + # + # { def a; end => 1 } + # ^^^^^^^^^^ + # -- + # : () -> Prism::node + def key: () -> Prism::node + + # :call-seq: + # value -> Node + # + # 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). + # + # { foo => bar } + # ^^^ + # + # { x: 1 } + # ^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location | nil + # + # The Location of the `=>` operator, if present. + # + # { foo => bar } + # ^^ + # -- + # : () -> Location? + def operator_loc: () -> Location? + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # operator -> String | nil + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String? + def operator: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a splat in a hash literal. + # + # { **foo } + # ^^^^^ + class AssocSplatNode < Node + @operator_loc: Location + + @value: Prism::node? + + # Initialize a new AssocSplatNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? value, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? value, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> AssocSplatNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node?, ?operator_loc: Location) -> AssocSplatNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node?, ?operator_loc: Location) -> AssocSplatNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :assoc_splat_node + def type: () -> :assoc_splat_node + + # See `Node.type`. + # -- + # : () -> :assoc_splat_node + def self.type: () -> :assoc_splat_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # value -> Node | nil + # + # The value to be splatted, if present. Will be missing when keyword rest argument forwarding is used. + # + # { **foo } + # ^^^ + # -- + # : () -> Prism::node? + def value: () -> Prism::node? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `**` operator. + # + # { **x } + # ^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents reading a reference to a field in the previous match. + # + # $' + # ^^ + class BackReferenceReadNode < Node + @name: Symbol + + # Initialize a new BackReferenceReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BackReferenceReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BackReferenceReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BackReferenceReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :back_reference_read_node + def type: () -> :back_reference_read_node + + # See `Node.type`. + # -- + # : () -> :back_reference_read_node + def self.type: () -> :back_reference_read_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the back-reference variable, including the leading `$`. + # + # $& # name `:$&` + # + # $+ # name `:$+` + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a begin statement. + # + # begin + # foo + # end + # ^^^^^ + class BeginNode < Node + @end_keyword_loc: Location? + + @ensure_clause: EnsureNode? + + @else_clause: ElseNode? + + @rescue_clause: RescueNode? + + @statements: StatementsNode? + + @begin_keyword_loc: Location? + + # Initialize a new BeginNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location? begin_keyword_loc, StatementsNode? statements, RescueNode? rescue_clause, ElseNode? else_clause, EnsureNode? ensure_clause, Location? end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location? begin_keyword_loc, StatementsNode? statements, RescueNode? rescue_clause, ElseNode? else_clause, EnsureNode? ensure_clause, Location? end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BeginNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?begin_keyword_loc: Location?, ?statements: StatementsNode?, ?rescue_clause: RescueNode?, ?else_clause: ElseNode?, ?ensure_clause: EnsureNode?, ?end_keyword_loc: Location?) -> BeginNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?begin_keyword_loc: Location?, ?statements: StatementsNode?, ?rescue_clause: RescueNode?, ?else_clause: ElseNode?, ?ensure_clause: EnsureNode?, ?end_keyword_loc: Location?) -> BeginNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :begin_node + def type: () -> :begin_node + + # See `Node.type`. + # -- + # : () -> :begin_node + def self.type: () -> :begin_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # begin_keyword_loc -> Location | nil + # + # Represents the Location of the `begin` keyword. + # + # begin x end + # ^^^^^ + # -- + # : () -> Location? + def begin_keyword_loc: () -> Location? + + # :category: Repository + # Save the begin_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_begin_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # statements -> StatementsNode | nil + # + # Represents the statements within the begin block. + # + # begin x end + # ^ + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :call-seq: + # rescue_clause -> RescueNode | nil + # + # Represents the rescue clause within the begin block. + # + # begin x; rescue y; end + # ^^^^^^^^ + # -- + # : () -> RescueNode? + def rescue_clause: () -> RescueNode? + + # :call-seq: + # else_clause -> ElseNode | nil + # + # Represents the else clause within the begin block. + # + # begin x; rescue y; else z; end + # ^^^^^^^^^^^ + # -- + # : () -> ElseNode? + def else_clause: () -> ElseNode? + + # :call-seq: + # ensure_clause -> EnsureNode | nil + # + # Represents the ensure clause within the begin block. + # + # begin x; ensure y; end + # ^^^^^^^^ + # -- + # : () -> EnsureNode? + def ensure_clause: () -> EnsureNode? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location | nil + # + # Represents the Location of the `end` keyword. + # + # begin x end + # ^^^ + # -- + # : () -> Location? + def end_keyword_loc: () -> Location? + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # begin_keyword -> String | nil + # + # Slice the location of begin_keyword_loc from the source. + # -- + # : () -> String? + def begin_keyword: () -> String? + + # :call-seq: + # end_keyword -> String | nil + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String? + def end_keyword: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a block argument using `&`. + # + # bar(&args) + # ^^^^^ + class BlockArgumentNode < Node + @operator_loc: Location + + @expression: Prism::node? + + # Initialize a new BlockArgumentNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? expression, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? expression, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BlockArgumentNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node?, ?operator_loc: Location) -> BlockArgumentNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node?, ?operator_loc: Location) -> BlockArgumentNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :block_argument_node + def type: () -> :block_argument_node + + # See `Node.type`. + # -- + # : () -> :block_argument_node + def self.type: () -> :block_argument_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # expression -> Node | nil + # + # The expression that is being passed as a block argument. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo(&args) + # ^^^^ + # -- + # : () -> Prism::node? + def expression: () -> Prism::node? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Represents the Location of the `&` operator. + # + # foo(&args) + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a block local variable. + # + # a { |; b| } + # ^ + class BlockLocalVariableNode < Node + @name: Symbol + + # Initialize a new BlockLocalVariableNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BlockLocalVariableNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BlockLocalVariableNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BlockLocalVariableNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :block_local_variable_node + def type: () -> :block_local_variable_node + + # See `Node.type`. + # -- + # : () -> :block_local_variable_node + def self.type: () -> :block_local_variable_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol + # + # The name of the block local variable. + # + # a { |; b| } # name `:b` + # ^ + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a block of ruby code. + # + # [1, 2, 3].each { |i| puts x } + # ^^^^^^^^^^^^^^ + class BlockNode < Node + @closing_loc: Location + + @opening_loc: Location + + @body: (StatementsNode | BeginNode)? + + @parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)? + + @locals: Array[Symbol] + + # Initialize a new BlockNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, (BlockParametersNode | NumberedParametersNode | ItParametersNode)? parameters, (StatementsNode | BeginNode)? body, Location opening_loc, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, (BlockParametersNode | NumberedParametersNode | ItParametersNode)? parameters, (StatementsNode | BeginNode)? body, Location opening_loc, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BlockNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?, ?opening_loc: Location, ?closing_loc: Location) -> BlockNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?, ?opening_loc: Location, ?closing_loc: Location) -> BlockNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :block_node + def type: () -> :block_node + + # See `Node.type`. + # -- + # : () -> :block_node + def self.type: () -> :block_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # locals -> Array[Symbol] + # + # The local variables declared in the block. + # + # [1, 2, 3].each { |i| puts x } # locals: [:i] + # ^ + # -- + # : () -> Array[Symbol] + def locals: () -> Array[Symbol] + + # :call-seq: + # parameters -> BlockParametersNode | NumberedParametersNode | ItParametersNode | nil + # + # The parameters of the block. + # + # [1, 2, 3].each { |i| puts x } + # ^^^ + # [1, 2, 3].each { puts _1 } + # ^^^^^^^^^^^ + # [1, 2, 3].each { puts it } + # ^^^^^^^^^^^ + # -- + # : () -> (BlockParametersNode | NumberedParametersNode | ItParametersNode)? + def parameters: () -> (BlockParametersNode | NumberedParametersNode | ItParametersNode)? + + # :call-seq: + # body -> StatementsNode | BeginNode | nil + # + # The body of the block. + # + # [1, 2, 3].each { |i| puts x } + # ^^^^^^ + # -- + # : () -> (StatementsNode | BeginNode)? + def body: () -> (StatementsNode | BeginNode)? + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Represents the Location of the opening `{` or `do`. + # + # [1, 2, 3].each { |i| puts x } + # ^ + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Represents the Location of the closing `}` or `end`. + # + # [1, 2, 3].each { |i| puts x } + # ^ + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a block parameter of a method, block, or lambda definition. + # + # def a(&b) + # ^^ + # end + class BlockParameterNode < Node + @operator_loc: Location + + @name_loc: Location? + + @name: Symbol? + + # Initialize a new BlockParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol? name, Location? name_loc, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol? name, Location? name_loc, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BlockParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> BlockParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> BlockParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :block_parameter_node + def type: () -> :block_parameter_node + + # See `Node.type`. + # -- + # : () -> :block_parameter_node + def self.type: () -> :block_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol | nil + # + # The name of the block parameter. + # + # def a(&b) # name `:b` + # ^ + # end + # -- + # : () -> Symbol? + def name: () -> Symbol? + + # :category: Locations + # :call-seq: + # name_loc -> Location | nil + # + # Represents the Location of the block parameter name. + # + # def a(&b) + # ^ + # -- + # : () -> Location? + def name_loc: () -> Location? + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_name_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Represents the Location of the `&` operator. + # + # def a(&b) + # ^ + # end + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a block's parameters declaration. + # + # -> (a, b = 1; local) { } + # ^^^^^^^^^^^^^^^^^ + # + # foo do |a, b = 1; local| + # ^^^^^^^^^^^^^^^^^ + # end + class BlockParametersNode < Node + @closing_loc: Location? + + @opening_loc: Location? + + @locals: Array[BlockLocalVariableNode] + + @parameters: ParametersNode? + + # Initialize a new BlockParametersNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ParametersNode? parameters, Array[BlockLocalVariableNode] locals, Location? opening_loc, Location? closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ParametersNode? parameters, Array[BlockLocalVariableNode] locals, Location? opening_loc, Location? closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BlockParametersNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?parameters: ParametersNode?, ?locals: Array[BlockLocalVariableNode], ?opening_loc: Location?, ?closing_loc: Location?) -> BlockParametersNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?parameters: ParametersNode?, ?locals: Array[BlockLocalVariableNode], ?opening_loc: Location?, ?closing_loc: Location?) -> BlockParametersNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :block_parameters_node + def type: () -> :block_parameters_node + + # See `Node.type`. + # -- + # : () -> :block_parameters_node + def self.type: () -> :block_parameters_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # parameters -> ParametersNode | nil + # + # Represents the parameters of the block. + # + # -> (a, b = 1; local) { } + # ^^^^^^^^ + # + # foo do |a, b = 1; local| + # ^^^^^^^^ + # end + # -- + # : () -> ParametersNode? + def parameters: () -> ParametersNode? + + # :call-seq: + # locals -> Array[BlockLocalVariableNode] + # + # Represents the local variables of the block. + # + # -> (a, b = 1; local) { } + # ^^^^^ + # + # foo do |a, b = 1; local| + # ^^^^^ + # end + # -- + # : () -> Array[BlockLocalVariableNode] + def locals: () -> Array[BlockLocalVariableNode] + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Represents the opening Location of the block parameters. + # + # -> (a, b = 1; local) { } + # ^ + # + # foo do |a, b = 1; local| + # ^ + # end + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Represents the closing Location of the block parameters. + # + # -> (a, b = 1; local) { } + # ^ + # + # foo do |a, b = 1; local| + # ^ + # end + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `break` keyword. + # + # break foo + # ^^^^^^^^^ + class BreakNode < Node + @keyword_loc: Location + + @arguments: ArgumentsNode? + + # Initialize a new BreakNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ArgumentsNode? arguments, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ArgumentsNode? arguments, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BreakNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> BreakNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> BreakNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :break_node + def type: () -> :break_node + + # See `Node.type`. + # -- + # : () -> :break_node + def self.type: () -> :break_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # The arguments to the break statement, if present. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # break foo + # ^^^ + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # The Location of the `break` keyword. + # + # break foo + # ^^^^^ + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `&&=` operator on a call. + # + # foo.bar &&= value + # ^^^^^^^^^^^^^^^^^ + class CallAndWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @write_name: Symbol + + @read_name: Symbol + + @message_loc: Location? + + @call_operator_loc: Location? + + @receiver: Prism::node? + + # Initialize a new CallAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location? message_loc, Symbol read_name, Symbol write_name, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location? message_loc, Symbol read_name, Symbol write_name, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CallAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :call_and_write_node + def type: () -> :call_and_write_node + + # See `Node.type`. + # -- + # : () -> :call_and_write_node + def self.type: () -> :call_and_write_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node | nil + # + # 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). + # + # foo.bar &&= value + # ^^^ + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location | nil + # + # Represents the Location of the call operator. + # + # foo.bar &&= value + # ^ + # -- + # : () -> Location? + def call_operator_loc: () -> Location? + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # message_loc -> Location | nil + # + # Represents the Location of the message. + # + # foo.bar &&= value + # ^^^ + # -- + # : () -> Location? + def message_loc: () -> Location? + + # :category: Repository + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_message_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # read_name -> Symbol + # + # Represents the name of the method being called. + # + # foo.bar &&= value # read_name `:bar` + # ^^^ + # -- + # : () -> Symbol + def read_name: () -> Symbol + + # :call-seq: + # write_name -> Symbol + # + # Represents the name of the method being written to. + # + # foo.bar &&= value # write_name `:bar=` + # ^^^ + # -- + # : () -> Symbol + def write_name: () -> Symbol + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Represents the Location of the operator. + # + # foo.bar &&= value + # ^^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Represents the value being assigned. + # + # foo.bar &&= value + # ^^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # call_operator -> String | nil + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String? + def call_operator: () -> String? + + # :call-seq: + # message -> String | nil + # + # Slice the location of message_loc from the source. + # -- + # : () -> String? + def message: () -> String? + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a method call, in all of the various forms that can take. + # + # foo + # ^^^ + # + # foo() + # ^^^^^ + # + # +foo + # ^^^^ + # + # foo + bar + # ^^^^^^^^^ + # + # foo.bar + # ^^^^^^^ + # + # foo&.bar + # ^^^^^^^^ + class CallNode < Node + @block: (BlockNode | BlockArgumentNode)? + + @equal_loc: Location? + + @closing_loc: Location? + + @arguments: ArgumentsNode? + + @opening_loc: Location? + + @message_loc: Location? + + @name: Symbol + + @call_operator_loc: Location? + + @receiver: Prism::node? + + # Initialize a new CallNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Symbol name, Location? message_loc, Location? opening_loc, ArgumentsNode? arguments, Location? closing_loc, Location? equal_loc, (BlockNode | BlockArgumentNode)? block) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Symbol name, Location? message_loc, Location? opening_loc, ArgumentsNode? arguments, Location? closing_loc, Location? equal_loc, (BlockNode | BlockArgumentNode)? block) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CallNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?name: Symbol, ?message_loc: Location?, ?opening_loc: Location?, ?arguments: ArgumentsNode?, ?closing_loc: Location?, ?equal_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> CallNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?name: Symbol, ?message_loc: Location?, ?opening_loc: Location?, ?arguments: ArgumentsNode?, ?closing_loc: Location?, ?equal_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> CallNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :call_node + def type: () -> :call_node + + # See `Node.type`. + # -- + # : () -> :call_node + def self.type: () -> :call_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node | nil + # + # 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). + # + # foo.bar + # ^^^ + # + # +foo + # ^^^ + # + # foo + bar + # ^^^ + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location | nil + # + # Represents the Location of the call operator. + # + # foo.bar + # ^ + # + # foo&.bar + # ^^ + # -- + # : () -> Location? + def call_operator_loc: () -> Location? + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # name -> Symbol + # + # Represents the name of the method being called. + # + # foo.bar # name `:foo` + # ^^^ + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # message_loc -> Location | nil + # + # Represents the Location of the message. + # + # foo.bar + # ^^^ + # -- + # : () -> Location? + def message_loc: () -> Location? + + # :category: Repository + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_message_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Represents the Location of the left parenthesis. + # + # foo(bar) + # ^ + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Represents the arguments to the method call. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo(bar) + # ^^^ + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Represents the Location of the right parenthesis. + # + # foo(bar) + # ^ + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # equal_loc -> Location | nil + # + # Represents the Location of the equal sign, in the case that this is an attribute write. + # + # foo.bar = value + # ^ + # + # foo[bar] = value + # ^ + # -- + # : () -> Location? + def equal_loc: () -> Location? + + # :category: Repository + # Save the equal_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_equal_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # block -> BlockNode | BlockArgumentNode | nil + # + # Represents the block that is being passed to the method. + # + # foo { |a| a } + # ^^^^^^^^^ + # -- + # : () -> (BlockNode | BlockArgumentNode)? + def block: () -> (BlockNode | BlockArgumentNode)? + + # :call-seq: + # call_operator -> String | nil + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String? + def call_operator: () -> String? + + # :call-seq: + # message -> String | nil + # + # Slice the location of message_loc from the source. + # -- + # : () -> String? + def message: () -> String? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # :call-seq: + # equal -> String | nil + # + # Slice the location of equal_loc from the source. + # -- + # : () -> String? + def equal: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of an assignment operator on a call. + # + # foo.bar += baz + # ^^^^^^^^^^^^^^ + class CallOperatorWriteNode < Node + @value: Prism::node + + @binary_operator_loc: Location + + @binary_operator: Symbol + + @write_name: Symbol + + @read_name: Symbol + + @message_loc: Location? + + @call_operator_loc: Location? + + @receiver: Prism::node? + + # Initialize a new CallOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location? message_loc, Symbol read_name, Symbol write_name, Symbol binary_operator, Location binary_operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location? message_loc, Symbol read_name, Symbol write_name, Symbol binary_operator, Location binary_operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CallOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> CallOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> CallOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :call_operator_write_node + def type: () -> :call_operator_write_node + + # See `Node.type`. + # -- + # : () -> :call_operator_write_node + def self.type: () -> :call_operator_write_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node | nil + # + # The object that the method is being called on. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar += value + # ^^^ + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location | nil + # + # Represents the Location of the call operator. + # + # foo.bar += value + # ^ + # -- + # : () -> Location? + def call_operator_loc: () -> Location? + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # message_loc -> Location | nil + # + # Represents the Location of the message. + # + # foo.bar += value + # ^^^ + # -- + # : () -> Location? + def message_loc: () -> Location? + + # :category: Repository + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_message_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # read_name -> Symbol + # + # Represents the name of the method being called. + # + # foo.bar += value # read_name `:bar` + # ^^^ + # -- + # : () -> Symbol + def read_name: () -> Symbol + + # :call-seq: + # write_name -> Symbol + # + # Represents the name of the method being written to. + # + # foo.bar += value # write_name `:bar=` + # ^^^ + # -- + # : () -> Symbol + def write_name: () -> Symbol + + # :call-seq: + # binary_operator -> Symbol + # + # Represents the binary operator being used. + # + # foo.bar += value # binary_operator `:+` + # ^ + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Represents the Location of the binary operator. + # + # foo.bar += value + # ^^ + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Represents the value being assigned. + # + # foo.bar += value + # ^^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # call_operator -> String | nil + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String? + def call_operator: () -> String? + + # :call-seq: + # message -> String | nil + # + # Slice the location of message_loc from the source. + # -- + # : () -> String? + def message: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `||=` operator on a call. + # + # foo.bar ||= value + # ^^^^^^^^^^^^^^^^^ + class CallOrWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @write_name: Symbol + + @read_name: Symbol + + @message_loc: Location? + + @call_operator_loc: Location? + + @receiver: Prism::node? + + # Initialize a new CallOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location? message_loc, Symbol read_name, Symbol write_name, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location? message_loc, Symbol read_name, Symbol write_name, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CallOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :call_or_write_node + def type: () -> :call_or_write_node + + # See `Node.type`. + # -- + # : () -> :call_or_write_node + def self.type: () -> :call_or_write_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node | nil + # + # The object that the method is being called on. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar ||= value + # ^^^ + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location | nil + # + # Represents the Location of the call operator. + # + # foo.bar ||= value + # ^ + # -- + # : () -> Location? + def call_operator_loc: () -> Location? + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # message_loc -> Location | nil + # + # Represents the Location of the message. + # + # foo.bar ||= value + # ^^^ + # -- + # : () -> Location? + def message_loc: () -> Location? + + # :category: Repository + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_message_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # read_name -> Symbol + # + # Represents the name of the method being called. + # + # foo.bar ||= value # read_name `:bar` + # ^^^ + # -- + # : () -> Symbol + def read_name: () -> Symbol + + # :call-seq: + # write_name -> Symbol + # + # Represents the name of the method being written to. + # + # foo.bar ||= value # write_name `:bar=` + # ^^^ + # -- + # : () -> Symbol + def write_name: () -> Symbol + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Represents the Location of the operator. + # + # foo.bar ||= value + # ^^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Represents the value being assigned. + # + # foo.bar ||= value + # ^^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # call_operator -> String | nil + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String? + def call_operator: () -> String? + + # :call-seq: + # message -> String | nil + # + # Slice the location of message_loc from the source. + # -- + # : () -> String? + def message: () -> String? + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents assigning to a method call. + # + # foo.bar, = 1 + # ^^^^^^^ + # + # begin + # rescue => foo.bar + # ^^^^^^^ + # end + # + # for foo.bar in baz do end + # ^^^^^^^ + class CallTargetNode < Node + @message_loc: Location + + @name: Symbol + + @call_operator_loc: Location + + @receiver: Prism::node + + # Initialize a new CallTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node receiver, Location call_operator_loc, Symbol name, Location message_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node receiver, Location call_operator_loc, Symbol name, Location message_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CallTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?call_operator_loc: Location, ?name: Symbol, ?message_loc: Location) -> CallTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?call_operator_loc: Location, ?name: Symbol, ?message_loc: Location) -> CallTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :call_target_node + def type: () -> :call_target_node + + # See `Node.type`. + # -- + # : () -> :call_target_node + def self.type: () -> :call_target_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node + # + # The object that the method is being called on. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar = 1 + # ^^^ + # -- + # : () -> Prism::node + def receiver: () -> Prism::node + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location + # + # Represents the Location of the call operator. + # + # foo.bar = 1 + # ^ + # -- + # : () -> Location + def call_operator_loc: () -> Location + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # name -> Symbol + # + # Represents the name of the method being called. + # + # foo.bar = 1 # name `:foo` + # ^^^ + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # message_loc -> Location + # + # Represents the Location of the message. + # + # foo.bar = 1 + # ^^^ + # -- + # : () -> Location + def message_loc: () -> Location + + # :category: Repository + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_message_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # call_operator -> String + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String + def call_operator: () -> String + + # :call-seq: + # message -> String + # + # Slice the location of message_loc from the source. + # -- + # : () -> String + def message: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents assigning to a local variable in pattern matching. + # + # foo => [bar => baz] + # ^^^^^^^^^^ + class CapturePatternNode < Node + @operator_loc: Location + + @target: LocalVariableTargetNode + + @value: Prism::node + + # Initialize a new CapturePatternNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node value, LocalVariableTargetNode target, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node value, LocalVariableTargetNode target, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CapturePatternNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?target: LocalVariableTargetNode, ?operator_loc: Location) -> CapturePatternNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?target: LocalVariableTargetNode, ?operator_loc: Location) -> CapturePatternNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :capture_pattern_node + def type: () -> :capture_pattern_node + + # See `Node.type`. + # -- + # : () -> :capture_pattern_node + def self.type: () -> :capture_pattern_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # value -> Node + # + # Represents the value to capture. + # + # foo => bar + # ^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # target -> LocalVariableTargetNode + # + # Represents the target of the capture. + # + # foo => bar + # ^^^ + # -- + # : () -> LocalVariableTargetNode + def target: () -> LocalVariableTargetNode + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Represents the Location of the `=>` operator. + # + # foo => bar + # ^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of a case statement for pattern matching. + # + # case true + # in false + # end + # ^^^^^^^^^ + class CaseMatchNode < Node + @end_keyword_loc: Location + + @case_keyword_loc: Location + + @else_clause: ElseNode? + + @conditions: Array[InNode] + + @predicate: Prism::node? + + # Initialize a new CaseMatchNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? predicate, Array[InNode] conditions, ElseNode? else_clause, Location case_keyword_loc, Location end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? predicate, Array[InNode] conditions, ElseNode? else_clause, Location case_keyword_loc, Location end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CaseMatchNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[InNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseMatchNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[InNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseMatchNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :case_match_node + def type: () -> :case_match_node + + # See `Node.type`. + # -- + # : () -> :case_match_node + def self.type: () -> :case_match_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # predicate -> Node | nil + # + # Represents the predicate of the case match. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # case true; in false; end + # ^^^^ + # -- + # : () -> Prism::node? + def predicate: () -> Prism::node? + + # :call-seq: + # conditions -> Array[InNode] + # + # Represents the conditions of the case match. + # + # case true; in false; end + # ^^^^^^^^ + # -- + # : () -> Array[InNode] + def conditions: () -> Array[InNode] + + # :call-seq: + # else_clause -> ElseNode | nil + # + # Represents the else clause of the case match. + # + # case true; in false; else; end + # ^^^^^^^^^ + # -- + # : () -> ElseNode? + def else_clause: () -> ElseNode? + + # :category: Locations + # :call-seq: + # case_keyword_loc -> Location + # + # Represents the Location of the `case` keyword. + # + # case true; in false; end + # ^^^^ + # -- + # : () -> Location + def case_keyword_loc: () -> Location + + # :category: Repository + # Save the case_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_case_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location + # + # Represents the Location of the `end` keyword. + # + # case true; in false; end + # ^^^ + # -- + # : () -> Location + def end_keyword_loc: () -> Location + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # case_keyword -> String + # + # Slice the location of case_keyword_loc from the source. + # -- + # : () -> String + def case_keyword: () -> String + + # :call-seq: + # end_keyword -> String + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String + def end_keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of a case statement. + # + # case true + # when false + # end + # ^^^^^^^^^^ + class CaseNode < Node + @end_keyword_loc: Location + + @case_keyword_loc: Location + + @else_clause: ElseNode? + + @conditions: Array[WhenNode] + + @predicate: Prism::node? + + # Initialize a new CaseNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? predicate, Array[WhenNode] conditions, ElseNode? else_clause, Location case_keyword_loc, Location end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? predicate, Array[WhenNode] conditions, ElseNode? else_clause, Location case_keyword_loc, Location end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CaseNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[WhenNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[WhenNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :case_node + def type: () -> :case_node + + # See `Node.type`. + # -- + # : () -> :case_node + def self.type: () -> :case_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # predicate -> Node | nil + # + # Represents the predicate of the case statement. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # case true; when false; end + # ^^^^ + # -- + # : () -> Prism::node? + def predicate: () -> Prism::node? + + # :call-seq: + # conditions -> Array[WhenNode] + # + # Represents the conditions of the case statement. + # + # case true; when false; end + # ^^^^^^^^^^ + # -- + # : () -> Array[WhenNode] + def conditions: () -> Array[WhenNode] + + # :call-seq: + # else_clause -> ElseNode | nil + # + # Represents the else clause of the case statement. + # + # case true; when false; else; end + # ^^^^^^^^^ + # -- + # : () -> ElseNode? + def else_clause: () -> ElseNode? + + # :category: Locations + # :call-seq: + # case_keyword_loc -> Location + # + # Represents the Location of the `case` keyword. + # + # case true; when false; end + # ^^^^ + # -- + # : () -> Location + def case_keyword_loc: () -> Location + + # :category: Repository + # Save the case_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_case_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location + # + # Represents the Location of the `end` keyword. + # + # case true; when false; end + # ^^^ + # -- + # : () -> Location + def end_keyword_loc: () -> Location + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # case_keyword -> String + # + # Slice the location of case_keyword_loc from the source. + # -- + # : () -> String + def case_keyword: () -> String + + # :call-seq: + # end_keyword -> String + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String + def end_keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a class declaration involving the `class` keyword. + # + # class Foo end + # ^^^^^^^^^^^^^ + class ClassNode < Node + @name: Symbol + + @end_keyword_loc: Location + + @body: (StatementsNode | BeginNode)? + + @superclass: Prism::node? + + @inheritance_operator_loc: Location? + + @constant_path: ConstantReadNode | ConstantPathNode | CallNode + + @class_keyword_loc: Location + + @locals: Array[Symbol] + + # Initialize a new ClassNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location class_keyword_loc, (ConstantReadNode | ConstantPathNode | CallNode) constant_path, Location? inheritance_operator_loc, Prism::node? superclass, (StatementsNode | BeginNode)? body, Location end_keyword_loc, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location class_keyword_loc, ConstantReadNode | ConstantPathNode | CallNode constant_path, Location? inheritance_operator_loc, Prism::node? superclass, (StatementsNode | BeginNode)? body, Location end_keyword_loc, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ClassNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?constant_path: (ConstantReadNode | ConstantPathNode | CallNode), ?inheritance_operator_loc: Location?, ?superclass: Prism::node?, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ClassNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?constant_path: ConstantReadNode | ConstantPathNode | CallNode, ?inheritance_operator_loc: Location?, ?superclass: Prism::node?, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ClassNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :class_node + def type: () -> :class_node + + # See `Node.type`. + # -- + # : () -> :class_node + def self.type: () -> :class_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # locals -> Array[Symbol] + # + # Returns the `locals` attribute. + # -- + # : () -> Array[Symbol] + def locals: () -> Array[Symbol] + + # :category: Locations + # :call-seq: + # class_keyword_loc -> Location + # + # Represents the Location of the `class` keyword. + # + # class Foo end + # ^^^^^ + # -- + # : () -> Location + def class_keyword_loc: () -> Location + + # :category: Repository + # Save the class_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_class_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # constant_path -> ConstantReadNode | ConstantPathNode | CallNode + # + # Returns the `constant_path` attribute. + # -- + # : () -> (ConstantReadNode | ConstantPathNode | CallNode) + def constant_path: () -> (ConstantReadNode | ConstantPathNode | CallNode) + + # :category: Locations + # :call-seq: + # inheritance_operator_loc -> Location | nil + # + # Represents the Location of the `<` operator. + # + # class Foo < Bar + # ^ + # -- + # : () -> Location? + def inheritance_operator_loc: () -> Location? + + # :category: Repository + # Save the inheritance_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_inheritance_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # superclass -> Node | nil + # + # Represents the superclass of the class. + # + # class Foo < Bar + # ^^^ + # -- + # : () -> Prism::node? + def superclass: () -> Prism::node? + + # :call-seq: + # body -> StatementsNode | BeginNode | nil + # + # Represents the body of the class. + # + # class Foo; bar; end + # ^^^ + # -- + # : () -> (StatementsNode | BeginNode)? + def body: () -> (StatementsNode | BeginNode)? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location + # + # Represents the Location of the `end` keyword. + # + # class Foo end + # ^^^ + # -- + # : () -> Location + def end_keyword_loc: () -> Location + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # name -> Symbol + # + # The name of the class. + # + # class Foo end # name `:Foo` + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # class_keyword -> String + # + # Slice the location of class_keyword_loc from the source. + # -- + # : () -> String + def class_keyword: () -> String + + # :call-seq: + # inheritance_operator -> String | nil + # + # Slice the location of inheritance_operator_loc from the source. + # -- + # : () -> String? + def inheritance_operator: () -> String? + + # :call-seq: + # end_keyword -> String + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String + def end_keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `&&=` operator for assignment to a class variable. + # + # @@target &&= value + # ^^^^^^^^^^^^^^^^^^ + class ClassVariableAndWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new ClassVariableAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ClassVariableAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :class_variable_and_write_node + def type: () -> :class_variable_and_write_node + + # See `Node.type`. + # -- + # : () -> :class_variable_and_write_node + def self.type: () -> :class_variable_and_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @@target &&= value # name `:@@target` + # ^^^^^^^^ + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Represents the Location of the variable name. + # + # @@target &&= value + # ^^^^^^^^ + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Represents the Location of the `&&=` operator. + # + # @@target &&= value + # ^^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Represents the value being assigned. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # @@target &&= value + # ^^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents assigning to a class variable using an operator that isn't `=`. + # + # @@target += value + # ^^^^^^^^^^^^^^^^^ + class ClassVariableOperatorWriteNode < Node + @binary_operator: Symbol + + @value: Prism::node + + @binary_operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new ClassVariableOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ClassVariableOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ClassVariableOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ClassVariableOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :class_variable_operator_write_node + def type: () -> :class_variable_operator_write_node + + # See `Node.type`. + # -- + # : () -> :class_variable_operator_write_node + def self.type: () -> :class_variable_operator_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Returns the Location represented by `binary_operator_loc`. + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # binary_operator -> Symbol + # + # Returns the `binary_operator` attribute. + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `||=` operator for assignment to a class variable. + # + # @@target ||= value + # ^^^^^^^^^^^^^^^^^^ + class ClassVariableOrWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new ClassVariableOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ClassVariableOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :class_variable_or_write_node + def type: () -> :class_variable_or_write_node + + # See `Node.type`. + # -- + # : () -> :class_variable_or_write_node + def self.type: () -> :class_variable_or_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents referencing a class variable. + # + # @@foo + # ^^^^^ + class ClassVariableReadNode < Node + @name: Symbol + + # Initialize a new ClassVariableReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ClassVariableReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :class_variable_read_node + def type: () -> :class_variable_read_node + + # See `Node.type`. + # -- + # : () -> :class_variable_read_node + def self.type: () -> :class_variable_read_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @@abc # name `:@@abc` + # + # @@_test # name `:@@_test` + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents writing to a class variable in a context that doesn't have an explicit value. + # + # @@foo, @@bar = baz + # ^^^^^ ^^^^^ + class ClassVariableTargetNode < Node + @name: Symbol + + # Initialize a new ClassVariableTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ClassVariableTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :class_variable_target_node + def type: () -> :class_variable_target_node + + # See `Node.type`. + # -- + # : () -> :class_variable_target_node + def self.type: () -> :class_variable_target_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents writing to a class variable. + # + # @@foo = 1 + # ^^^^^^^^^ + class ClassVariableWriteNode < Node + @operator_loc: Location + + @value: Prism::node + + @name_loc: Location + + @name: Symbol + + # Initialize a new ClassVariableWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ClassVariableWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ClassVariableWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ClassVariableWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :class_variable_write_node + def type: () -> :class_variable_write_node + + # See `Node.type`. + # -- + # : () -> :class_variable_write_node + def self.type: () -> :class_variable_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @@abc = 123 # name `@@abc` + # + # @@_test = :test # name `@@_test` + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # The Location of the variable name. + # + # @@foo = :bar + # ^^^^^ + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # 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). + # + # @@foo = :bar + # ^^^^ + # + # @@_xyz = 123 + # ^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `=` operator. + # + # @@foo = :bar + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `&&=` operator for assignment to a constant. + # + # Target &&= value + # ^^^^^^^^^^^^^^^^ + class ConstantAndWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new ConstantAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_and_write_node + def type: () -> :constant_and_write_node + + # See `Node.type`. + # -- + # : () -> :constant_and_write_node + def self.type: () -> :constant_and_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents assigning to a constant using an operator that isn't `=`. + # + # Target += value + # ^^^^^^^^^^^^^^^ + class ConstantOperatorWriteNode < Node + @binary_operator: Symbol + + @value: Prism::node + + @binary_operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new ConstantOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_operator_write_node + def type: () -> :constant_operator_write_node + + # See `Node.type`. + # -- + # : () -> :constant_operator_write_node + def self.type: () -> :constant_operator_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Returns the Location represented by `binary_operator_loc`. + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # binary_operator -> Symbol + # + # Returns the `binary_operator` attribute. + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `||=` operator for assignment to a constant. + # + # Target ||= value + # ^^^^^^^^^^^^^^^^ + class ConstantOrWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new ConstantOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_or_write_node + def type: () -> :constant_or_write_node + + # See `Node.type`. + # -- + # : () -> :constant_or_write_node + def self.type: () -> :constant_or_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `&&=` operator for assignment to a constant path. + # + # Parent::Child &&= value + # ^^^^^^^^^^^^^^^^^^^^^^^ + class ConstantPathAndWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @target: ConstantPathNode + + # Initialize a new ConstantPathAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantPathAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_path_and_write_node + def type: () -> :constant_path_and_write_node + + # See `Node.type`. + # -- + # : () -> :constant_path_and_write_node + def self.type: () -> :constant_path_and_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # target -> ConstantPathNode + # + # Returns the `target` attribute. + # -- + # : () -> ConstantPathNode + def target: () -> ConstantPathNode + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents accessing a constant through a path of `::` operators. + # + # Foo::Bar + # ^^^^^^^^ + class ConstantPathNode < Node + @name_loc: Location + + @delimiter_loc: Location + + @name: Symbol? + + @parent: Prism::node? + + # Initialize a new ConstantPathNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? parent, Symbol? name, Location delimiter_loc, Location name_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? parent, Symbol? name, Location delimiter_loc, Location name_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantPathNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_path_node + def type: () -> :constant_path_node + + # See `Node.type`. + # -- + # : () -> :constant_path_node + def self.type: () -> :constant_path_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # parent -> Node | nil + # + # 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. + # + # Foo::Bar + # ^^^ + # + # self::Test + # ^^^^ + # + # a.b::C + # ^^^ + # -- + # : () -> Prism::node? + def parent: () -> Prism::node? + + # :call-seq: + # name -> Symbol | nil + # + # The name of the constant being accessed. This could be `nil` in the event of a syntax error. + # -- + # : () -> Symbol? + def name: () -> Symbol? + + # :category: Locations + # :call-seq: + # delimiter_loc -> Location + # + # The Location of the `::` delimiter. + # + # ::Foo + # ^^ + # + # One::Two + # ^^ + # -- + # : () -> Location + def delimiter_loc: () -> Location + + # :category: Repository + # Save the delimiter_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_delimiter_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # The Location of the name of the constant. + # + # ::Foo + # ^^^ + # + # One::Two + # ^^^ + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # delimiter -> String + # + # Slice the location of delimiter_loc from the source. + # -- + # : () -> String + def delimiter: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents assigning to a constant path using an operator that isn't `=`. + # + # Parent::Child += value + # ^^^^^^^^^^^^^^^^^^^^^^ + class ConstantPathOperatorWriteNode < Node + @binary_operator: Symbol + + @value: Prism::node + + @binary_operator_loc: Location + + @target: ConstantPathNode + + # Initialize a new ConstantPathOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantPathOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantPathOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantPathOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_path_operator_write_node + def type: () -> :constant_path_operator_write_node + + # See `Node.type`. + # -- + # : () -> :constant_path_operator_write_node + def self.type: () -> :constant_path_operator_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # target -> ConstantPathNode + # + # Returns the `target` attribute. + # -- + # : () -> ConstantPathNode + def target: () -> ConstantPathNode + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Returns the Location represented by `binary_operator_loc`. + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # binary_operator -> Symbol + # + # Returns the `binary_operator` attribute. + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `||=` operator for assignment to a constant path. + # + # Parent::Child ||= value + # ^^^^^^^^^^^^^^^^^^^^^^^ + class ConstantPathOrWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @target: ConstantPathNode + + # Initialize a new ConstantPathOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantPathOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_path_or_write_node + def type: () -> :constant_path_or_write_node + + # See `Node.type`. + # -- + # : () -> :constant_path_or_write_node + def self.type: () -> :constant_path_or_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # target -> ConstantPathNode + # + # Returns the `target` attribute. + # -- + # : () -> ConstantPathNode + def target: () -> ConstantPathNode + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents writing to a constant path in a context that doesn't have an explicit value. + # + # Foo::Foo, Bar::Bar = baz + # ^^^^^^^^ ^^^^^^^^ + class ConstantPathTargetNode < Node + @name_loc: Location + + @delimiter_loc: Location + + @name: Symbol? + + @parent: Prism::node? + + # Initialize a new ConstantPathTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? parent, Symbol? name, Location delimiter_loc, Location name_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? parent, Symbol? name, Location delimiter_loc, Location name_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantPathTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_path_target_node + def type: () -> :constant_path_target_node + + # See `Node.type`. + # -- + # : () -> :constant_path_target_node + def self.type: () -> :constant_path_target_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # parent -> Node | nil + # + # Returns the `parent` attribute. + # -- + # : () -> Prism::node? + def parent: () -> Prism::node? + + # :call-seq: + # name -> Symbol | nil + # + # Returns the `name` attribute. + # -- + # : () -> Symbol? + def name: () -> Symbol? + + # :category: Locations + # :call-seq: + # delimiter_loc -> Location + # + # Returns the Location represented by `delimiter_loc`. + # -- + # : () -> Location + def delimiter_loc: () -> Location + + # :category: Repository + # Save the delimiter_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_delimiter_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # delimiter -> String + # + # Slice the location of delimiter_loc from the source. + # -- + # : () -> String + def delimiter: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents writing to a constant path. + # + # ::Foo = 1 + # ^^^^^^^^^ + # + # Foo::Bar = 1 + # ^^^^^^^^^^^^ + # + # ::Foo::Bar = 1 + # ^^^^^^^^^^^^^^ + class ConstantPathWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @target: ConstantPathNode + + # Initialize a new ConstantPathWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantPathWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_path_write_node + def type: () -> :constant_path_write_node + + # See `Node.type`. + # -- + # : () -> :constant_path_write_node + def self.type: () -> :constant_path_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # target -> ConstantPathNode + # + # A node representing the constant path being written to. + # + # Foo::Bar = 1 + # ^^^^^^^^ + # + # ::Foo = :abc + # ^^^^^ + # -- + # : () -> ConstantPathNode + def target: () -> ConstantPathNode + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `=` operator. + # + # ::ABC = 123 + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # 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). + # + # FOO::BAR = :abc + # ^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents referencing a constant. + # + # Foo + # ^^^ + class ConstantReadNode < Node + @name: Symbol + + # Initialize a new ConstantReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_read_node + def type: () -> :constant_read_node + + # See `Node.type`. + # -- + # : () -> :constant_read_node + def self.type: () -> :constant_read_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the [constant](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#constants). + # + # X # name `:X` + # + # SOME_CONSTANT # name `:SOME_CONSTANT` + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents writing to a constant in a context that doesn't have an explicit value. + # + # Foo, Bar = baz + # ^^^ ^^^ + class ConstantTargetNode < Node + @name: Symbol + + # Initialize a new ConstantTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_target_node + def type: () -> :constant_target_node + + # See `Node.type`. + # -- + # : () -> :constant_target_node + def self.type: () -> :constant_target_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents writing to a constant. + # + # Foo = 1 + # ^^^^^^^ + class ConstantWriteNode < Node + @operator_loc: Location + + @value: Prism::node + + @name_loc: Location + + @name: Symbol + + # Initialize a new ConstantWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ConstantWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ConstantWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_write_node + def type: () -> :constant_write_node + + # See `Node.type`. + # -- + # : () -> :constant_write_node + def self.type: () -> :constant_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the [constant](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#constants). + # + # Foo = :bar # name `:Foo` + # + # XYZ = 1 # name `:XYZ` + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # The Location of the constant name. + # + # FOO = 1 + # ^^^ + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # 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). + # + # FOO = :bar + # ^^^^ + # + # MyClass = Class.new + # ^^^^^^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `=` operator. + # + # FOO = :bar + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a method definition. + # + # def method + # end + # ^^^^^^^^^^ + class DefNode < Node + @end_keyword_loc: Location? + + @equal_loc: Location? + + @rparen_loc: Location? + + @lparen_loc: Location? + + @operator_loc: Location? + + @def_keyword_loc: Location + + @locals: Array[Symbol] + + @body: (StatementsNode | BeginNode)? + + @parameters: ParametersNode? + + @receiver: Prism::node? + + @name_loc: Location + + @name: Symbol + + # Initialize a new DefNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node? receiver, ParametersNode? parameters, (StatementsNode | BeginNode)? body, Array[Symbol] locals, Location def_keyword_loc, Location? operator_loc, Location? lparen_loc, Location? rparen_loc, Location? equal_loc, Location? end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node? receiver, ParametersNode? parameters, (StatementsNode | BeginNode)? body, Array[Symbol] locals, Location def_keyword_loc, Location? operator_loc, Location? lparen_loc, Location? rparen_loc, Location? equal_loc, Location? end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> DefNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?receiver: Prism::node?, ?parameters: ParametersNode?, ?body: (StatementsNode | BeginNode)?, ?locals: Array[Symbol], ?def_keyword_loc: Location, ?operator_loc: Location?, ?lparen_loc: Location?, ?rparen_loc: Location?, ?equal_loc: Location?, ?end_keyword_loc: Location?) -> DefNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?receiver: Prism::node?, ?parameters: ParametersNode?, ?body: (StatementsNode | BeginNode)?, ?locals: Array[Symbol], ?def_keyword_loc: Location, ?operator_loc: Location?, ?lparen_loc: Location?, ?rparen_loc: Location?, ?equal_loc: Location?, ?end_keyword_loc: Location?) -> DefNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :def_node + def type: () -> :def_node + + # See `Node.type`. + # -- + # : () -> :def_node + def self.type: () -> :def_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # receiver -> Node | nil + # + # Returns the `receiver` attribute. + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :call-seq: + # parameters -> ParametersNode | nil + # + # Returns the `parameters` attribute. + # -- + # : () -> ParametersNode? + def parameters: () -> ParametersNode? + + # :call-seq: + # body -> StatementsNode | BeginNode | nil + # + # Returns the `body` attribute. + # -- + # : () -> (StatementsNode | BeginNode)? + def body: () -> (StatementsNode | BeginNode)? + + # :call-seq: + # locals -> Array[Symbol] + # + # Returns the `locals` attribute. + # -- + # : () -> Array[Symbol] + def locals: () -> Array[Symbol] + + # :category: Locations + # :call-seq: + # def_keyword_loc -> Location + # + # Returns the Location represented by `def_keyword_loc`. + # -- + # : () -> Location + def def_keyword_loc: () -> Location + + # :category: Repository + # Save the def_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_def_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location | nil + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location? + def operator_loc: () -> Location? + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # lparen_loc -> Location | nil + # + # Returns the Location represented by `lparen_loc`. + # -- + # : () -> Location? + def lparen_loc: () -> Location? + + # :category: Repository + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_lparen_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # rparen_loc -> Location | nil + # + # Returns the Location represented by `rparen_loc`. + # -- + # : () -> Location? + def rparen_loc: () -> Location? + + # :category: Repository + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_rparen_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # equal_loc -> Location | nil + # + # Returns the Location represented by `equal_loc`. + # -- + # : () -> Location? + def equal_loc: () -> Location? + + # :category: Repository + # Save the equal_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_equal_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location | nil + # + # Returns the Location represented by `end_keyword_loc`. + # -- + # : () -> Location? + def end_keyword_loc: () -> Location? + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # def_keyword -> String + # + # Slice the location of def_keyword_loc from the source. + # -- + # : () -> String + def def_keyword: () -> String + + # :call-seq: + # operator -> String | nil + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String? + def operator: () -> String? + + # :call-seq: + # lparen -> String | nil + # + # Slice the location of lparen_loc from the source. + # -- + # : () -> String? + def lparen: () -> String? + + # :call-seq: + # rparen -> String | nil + # + # Slice the location of rparen_loc from the source. + # -- + # : () -> String? + def rparen: () -> String? + + # :call-seq: + # equal -> String | nil + # + # Slice the location of equal_loc from the source. + # -- + # : () -> String? + def equal: () -> String? + + # :call-seq: + # end_keyword -> String | nil + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String? + def end_keyword: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `defined?` keyword. + # + # defined?(a) + # ^^^^^^^^^^^ + class DefinedNode < Node + @keyword_loc: Location + + @rparen_loc: Location? + + @value: Prism::node + + @lparen_loc: Location? + + # Initialize a new DefinedNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location? lparen_loc, Prism::node value, Location? rparen_loc, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location? lparen_loc, Prism::node value, Location? rparen_loc, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> DefinedNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?lparen_loc: Location?, ?value: Prism::node, ?rparen_loc: Location?, ?keyword_loc: Location) -> DefinedNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?lparen_loc: Location?, ?value: Prism::node, ?rparen_loc: Location?, ?keyword_loc: Location) -> DefinedNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :defined_node + def type: () -> :defined_node + + # See `Node.type`. + # -- + # : () -> :defined_node + def self.type: () -> :defined_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # lparen_loc -> Location | nil + # + # Returns the Location represented by `lparen_loc`. + # -- + # : () -> Location? + def lparen_loc: () -> Location? + + # :category: Repository + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_lparen_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :category: Locations + # :call-seq: + # rparen_loc -> Location | nil + # + # Returns the Location represented by `rparen_loc`. + # -- + # : () -> Location? + def rparen_loc: () -> Location? + + # :category: Repository + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_rparen_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # lparen -> String | nil + # + # Slice the location of lparen_loc from the source. + # -- + # : () -> String? + def lparen: () -> String? + + # :call-seq: + # rparen -> String | nil + # + # Slice the location of rparen_loc from the source. + # -- + # : () -> String? + def rparen: () -> String? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an `else` clause in a `case`, `if`, or `unless` statement. + # + # if a then b else c end + # ^^^^^^^^^^ + class ElseNode < Node + @end_keyword_loc: Location? + + @statements: StatementsNode? + + @else_keyword_loc: Location + + # Initialize a new ElseNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location else_keyword_loc, StatementsNode? statements, Location? end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location else_keyword_loc, StatementsNode? statements, Location? end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ElseNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?else_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location?) -> ElseNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?else_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location?) -> ElseNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :else_node + def type: () -> :else_node + + # See `Node.type`. + # -- + # : () -> :else_node + def self.type: () -> :else_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # else_keyword_loc -> Location + # + # Returns the Location represented by `else_keyword_loc`. + # -- + # : () -> Location + def else_keyword_loc: () -> Location + + # :category: Repository + # Save the else_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_else_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location | nil + # + # Returns the Location represented by `end_keyword_loc`. + # -- + # : () -> Location? + def end_keyword_loc: () -> Location? + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # else_keyword -> String + # + # Slice the location of else_keyword_loc from the source. + # -- + # : () -> String + def else_keyword: () -> String + + # :call-seq: + # end_keyword -> String | nil + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String? + def end_keyword: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an interpolated set of statements. + # + # "foo #{bar}" + # ^^^^^^ + class EmbeddedStatementsNode < Node + @closing_loc: Location + + @statements: StatementsNode? + + @opening_loc: Location + + # Initialize a new EmbeddedStatementsNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, StatementsNode? statements, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, StatementsNode? statements, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> EmbeddedStatementsNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?statements: StatementsNode?, ?closing_loc: Location) -> EmbeddedStatementsNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?statements: StatementsNode?, ?closing_loc: Location) -> EmbeddedStatementsNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :embedded_statements_node + def type: () -> :embedded_statements_node + + # See `Node.type`. + # -- + # : () -> :embedded_statements_node + def self.type: () -> :embedded_statements_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an interpolated variable. + # + # "foo #@bar" + # ^^^^^ + class EmbeddedVariableNode < Node + @variable: InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode + + @operator_loc: Location + + # Initialize a new EmbeddedVariableNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, (InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) variable) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode variable) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> EmbeddedVariableNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?variable: (InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode)) -> EmbeddedVariableNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?variable: InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) -> EmbeddedVariableNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :embedded_variable_node + def type: () -> :embedded_variable_node + + # See `Node.type`. + # -- + # : () -> :embedded_variable_node + def self.type: () -> :embedded_variable_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # variable -> InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode + # + # Returns the `variable` attribute. + # -- + # : () -> (InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) + def variable: () -> (InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an `ensure` clause in a `begin` statement. + # + # begin + # foo + # ensure + # ^^^^^^ + # bar + # end + class EnsureNode < Node + @end_keyword_loc: Location + + @statements: StatementsNode? + + @ensure_keyword_loc: Location + + # Initialize a new EnsureNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location ensure_keyword_loc, StatementsNode? statements, Location end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location ensure_keyword_loc, StatementsNode? statements, Location end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> EnsureNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?ensure_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location) -> EnsureNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?ensure_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location) -> EnsureNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :ensure_node + def type: () -> :ensure_node + + # See `Node.type`. + # -- + # : () -> :ensure_node + def self.type: () -> :ensure_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # ensure_keyword_loc -> Location + # + # Returns the Location represented by `ensure_keyword_loc`. + # -- + # : () -> Location + def ensure_keyword_loc: () -> Location + + # :category: Repository + # Save the ensure_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_ensure_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location + # + # Returns the Location represented by `end_keyword_loc`. + # -- + # : () -> Location + def end_keyword_loc: () -> Location + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # ensure_keyword -> String + # + # Slice the location of ensure_keyword_loc from the source. + # -- + # : () -> String + def ensure_keyword: () -> String + + # :call-seq: + # end_keyword -> String + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String + def end_keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the literal `false` keyword. + # + # false + # ^^^^^ + class FalseNode < Node + # Initialize a new FalseNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> FalseNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> FalseNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> FalseNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :false_node + def type: () -> :false_node + + # See `Node.type`. + # -- + # : () -> :false_node + def self.type: () -> :false_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a find pattern in pattern matching. + # + # foo in *bar, baz, *qux + # ^^^^^^^^^^^^^^^ + # + # foo in [*bar, baz, *qux] + # ^^^^^^^^^^^^^^^^^ + # + # foo in Foo(*bar, baz, *qux) + # ^^^^^^^^^^^^^^^^^^^^ + # + # foo => *bar, baz, *qux + # ^^^^^^^^^^^^^^^ + class FindPatternNode < Node + @closing_loc: Location? + + @opening_loc: Location? + + @right: SplatNode | MissingNode + + @requireds: Array[Prism::node] + + @left: SplatNode + + @constant: (ConstantPathNode | ConstantReadNode)? + + # Initialize a new FindPatternNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (ConstantPathNode | ConstantReadNode)? constant, SplatNode left, Array[Prism::node] requireds, (SplatNode | MissingNode) right, Location? opening_loc, Location? closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, (ConstantPathNode | ConstantReadNode)? constant, SplatNode left, Array[Prism::node] requireds, SplatNode | MissingNode right, Location? opening_loc, Location? closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> FindPatternNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?left: SplatNode, ?requireds: Array[Prism::node], ?right: (SplatNode | MissingNode), ?opening_loc: Location?, ?closing_loc: Location?) -> FindPatternNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?left: SplatNode, ?requireds: Array[Prism::node], ?right: SplatNode | MissingNode, ?opening_loc: Location?, ?closing_loc: Location?) -> FindPatternNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :find_pattern_node + def type: () -> :find_pattern_node + + # See `Node.type`. + # -- + # : () -> :find_pattern_node + def self.type: () -> :find_pattern_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # constant -> ConstantPathNode | ConstantReadNode | nil + # + # Represents the optional constant preceding the pattern + # + # foo in Foo(*bar, baz, *qux) + # ^^^ + # -- + # : () -> (ConstantPathNode | ConstantReadNode)? + def constant: () -> (ConstantPathNode | ConstantReadNode)? + + # :call-seq: + # left -> SplatNode + # + # Represents the first wildcard node in the pattern. + # + # foo in *bar, baz, *qux + # ^^^^ + # + # foo in Foo(*bar, baz, *qux) + # ^^^^ + # -- + # : () -> SplatNode + def left: () -> SplatNode + + # :call-seq: + # requireds -> Array[Node] + # + # Represents the nodes in between the wildcards. + # + # foo in *bar, baz, *qux + # ^^^ + # + # foo in Foo(*bar, baz, 1, *qux) + # ^^^^^^ + # -- + # : () -> Array[Prism::node] + def requireds: () -> Array[Prism::node] + + # :call-seq: + # right -> SplatNode | MissingNode + # + # Represents the second wildcard node in the pattern. + # + # foo in *bar, baz, *qux + # ^^^^ + # + # foo in Foo(*bar, baz, *qux) + # ^^^^ + # -- + # : () -> (SplatNode | MissingNode) + def right: () -> (SplatNode | MissingNode) + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # The Location of the opening brace. + # + # foo in [*bar, baz, *qux] + # ^ + # + # foo in Foo(*bar, baz, *qux) + # ^ + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # The Location of the closing brace. + # + # foo in [*bar, baz, *qux] + # ^ + # + # foo in Foo(*bar, baz, *qux) + # ^ + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `..` or `...` operators to create flip flops. + # + # baz if foo .. bar + # ^^^^^^^^^^ + class FlipFlopNode < Node + @operator_loc: Location + + @right: Prism::node? + + @left: Prism::node? + + # Initialize a new FlipFlopNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? left, Prism::node? right, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? left, Prism::node? right, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> FlipFlopNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> FlipFlopNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> FlipFlopNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :flip_flop_node + def type: () -> :flip_flop_node + + # See `Node.type`. + # -- + # : () -> :flip_flop_node + def self.type: () -> :flip_flop_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # ... operator + # -- + # : () -> bool + def exclude_end?: () -> bool + + # :call-seq: + # left -> Node | nil + # + # Returns the `left` attribute. + # -- + # : () -> Prism::node? + def left: () -> Prism::node? + + # :call-seq: + # right -> Node | nil + # + # Returns the `right` attribute. + # -- + # : () -> Prism::node? + def right: () -> Prism::node? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a floating point number literal. + # + # 1.0 + # ^^^ + class FloatNode < Node + @value: Float + + # Initialize a new FloatNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Float value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Float value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> FloatNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Float) -> FloatNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Float) -> FloatNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :float_node + def type: () -> :float_node + + # See `Node.type`. + # -- + # : () -> :float_node + def self.type: () -> :float_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # value -> Float + # + # The value of the floating point number as a Float. + # -- + # : () -> Float + def value: () -> Float + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `for` keyword. + # + # for i in a end + # ^^^^^^^^^^^^^^ + class ForNode < Node + @end_keyword_loc: Location + + @do_keyword_loc: Location? + + @in_keyword_loc: Location + + @for_keyword_loc: Location + + @statements: StatementsNode? + + @collection: Prism::node + + @index: LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode + + # Initialize a new ForNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode) index, Prism::node collection, StatementsNode? statements, Location for_keyword_loc, Location in_keyword_loc, Location? do_keyword_loc, Location end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode index, Prism::node collection, StatementsNode? statements, Location for_keyword_loc, Location in_keyword_loc, Location? do_keyword_loc, Location end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ForNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?index: (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode), ?collection: Prism::node, ?statements: StatementsNode?, ?for_keyword_loc: Location, ?in_keyword_loc: Location, ?do_keyword_loc: Location?, ?end_keyword_loc: Location) -> ForNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?index: LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode, ?collection: Prism::node, ?statements: StatementsNode?, ?for_keyword_loc: Location, ?in_keyword_loc: Location, ?do_keyword_loc: Location?, ?end_keyword_loc: Location) -> ForNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :for_node + def type: () -> :for_node + + # See `Node.type`. + # -- + # : () -> :for_node + def self.type: () -> :for_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # index -> LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode + # + # The index expression for `for` loops. + # + # for i in a end + # ^ + # -- + # : () -> (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode) + def index: () -> (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode) + + # :call-seq: + # collection -> Node + # + # The collection to iterate over. + # + # for i in a end + # ^ + # -- + # : () -> Prism::node + def collection: () -> Prism::node + + # :call-seq: + # statements -> StatementsNode | nil + # + # Represents the body of statements to execute for each iteration of the loop. + # + # for i in a + # foo(i) + # ^^^^^^ + # end + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :category: Locations + # :call-seq: + # for_keyword_loc -> Location + # + # The Location of the `for` keyword. + # + # for i in a end + # ^^^ + # -- + # : () -> Location + def for_keyword_loc: () -> Location + + # :category: Repository + # Save the for_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_for_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # in_keyword_loc -> Location + # + # The Location of the `in` keyword. + # + # for i in a end + # ^^ + # -- + # : () -> Location + def in_keyword_loc: () -> Location + + # :category: Repository + # Save the in_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_in_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # do_keyword_loc -> Location | nil + # + # The Location of the `do` keyword, if present. + # + # for i in a do end + # ^^ + # -- + # : () -> Location? + def do_keyword_loc: () -> Location? + + # :category: Repository + # Save the do_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_do_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location + # + # The Location of the `end` keyword. + # + # for i in a end + # ^^^ + # -- + # : () -> Location + def end_keyword_loc: () -> Location + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # for_keyword -> String + # + # Slice the location of for_keyword_loc from the source. + # -- + # : () -> String + def for_keyword: () -> String + + # :call-seq: + # in_keyword -> String + # + # Slice the location of in_keyword_loc from the source. + # -- + # : () -> String + def in_keyword: () -> String + + # :call-seq: + # do_keyword -> String | nil + # + # Slice the location of do_keyword_loc from the source. + # -- + # : () -> String? + def do_keyword: () -> String? + + # :call-seq: + # end_keyword -> String + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String + def end_keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents forwarding all arguments to this method to another method. + # + # def foo(...) + # bar(...) + # ^^^ + # end + class ForwardingArgumentsNode < Node + # Initialize a new ForwardingArgumentsNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ForwardingArgumentsNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> ForwardingArgumentsNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> ForwardingArgumentsNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :forwarding_arguments_node + def type: () -> :forwarding_arguments_node + + # See `Node.type`. + # -- + # : () -> :forwarding_arguments_node + def self.type: () -> :forwarding_arguments_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the forwarding parameter in a method, block, or lambda declaration. + # + # def foo(...) + # ^^^ + # end + class ForwardingParameterNode < Node + # Initialize a new ForwardingParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ForwardingParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> ForwardingParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> ForwardingParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :forwarding_parameter_node + def type: () -> :forwarding_parameter_node + + # See `Node.type`. + # -- + # : () -> :forwarding_parameter_node + def self.type: () -> :forwarding_parameter_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `super` keyword without parentheses or arguments, but which might have a block. + # + # super + # ^^^^^ + # + # super { 123 } + # ^^^^^^^^^^^^^ + # + # If it has any other arguments, it would be a `SuperNode` instead. + class ForwardingSuperNode < Node + @block: BlockNode? + + # Initialize a new ForwardingSuperNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, BlockNode? block) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, BlockNode? block) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ForwardingSuperNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?block: BlockNode?) -> ForwardingSuperNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?block: BlockNode?) -> ForwardingSuperNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :forwarding_super_node + def type: () -> :forwarding_super_node + + # See `Node.type`. + # -- + # : () -> :forwarding_super_node + def self.type: () -> :forwarding_super_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # block -> BlockNode | nil + # + # All other arguments are forwarded as normal, except the original block is replaced with the new block. + # -- + # : () -> BlockNode? + def block: () -> BlockNode? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `&&=` operator for assignment to a global variable. + # + # $target &&= value + # ^^^^^^^^^^^^^^^^^ + class GlobalVariableAndWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new GlobalVariableAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> GlobalVariableAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :global_variable_and_write_node + def type: () -> :global_variable_and_write_node + + # See `Node.type`. + # -- + # : () -> :global_variable_and_write_node + def self.type: () -> :global_variable_and_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents assigning to a global variable using an operator that isn't `=`. + # + # $target += value + # ^^^^^^^^^^^^^^^^ + class GlobalVariableOperatorWriteNode < Node + @binary_operator: Symbol + + @value: Prism::node + + @binary_operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new GlobalVariableOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> GlobalVariableOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> GlobalVariableOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> GlobalVariableOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :global_variable_operator_write_node + def type: () -> :global_variable_operator_write_node + + # See `Node.type`. + # -- + # : () -> :global_variable_operator_write_node + def self.type: () -> :global_variable_operator_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Returns the Location represented by `binary_operator_loc`. + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # binary_operator -> Symbol + # + # Returns the `binary_operator` attribute. + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `||=` operator for assignment to a global variable. + # + # $target ||= value + # ^^^^^^^^^^^^^^^^^ + class GlobalVariableOrWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new GlobalVariableOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> GlobalVariableOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :global_variable_or_write_node + def type: () -> :global_variable_or_write_node + + # See `Node.type`. + # -- + # : () -> :global_variable_or_write_node + def self.type: () -> :global_variable_or_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents referencing a global variable. + # + # $foo + # ^^^^ + class GlobalVariableReadNode < Node + @name: Symbol + + # Initialize a new GlobalVariableReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> GlobalVariableReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :global_variable_read_node + def type: () -> :global_variable_read_node + + # See `Node.type`. + # -- + # : () -> :global_variable_read_node + def self.type: () -> :global_variable_read_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the global variable, which is a `$` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). Alternatively, it can be one of the special global variables designated by a symbol. + # + # $foo # name `:$foo` + # + # $_Test # name `:$_Test` + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents writing to a global variable in a context that doesn't have an explicit value. + # + # $foo, $bar = baz + # ^^^^ ^^^^ + class GlobalVariableTargetNode < Node + @name: Symbol + + # Initialize a new GlobalVariableTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> GlobalVariableTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :global_variable_target_node + def type: () -> :global_variable_target_node + + # See `Node.type`. + # -- + # : () -> :global_variable_target_node + def self.type: () -> :global_variable_target_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents writing to a global variable. + # + # $foo = 1 + # ^^^^^^^^ + class GlobalVariableWriteNode < Node + @operator_loc: Location + + @value: Prism::node + + @name_loc: Location + + @name: Symbol + + # Initialize a new GlobalVariableWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> GlobalVariableWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> GlobalVariableWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> GlobalVariableWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :global_variable_write_node + def type: () -> :global_variable_write_node + + # See `Node.type`. + # -- + # : () -> :global_variable_write_node + def self.type: () -> :global_variable_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the global variable, which is a `$` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). Alternatively, it can be one of the special global variables designated by a symbol. + # + # $foo = :bar # name `:$foo` + # + # $_Test = 123 # name `:$_Test` + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # The Location of the global variable's name. + # + # $foo = :bar + # ^^^^ + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # 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). + # + # $foo = :bar + # ^^^^ + # + # $-xyz = 123 + # ^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `=` operator. + # + # $foo = :bar + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a hash literal. + # + # { a => b } + # ^^^^^^^^^^ + class HashNode < Node + @closing_loc: Location + + @elements: Array[AssocNode | AssocSplatNode] + + @opening_loc: Location + + # Initialize a new HashNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[AssocNode | AssocSplatNode] elements, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[AssocNode | AssocSplatNode] elements, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> HashNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?elements: Array[AssocNode | AssocSplatNode], ?closing_loc: Location) -> HashNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?elements: Array[AssocNode | AssocSplatNode], ?closing_loc: Location) -> HashNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :hash_node + def type: () -> :hash_node + + # See `Node.type`. + # -- + # : () -> :hash_node + def self.type: () -> :hash_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # The Location of the opening brace. + # + # { a => b } + # ^ + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # elements -> Array[AssocNode | AssocSplatNode] + # + # The elements of the hash. These can be either `AssocNode`s or `AssocSplatNode`s. + # + # { a: b } + # ^^^^ + # + # { **foo } + # ^^^^^ + # -- + # : () -> Array[AssocNode | AssocSplatNode] + def elements: () -> Array[AssocNode | AssocSplatNode] + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # The Location of the closing brace. + # + # { a => b } + # ^ + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a hash pattern in pattern matching. + # + # foo => { a: 1, b: 2 } + # ^^^^^^^^^^^^^^ + # + # foo => { a: 1, b: 2, **c } + # ^^^^^^^^^^^^^^^^^^^ + # + # foo => Bar[a: 1, b: 2] + # ^^^^^^^^^^^^^^^ + # + # foo in { a: 1, b: 2 } + # ^^^^^^^^^^^^^^ + class HashPatternNode < Node + @closing_loc: Location? + + @opening_loc: Location? + + @rest: (AssocSplatNode | NoKeywordsParameterNode)? + + @elements: Array[AssocNode] + + @constant: (ConstantPathNode | ConstantReadNode)? + + # Initialize a new HashPatternNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (ConstantPathNode | ConstantReadNode)? constant, Array[AssocNode] elements, (AssocSplatNode | NoKeywordsParameterNode)? rest, Location? opening_loc, Location? closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, (ConstantPathNode | ConstantReadNode)? constant, Array[AssocNode] elements, (AssocSplatNode | NoKeywordsParameterNode)? rest, Location? opening_loc, Location? closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> HashPatternNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?elements: Array[AssocNode], ?rest: (AssocSplatNode | NoKeywordsParameterNode)?, ?opening_loc: Location?, ?closing_loc: Location?) -> HashPatternNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?elements: Array[AssocNode], ?rest: (AssocSplatNode | NoKeywordsParameterNode)?, ?opening_loc: Location?, ?closing_loc: Location?) -> HashPatternNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :hash_pattern_node + def type: () -> :hash_pattern_node + + # See `Node.type`. + # -- + # : () -> :hash_pattern_node + def self.type: () -> :hash_pattern_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # constant -> ConstantPathNode | ConstantReadNode | nil + # + # Represents the optional constant preceding the Hash. + # + # foo => Bar[a: 1, b: 2] + # ^^^ + # + # foo => Bar::Baz[a: 1, b: 2] + # ^^^^^^^^ + # -- + # : () -> (ConstantPathNode | ConstantReadNode)? + def constant: () -> (ConstantPathNode | ConstantReadNode)? + + # :call-seq: + # elements -> Array[AssocNode] + # + # Represents the explicit named hash keys and values. + # + # foo => { a: 1, b:, ** } + # ^^^^^^^^ + # -- + # : () -> Array[AssocNode] + def elements: () -> Array[AssocNode] + + # :call-seq: + # rest -> AssocSplatNode | NoKeywordsParameterNode | nil + # + # Represents the rest of the Hash keys and values. This can be named, unnamed, or explicitly forbidden via `**nil`, this last one results in a `NoKeywordsParameterNode`. + # + # foo => { a: 1, b:, **c } + # ^^^ + # + # foo => { a: 1, b:, ** } + # ^^ + # + # foo => { a: 1, b:, **nil } + # ^^^^^ + # -- + # : () -> (AssocSplatNode | NoKeywordsParameterNode)? + def rest: () -> (AssocSplatNode | NoKeywordsParameterNode)? + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # The Location of the opening brace. + # + # foo => { a: 1 } + # ^ + # + # foo => Bar[a: 1] + # ^ + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # The Location of the closing brace. + # + # foo => { a: 1 } + # ^ + # + # foo => Bar[a: 1] + # ^ + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `if` keyword, either in the block form or the modifier form, or a ternary expression. + # + # bar if foo + # ^^^^^^^^^^ + # + # if foo then bar end + # ^^^^^^^^^^^^^^^^^^^ + # + # foo ? bar : baz + # ^^^^^^^^^^^^^^^ + class IfNode < Node + @end_keyword_loc: Location? + + @subsequent: (ElseNode | IfNode)? + + @statements: StatementsNode? + + @then_keyword_loc: Location? + + @predicate: Prism::node + + @if_keyword_loc: Location? + + # Initialize a new IfNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location? if_keyword_loc, Prism::node predicate, Location? then_keyword_loc, StatementsNode? statements, (ElseNode | IfNode)? subsequent, Location? end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location? if_keyword_loc, Prism::node predicate, Location? then_keyword_loc, StatementsNode? statements, (ElseNode | IfNode)? subsequent, Location? end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> IfNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?if_keyword_loc: Location?, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: (ElseNode | IfNode)?, ?end_keyword_loc: Location?) -> IfNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?if_keyword_loc: Location?, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: (ElseNode | IfNode)?, ?end_keyword_loc: Location?) -> IfNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :if_node + def type: () -> :if_node + + # See `Node.type`. + # -- + # : () -> :if_node + def self.type: () -> :if_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # if_keyword_loc -> Location | nil + # + # The Location of the `if` keyword if present. + # + # bar if foo + # ^^ + # + # The `if_keyword_loc` field will be `nil` when the `IfNode` represents a ternary expression. + # -- + # : () -> Location? + def if_keyword_loc: () -> Location? + + # :category: Repository + # Save the if_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_if_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # predicate -> Node + # + # The node for the condition the `IfNode` is testing. + # + # if foo + # ^^^ + # bar + # end + # + # bar if foo + # ^^^ + # + # foo ? bar : baz + # ^^^ + # -- + # : () -> Prism::node + def predicate: () -> Prism::node + + # :category: Locations + # :call-seq: + # then_keyword_loc -> Location | nil + # + # The Location of the `then` keyword (if present) or the `?` in a ternary expression, `nil` otherwise. + # + # if foo then bar end + # ^^^^ + # + # a ? b : c + # ^ + # -- + # : () -> Location? + def then_keyword_loc: () -> Location? + + # :category: Repository + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_then_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # statements -> StatementsNode | nil + # + # Represents the body of statements that will be executed when the predicate is evaluated as truthy. Will be `nil` when no body is provided. + # + # if foo + # bar + # ^^^ + # baz + # ^^^ + # end + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :call-seq: + # subsequent -> ElseNode | IfNode | nil + # + # Represents an `ElseNode` or an `IfNode` when there is an `else` or an `elsif` in the `if` statement. + # + # if foo + # bar + # elsif baz + # ^^^^^^^^^ + # qux + # ^^^ + # end + # ^^^ + # + # if foo then bar else baz end + # ^^^^^^^^^^^^ + # -- + # : () -> (ElseNode | IfNode)? + def subsequent: () -> (ElseNode | IfNode)? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location | nil + # + # The Location of the `end` keyword if present, `nil` otherwise. + # + # if foo + # bar + # end + # ^^^ + # -- + # : () -> Location? + def end_keyword_loc: () -> Location? + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # if_keyword -> String | nil + # + # Slice the location of if_keyword_loc from the source. + # -- + # : () -> String? + def if_keyword: () -> String? + + # :call-seq: + # then_keyword -> String | nil + # + # Slice the location of then_keyword_loc from the source. + # -- + # : () -> String? + def then_keyword: () -> String? + + # :call-seq: + # end_keyword -> String | nil + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String? + def end_keyword: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an imaginary number literal. + # + # 1.0i + # ^^^^ + class ImaginaryNode < Node + @numeric: FloatNode | IntegerNode | RationalNode + + # Initialize a new ImaginaryNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (FloatNode | IntegerNode | RationalNode) numeric) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, FloatNode | IntegerNode | RationalNode numeric) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ImaginaryNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?numeric: (FloatNode | IntegerNode | RationalNode)) -> ImaginaryNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?numeric: FloatNode | IntegerNode | RationalNode) -> ImaginaryNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :imaginary_node + def type: () -> :imaginary_node + + # See `Node.type`. + # -- + # : () -> :imaginary_node + def self.type: () -> :imaginary_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # numeric -> FloatNode | IntegerNode | RationalNode + # + # Returns the `numeric` attribute. + # -- + # : () -> (FloatNode | IntegerNode | RationalNode) + def numeric: () -> (FloatNode | IntegerNode | RationalNode) + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a node that is implicitly being added to the tree but doesn't correspond directly to a node in the source. + # + # { foo: } + # ^^^^ + # + # { Foo: } + # ^^^^ + # + # foo in { bar: } + # ^^^^ + class ImplicitNode < Node + @value: LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode + + # Initialize a new ImplicitNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode) value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ImplicitNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: (LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode)) -> ImplicitNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode) -> ImplicitNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :implicit_node + def type: () -> :implicit_node + + # See `Node.type`. + # -- + # : () -> :implicit_node + def self.type: () -> :implicit_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # value -> LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode + # + # Returns the `value` attribute. + # -- + # : () -> (LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode) + def value: () -> (LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode) + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents using a trailing comma to indicate an implicit rest parameter. + # + # foo { |bar,| } + # ^ + # + # foo in [bar,] + # ^ + # + # for foo, in bar do end + # ^ + # + # foo, = bar + # ^ + class ImplicitRestNode < Node + # Initialize a new ImplicitRestNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ImplicitRestNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> ImplicitRestNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> ImplicitRestNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :implicit_rest_node + def type: () -> :implicit_rest_node + + # See `Node.type`. + # -- + # : () -> :implicit_rest_node + def self.type: () -> :implicit_rest_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `in` keyword in a case statement. + # + # case a; in b then c end + # ^^^^^^^^^^^ + class InNode < Node + @then_loc: Location? + + @in_loc: Location + + @statements: StatementsNode? + + @pattern: Prism::node + + # Initialize a new InNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node pattern, StatementsNode? statements, Location in_loc, Location? then_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node pattern, StatementsNode? statements, Location in_loc, Location? then_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?pattern: Prism::node, ?statements: StatementsNode?, ?in_loc: Location, ?then_loc: Location?) -> InNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?pattern: Prism::node, ?statements: StatementsNode?, ?in_loc: Location, ?then_loc: Location?) -> InNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :in_node + def type: () -> :in_node + + # See `Node.type`. + # -- + # : () -> :in_node + def self.type: () -> :in_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # pattern -> Node + # + # Returns the `pattern` attribute. + # -- + # : () -> Prism::node + def pattern: () -> Prism::node + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :category: Locations + # :call-seq: + # in_loc -> Location + # + # Returns the Location represented by `in_loc`. + # -- + # : () -> Location + def in_loc: () -> Location + + # :category: Repository + # Save the in_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_in_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # then_loc -> Location | nil + # + # Returns the Location represented by `then_loc`. + # -- + # : () -> Location? + def then_loc: () -> Location? + + # :category: Repository + # Save the then_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_then_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # in -> String + # + # Slice the location of in_loc from the source. + # -- + # : () -> String + def in: () -> String + + # :call-seq: + # then -> String | nil + # + # Slice the location of then_loc from the source. + # -- + # : () -> String? + def then: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `&&=` operator on a call to the `[]` method. + # + # foo.bar[baz] &&= value + # ^^^^^^^^^^^^^^^^^^^^^^ + class IndexAndWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @block: BlockArgumentNode? + + @closing_loc: Location + + @arguments: ArgumentsNode? + + @opening_loc: Location + + @call_operator_loc: Location? + + @receiver: Prism::node? + + # Initialize a new IndexAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> IndexAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :index_and_write_node + def type: () -> :index_and_write_node + + # See `Node.type`. + # -- + # : () -> :index_and_write_node + def self.type: () -> :index_and_write_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node | nil + # + # Returns the `receiver` attribute. + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location | nil + # + # Returns the Location represented by `call_operator_loc`. + # -- + # : () -> Location? + def call_operator_loc: () -> Location? + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Returns the `arguments` attribute. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # block -> BlockArgumentNode | nil + # + # Returns the `block` attribute. + # -- + # : () -> BlockArgumentNode? + def block: () -> BlockArgumentNode? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # call_operator -> String | nil + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String? + def call_operator: () -> String? + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of an assignment operator on a call to `[]`. + # + # foo.bar[baz] += value + # ^^^^^^^^^^^^^^^^^^^^^ + class IndexOperatorWriteNode < Node + @value: Prism::node + + @binary_operator_loc: Location + + @binary_operator: Symbol + + @block: BlockArgumentNode? + + @closing_loc: Location + + @arguments: ArgumentsNode? + + @opening_loc: Location + + @call_operator_loc: Location? + + @receiver: Prism::node? + + # Initialize a new IndexOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block, Symbol binary_operator, Location binary_operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block, Symbol binary_operator, Location binary_operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> IndexOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> IndexOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> IndexOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :index_operator_write_node + def type: () -> :index_operator_write_node + + # See `Node.type`. + # -- + # : () -> :index_operator_write_node + def self.type: () -> :index_operator_write_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node | nil + # + # Returns the `receiver` attribute. + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location | nil + # + # Returns the Location represented by `call_operator_loc`. + # -- + # : () -> Location? + def call_operator_loc: () -> Location? + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Returns the `arguments` attribute. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # block -> BlockArgumentNode | nil + # + # Returns the `block` attribute. + # -- + # : () -> BlockArgumentNode? + def block: () -> BlockArgumentNode? + + # :call-seq: + # binary_operator -> Symbol + # + # Returns the `binary_operator` attribute. + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Returns the Location represented by `binary_operator_loc`. + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # call_operator -> String | nil + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String? + def call_operator: () -> String? + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `||=` operator on a call to `[]`. + # + # foo.bar[baz] ||= value + # ^^^^^^^^^^^^^^^^^^^^^^ + class IndexOrWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @block: BlockArgumentNode? + + @closing_loc: Location + + @arguments: ArgumentsNode? + + @opening_loc: Location + + @call_operator_loc: Location? + + @receiver: Prism::node? + + # Initialize a new IndexOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> IndexOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :index_or_write_node + def type: () -> :index_or_write_node + + # See `Node.type`. + # -- + # : () -> :index_or_write_node + def self.type: () -> :index_or_write_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node | nil + # + # Returns the `receiver` attribute. + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location | nil + # + # Returns the Location represented by `call_operator_loc`. + # -- + # : () -> Location? + def call_operator_loc: () -> Location? + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Returns the `arguments` attribute. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # block -> BlockArgumentNode | nil + # + # Returns the `block` attribute. + # -- + # : () -> BlockArgumentNode? + def block: () -> BlockArgumentNode? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # call_operator -> String | nil + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String? + def call_operator: () -> String? + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents assigning to an index. + # + # foo[bar], = 1 + # ^^^^^^^^ + # + # begin + # rescue => foo[bar] + # ^^^^^^^^ + # end + # + # for foo[bar] in baz do end + # ^^^^^^^^ + class IndexTargetNode < Node + @block: BlockArgumentNode? + + @closing_loc: Location + + @arguments: ArgumentsNode? + + @opening_loc: Location + + @receiver: Prism::node + + # Initialize a new IndexTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node receiver, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node receiver, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> IndexTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?) -> IndexTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?) -> IndexTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :index_target_node + def type: () -> :index_target_node + + # See `Node.type`. + # -- + # : () -> :index_target_node + def self.type: () -> :index_target_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node + # + # Returns the `receiver` attribute. + # -- + # : () -> Prism::node + def receiver: () -> Prism::node + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Returns the `arguments` attribute. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # block -> BlockArgumentNode | nil + # + # Returns the `block` attribute. + # -- + # : () -> BlockArgumentNode? + def block: () -> BlockArgumentNode? + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `&&=` operator for assignment to an instance variable. + # + # @target &&= value + # ^^^^^^^^^^^^^^^^^ + class InstanceVariableAndWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new InstanceVariableAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InstanceVariableAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :instance_variable_and_write_node + def type: () -> :instance_variable_and_write_node + + # See `Node.type`. + # -- + # : () -> :instance_variable_and_write_node + def self.type: () -> :instance_variable_and_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents assigning to an instance variable using an operator that isn't `=`. + # + # @target += value + # ^^^^^^^^^^^^^^^^ + class InstanceVariableOperatorWriteNode < Node + @binary_operator: Symbol + + @value: Prism::node + + @binary_operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new InstanceVariableOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InstanceVariableOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> InstanceVariableOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> InstanceVariableOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :instance_variable_operator_write_node + def type: () -> :instance_variable_operator_write_node + + # See `Node.type`. + # -- + # : () -> :instance_variable_operator_write_node + def self.type: () -> :instance_variable_operator_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Returns the Location represented by `binary_operator_loc`. + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # binary_operator -> Symbol + # + # Returns the `binary_operator` attribute. + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `||=` operator for assignment to an instance variable. + # + # @target ||= value + # ^^^^^^^^^^^^^^^^^ + class InstanceVariableOrWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new InstanceVariableOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InstanceVariableOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :instance_variable_or_write_node + def type: () -> :instance_variable_or_write_node + + # See `Node.type`. + # -- + # : () -> :instance_variable_or_write_node + def self.type: () -> :instance_variable_or_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents referencing an instance variable. + # + # @foo + # ^^^^ + class InstanceVariableReadNode < Node + @name: Symbol + + # Initialize a new InstanceVariableReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InstanceVariableReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :instance_variable_read_node + def type: () -> :instance_variable_read_node + + # See `Node.type`. + # -- + # : () -> :instance_variable_read_node + def self.type: () -> :instance_variable_read_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the instance variable, which is a `@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @x # name `:@x` + # + # @_test # name `:@_test` + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents writing to an instance variable in a context that doesn't have an explicit value. + # + # @foo, @bar = baz + # ^^^^ ^^^^ + class InstanceVariableTargetNode < Node + @name: Symbol + + # Initialize a new InstanceVariableTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InstanceVariableTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :instance_variable_target_node + def type: () -> :instance_variable_target_node + + # See `Node.type`. + # -- + # : () -> :instance_variable_target_node + def self.type: () -> :instance_variable_target_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents writing to an instance variable. + # + # @foo = 1 + # ^^^^^^^^ + class InstanceVariableWriteNode < Node + @operator_loc: Location + + @value: Prism::node + + @name_loc: Location + + @name: Symbol + + # Initialize a new InstanceVariableWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InstanceVariableWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> InstanceVariableWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> InstanceVariableWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :instance_variable_write_node + def type: () -> :instance_variable_write_node + + # See `Node.type`. + # -- + # : () -> :instance_variable_write_node + def self.type: () -> :instance_variable_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the instance variable, which is a `@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @x = :y # name `:@x` + # + # @_foo = "bar" # name `@_foo` + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # The Location of the variable name. + # + # @_x = 1 + # ^^^ + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # 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). + # + # @foo = :bar + # ^^^^ + # + # @_x = 1234 + # ^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `=` operator. + # + # @x = y + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an integer number literal. + # + # 1 + # ^ + class IntegerNode < Node + @value: Integer + + # Initialize a new IntegerNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Integer value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Integer value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> IntegerNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Integer) -> IntegerNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Integer) -> IntegerNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :integer_node + def type: () -> :integer_node + + # See `Node.type`. + # -- + # : () -> :integer_node + def self.type: () -> :integer_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # 0b prefix + # -- + # : () -> bool + def binary?: () -> bool + + # :category: Flags + # 0d or no prefix + # -- + # : () -> bool + def decimal?: () -> bool + + # :category: Flags + # 0o or 0 prefix + # -- + # : () -> bool + def octal?: () -> bool + + # :category: Flags + # 0x prefix + # -- + # : () -> bool + def hexadecimal?: () -> bool + + # :call-seq: + # value -> Integer + # + # The value of the integer literal as a number. + # -- + # : () -> Integer + def value: () -> Integer + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a regular expression literal that contains interpolation that is being used in the predicate of a conditional to implicitly match against the last line read by an IO object. + # + # if /foo #{bar} baz/ then end + # ^^^^^^^^^^^^^^^^ + class InterpolatedMatchLastLineNode < Node + @closing_loc: Location + + @parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + @opening_loc: Location + + # Initialize a new InterpolatedMatchLastLineNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InterpolatedMatchLastLineNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedMatchLastLineNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedMatchLastLineNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :interpolated_match_last_line_node + def type: () -> :interpolated_match_last_line_node + + # See `Node.type`. + # -- + # : () -> :interpolated_match_last_line_node + def self.type: () -> :interpolated_match_last_line_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # i - ignores the case of characters when matching + # -- + # : () -> bool + def ignore_case?: () -> bool + + # :category: Flags + # x - ignores whitespace and allows comments in regular expressions + # -- + # : () -> bool + def extended?: () -> bool + + # :category: Flags + # m - allows $ to match the end of lines within strings + # -- + # : () -> bool + def multi_line?: () -> bool + + # :category: Flags + # o - only interpolates values into the regular expression once + # -- + # : () -> bool + def once?: () -> bool + + # :category: Flags + # e - forces the EUC-JP encoding + # -- + # : () -> bool + def euc_jp?: () -> bool + + # :category: Flags + # n - forces the ASCII-8BIT encoding + # -- + # : () -> bool + def ascii_8bit?: () -> bool + + # :category: Flags + # s - forces the Windows-31J encoding + # -- + # : () -> bool + def windows_31j?: () -> bool + + # :category: Flags + # u - forces the UTF-8 encoding + # -- + # : () -> bool + def utf_8?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to US-ASCII + # -- + # : () -> bool + def forced_us_ascii_encoding?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # parts -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + # + # Returns the `parts` attribute. + # -- + # : () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + def parts: () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a regular expression literal that contains interpolation. + # + # /foo #{bar} baz/ + # ^^^^^^^^^^^^^^^^ + class InterpolatedRegularExpressionNode < Node + @closing_loc: Location + + @parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + @opening_loc: Location + + # Initialize a new InterpolatedRegularExpressionNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InterpolatedRegularExpressionNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedRegularExpressionNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedRegularExpressionNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :interpolated_regular_expression_node + def type: () -> :interpolated_regular_expression_node + + # See `Node.type`. + # -- + # : () -> :interpolated_regular_expression_node + def self.type: () -> :interpolated_regular_expression_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # i - ignores the case of characters when matching + # -- + # : () -> bool + def ignore_case?: () -> bool + + # :category: Flags + # x - ignores whitespace and allows comments in regular expressions + # -- + # : () -> bool + def extended?: () -> bool + + # :category: Flags + # m - allows $ to match the end of lines within strings + # -- + # : () -> bool + def multi_line?: () -> bool + + # :category: Flags + # o - only interpolates values into the regular expression once + # -- + # : () -> bool + def once?: () -> bool + + # :category: Flags + # e - forces the EUC-JP encoding + # -- + # : () -> bool + def euc_jp?: () -> bool + + # :category: Flags + # n - forces the ASCII-8BIT encoding + # -- + # : () -> bool + def ascii_8bit?: () -> bool + + # :category: Flags + # s - forces the Windows-31J encoding + # -- + # : () -> bool + def windows_31j?: () -> bool + + # :category: Flags + # u - forces the UTF-8 encoding + # -- + # : () -> bool + def utf_8?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to US-ASCII + # -- + # : () -> bool + def forced_us_ascii_encoding?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # parts -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + # + # Returns the `parts` attribute. + # -- + # : () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + def parts: () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a string literal that contains interpolation. + # + # "foo #{bar} baz" + # ^^^^^^^^^^^^^^^^ + class InterpolatedStringNode < Node + @closing_loc: Location? + + @parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode] + + @opening_loc: Location? + + # Initialize a new InterpolatedStringNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode] parts, Location? closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode] parts, Location? closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InterpolatedStringNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode], ?closing_loc: Location?) -> InterpolatedStringNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode], ?closing_loc: Location?) -> InterpolatedStringNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :interpolated_string_node + def type: () -> :interpolated_string_node + + # See `Node.type`. + # -- + # : () -> :interpolated_string_node + def self.type: () -> :interpolated_string_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + # -- + # : () -> bool + def frozen?: () -> bool + + # :category: Flags + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + # -- + # : () -> bool + def mutable?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # parts -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode] + # + # Returns the `parts` attribute. + # -- + # : () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode] + def parts: () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode] + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a symbol literal that contains interpolation. + # + # :"foo #{bar} baz" + # ^^^^^^^^^^^^^^^^^ + class InterpolatedSymbolNode < Node + @closing_loc: Location? + + @parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + @opening_loc: Location? + + # Initialize a new InterpolatedSymbolNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location? closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location? closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InterpolatedSymbolNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location?) -> InterpolatedSymbolNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location?) -> InterpolatedSymbolNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :interpolated_symbol_node + def type: () -> :interpolated_symbol_node + + # See `Node.type`. + # -- + # : () -> :interpolated_symbol_node + def self.type: () -> :interpolated_symbol_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # parts -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + # + # Returns the `parts` attribute. + # -- + # : () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + def parts: () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an xstring literal that contains interpolation. + # + # `foo #{bar} baz` + # ^^^^^^^^^^^^^^^^ + class InterpolatedXStringNode < Node + @closing_loc: Location + + @parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + @opening_loc: Location + + # Initialize a new InterpolatedXStringNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InterpolatedXStringNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedXStringNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedXStringNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :interpolated_x_string_node + def type: () -> :interpolated_x_string_node + + # See `Node.type`. + # -- + # : () -> :interpolated_x_string_node + def self.type: () -> :interpolated_x_string_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # parts -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + # + # Returns the `parts` attribute. + # -- + # : () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + def parts: () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents reading from the implicit `it` local variable. + # + # -> { it } + # ^^ + class ItLocalVariableReadNode < Node + # Initialize a new ItLocalVariableReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ItLocalVariableReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> ItLocalVariableReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> ItLocalVariableReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :it_local_variable_read_node + def type: () -> :it_local_variable_read_node + + # See `Node.type`. + # -- + # : () -> :it_local_variable_read_node + def self.type: () -> :it_local_variable_read_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an implicit set of parameters through the use of the `it` keyword within a block or lambda. + # + # -> { it + it } + # ^^^^^^^^^^^^^^ + class ItParametersNode < Node + # Initialize a new ItParametersNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ItParametersNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> ItParametersNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> ItParametersNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :it_parameters_node + def type: () -> :it_parameters_node + + # See `Node.type`. + # -- + # : () -> :it_parameters_node + def self.type: () -> :it_parameters_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a hash literal without opening and closing braces. + # + # foo(a: b) + # ^^^^ + class KeywordHashNode < Node + @elements: Array[AssocNode | AssocSplatNode] + + # Initialize a new KeywordHashNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[AssocNode | AssocSplatNode] elements) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[AssocNode | AssocSplatNode] elements) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> KeywordHashNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[AssocNode | AssocSplatNode]) -> KeywordHashNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[AssocNode | AssocSplatNode]) -> KeywordHashNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :keyword_hash_node + def type: () -> :keyword_hash_node + + # See `Node.type`. + # -- + # : () -> :keyword_hash_node + def self.type: () -> :keyword_hash_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a keyword hash which only has `AssocNode` elements all with symbol keys, which means the elements can be treated as keyword arguments + # -- + # : () -> bool + def symbol_keys?: () -> bool + + # :call-seq: + # elements -> Array[AssocNode | AssocSplatNode] + # + # Returns the `elements` attribute. + # -- + # : () -> Array[AssocNode | AssocSplatNode] + def elements: () -> Array[AssocNode | AssocSplatNode] + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a keyword rest parameter to a method, block, or lambda definition. + # + # def a(**b) + # ^^^ + # end + class KeywordRestParameterNode < Node + @operator_loc: Location + + @name_loc: Location? + + @name: Symbol? + + # Initialize a new KeywordRestParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol? name, Location? name_loc, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol? name, Location? name_loc, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> KeywordRestParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> KeywordRestParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> KeywordRestParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :keyword_rest_parameter_node + def type: () -> :keyword_rest_parameter_node + + # See `Node.type`. + # -- + # : () -> :keyword_rest_parameter_node + def self.type: () -> :keyword_rest_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol | nil + # + # Returns the `name` attribute. + # -- + # : () -> Symbol? + def name: () -> Symbol? + + # :category: Locations + # :call-seq: + # name_loc -> Location | nil + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location? + def name_loc: () -> Location? + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_name_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents using a lambda literal (not the lambda method call). + # + # ->(value) { value * 2 } + # ^^^^^^^^^^^^^^^^^^^^^^^ + class LambdaNode < Node + @body: (StatementsNode | BeginNode)? + + @parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)? + + @closing_loc: Location + + @opening_loc: Location + + @operator_loc: Location + + @locals: Array[Symbol] + + # Initialize a new LambdaNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location operator_loc, Location opening_loc, Location closing_loc, (BlockParametersNode | NumberedParametersNode | ItParametersNode)? parameters, (StatementsNode | BeginNode)? body) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location operator_loc, Location opening_loc, Location closing_loc, (BlockParametersNode | NumberedParametersNode | ItParametersNode)? parameters, (StatementsNode | BeginNode)? body) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> LambdaNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?operator_loc: Location, ?opening_loc: Location, ?closing_loc: Location, ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?) -> LambdaNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?operator_loc: Location, ?opening_loc: Location, ?closing_loc: Location, ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?) -> LambdaNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :lambda_node + def type: () -> :lambda_node + + # See `Node.type`. + # -- + # : () -> :lambda_node + def self.type: () -> :lambda_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # locals -> Array[Symbol] + # + # Returns the `locals` attribute. + # -- + # : () -> Array[Symbol] + def locals: () -> Array[Symbol] + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # parameters -> BlockParametersNode | NumberedParametersNode | ItParametersNode | nil + # + # Returns the `parameters` attribute. + # -- + # : () -> (BlockParametersNode | NumberedParametersNode | ItParametersNode)? + def parameters: () -> (BlockParametersNode | NumberedParametersNode | ItParametersNode)? + + # :call-seq: + # body -> StatementsNode | BeginNode | nil + # + # Returns the `body` attribute. + # -- + # : () -> (StatementsNode | BeginNode)? + def body: () -> (StatementsNode | BeginNode)? + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `&&=` operator for assignment to a local variable. + # + # target &&= value + # ^^^^^^^^^^^^^^^^ + class LocalVariableAndWriteNode < Node + @depth: Integer + + @name: Symbol + + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + # Initialize a new LocalVariableAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location name_loc, Location operator_loc, Prism::node value, Symbol name, Integer depth) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location name_loc, Location operator_loc, Prism::node value, Symbol name, Integer depth) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> LocalVariableAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :local_variable_and_write_node + def type: () -> :local_variable_and_write_node + + # See `Node.type`. + # -- + # : () -> :local_variable_and_write_node + def self.type: () -> :local_variable_and_write_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # depth -> Integer + # + # Returns the `depth` attribute. + # -- + # : () -> Integer + def depth: () -> Integer + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents assigning to a local variable using an operator that isn't `=`. + # + # target += value + # ^^^^^^^^^^^^^^^ + class LocalVariableOperatorWriteNode < Node + @depth: Integer + + @binary_operator: Symbol + + @name: Symbol + + @value: Prism::node + + @binary_operator_loc: Location + + @name_loc: Location + + # Initialize a new LocalVariableOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol name, Symbol binary_operator, Integer depth) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol name, Symbol binary_operator, Integer depth) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> LocalVariableOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?binary_operator: Symbol, ?depth: Integer) -> LocalVariableOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?binary_operator: Symbol, ?depth: Integer) -> LocalVariableOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :local_variable_operator_write_node + def type: () -> :local_variable_operator_write_node + + # See `Node.type`. + # -- + # : () -> :local_variable_operator_write_node + def self.type: () -> :local_variable_operator_write_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Returns the Location represented by `binary_operator_loc`. + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # binary_operator -> Symbol + # + # Returns the `binary_operator` attribute. + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # :call-seq: + # depth -> Integer + # + # Returns the `depth` attribute. + # -- + # : () -> Integer + def depth: () -> Integer + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `||=` operator for assignment to a local variable. + # + # target ||= value + # ^^^^^^^^^^^^^^^^ + class LocalVariableOrWriteNode < Node + @depth: Integer + + @name: Symbol + + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + # Initialize a new LocalVariableOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location name_loc, Location operator_loc, Prism::node value, Symbol name, Integer depth) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location name_loc, Location operator_loc, Prism::node value, Symbol name, Integer depth) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> LocalVariableOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :local_variable_or_write_node + def type: () -> :local_variable_or_write_node + + # See `Node.type`. + # -- + # : () -> :local_variable_or_write_node + def self.type: () -> :local_variable_or_write_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # depth -> Integer + # + # Returns the `depth` attribute. + # -- + # : () -> Integer + def depth: () -> Integer + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents reading a local variable. Note that this requires that a local variable of the same name has already been written to in the same scope, otherwise it is parsed as a method call. + # + # foo + # ^^^ + class LocalVariableReadNode < Node + @depth: Integer + + @name: Symbol + + # Initialize a new LocalVariableReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Integer depth) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Integer depth) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> LocalVariableReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :local_variable_read_node + def type: () -> :local_variable_read_node + + # See `Node.type`. + # -- + # : () -> :local_variable_read_node + def self.type: () -> :local_variable_read_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the local variable, which is an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # x # name `:x` + # + # _Test # name `:_Test` + # + # Note that this can also be an underscore followed by a number for the default block parameters. + # + # _1 # name `:_1` + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # depth -> Integer + # + # The number of visible scopes that should be searched to find the origin of this local variable. + # + # foo = 1; foo # depth 0 + # + # bar = 2; tap { bar } # depth 1 + # + # The specific rules for calculating the depth may differ from individual Ruby implementations, as they are not specified by the language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md). + # -- + # : () -> Integer + def depth: () -> Integer + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents writing to a local variable in a context that doesn't have an explicit value. + # + # foo, bar = baz + # ^^^ ^^^ + # + # foo => baz + # ^^^ + class LocalVariableTargetNode < Node + @depth: Integer + + @name: Symbol + + # Initialize a new LocalVariableTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Integer depth) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Integer depth) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> LocalVariableTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :local_variable_target_node + def type: () -> :local_variable_target_node + + # See `Node.type`. + # -- + # : () -> :local_variable_target_node + def self.type: () -> :local_variable_target_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # depth -> Integer + # + # Returns the `depth` attribute. + # -- + # : () -> Integer + def depth: () -> Integer + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents writing to a local variable. + # + # foo = 1 + # ^^^^^^^ + class LocalVariableWriteNode < Node + @operator_loc: Location + + @value: Prism::node + + @name_loc: Location + + @depth: Integer + + @name: Symbol + + # Initialize a new LocalVariableWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Integer depth, Location name_loc, Prism::node value, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Integer depth, Location name_loc, Prism::node value, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> LocalVariableWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> LocalVariableWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> LocalVariableWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :local_variable_write_node + def type: () -> :local_variable_write_node + + # See `Node.type`. + # -- + # : () -> :local_variable_write_node + def self.type: () -> :local_variable_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the local variable, which is an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # foo = :bar # name `:foo` + # + # abc = 123 # name `:abc` + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # depth -> Integer + # + # The number of semantic scopes we have to traverse to find the declaration of this variable. + # + # foo = 1 # depth 0 + # + # tap { foo = 1 } # depth 1 + # + # The specific rules for calculating the depth may differ from individual Ruby implementations, as they are not specified by the language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md). + # -- + # : () -> Integer + def depth: () -> Integer + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # The Location of the variable name. + # + # foo = :bar + # ^^^ + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # 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). + # + # foo = :bar + # ^^^^ + # + # abc = 1234 + # ^^^^ + # + # Note that since the name of a local variable is known before the value is parsed, it is valid for a local variable to appear within the value of its own write. + # + # foo = foo + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `=` operator. + # + # x = :y + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a regular expression literal used in the predicate of a conditional to implicitly match against the last line read by an IO object. + # + # if /foo/i then end + # ^^^^^^ + class MatchLastLineNode < Node + @unescaped: String + + @closing_loc: Location + + @content_loc: Location + + @opening_loc: Location + + # Initialize a new MatchLastLineNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Location content_loc, Location closing_loc, String unescaped) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Location content_loc, Location closing_loc, String unescaped) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> MatchLastLineNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> MatchLastLineNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> MatchLastLineNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :match_last_line_node + def type: () -> :match_last_line_node + + # See `Node.type`. + # -- + # : () -> :match_last_line_node + def self.type: () -> :match_last_line_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # i - ignores the case of characters when matching + # -- + # : () -> bool + def ignore_case?: () -> bool + + # :category: Flags + # x - ignores whitespace and allows comments in regular expressions + # -- + # : () -> bool + def extended?: () -> bool + + # :category: Flags + # m - allows $ to match the end of lines within strings + # -- + # : () -> bool + def multi_line?: () -> bool + + # :category: Flags + # o - only interpolates values into the regular expression once + # -- + # : () -> bool + def once?: () -> bool + + # :category: Flags + # e - forces the EUC-JP encoding + # -- + # : () -> bool + def euc_jp?: () -> bool + + # :category: Flags + # n - forces the ASCII-8BIT encoding + # -- + # : () -> bool + def ascii_8bit?: () -> bool + + # :category: Flags + # s - forces the Windows-31J encoding + # -- + # : () -> bool + def windows_31j?: () -> bool + + # :category: Flags + # u - forces the UTF-8 encoding + # -- + # : () -> bool + def utf_8?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to US-ASCII + # -- + # : () -> bool + def forced_us_ascii_encoding?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # content_loc -> Location + # + # Returns the Location represented by `content_loc`. + # -- + # : () -> Location + def content_loc: () -> Location + + # :category: Repository + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_content_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # unescaped -> String + # + # Returns the `unescaped` attribute. + # -- + # : () -> String + def unescaped: () -> String + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # content -> String + # + # Slice the location of content_loc from the source. + # -- + # : () -> String + def content: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the modifier `in` operator. + # + # foo in bar + # ^^^^^^^^^^ + class MatchPredicateNode < Node + @operator_loc: Location + + @pattern: Prism::node + + @value: Prism::node + + # Initialize a new MatchPredicateNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node value, Prism::node pattern, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node value, Prism::node pattern, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> MatchPredicateNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchPredicateNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchPredicateNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :match_predicate_node + def type: () -> :match_predicate_node + + # See `Node.type`. + # -- + # : () -> :match_predicate_node + def self.type: () -> :match_predicate_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # pattern -> Node + # + # Returns the `pattern` attribute. + # -- + # : () -> Prism::node + def pattern: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `=>` operator. + # + # foo => bar + # ^^^^^^^^^^ + class MatchRequiredNode < Node + @operator_loc: Location + + @pattern: Prism::node + + @value: Prism::node + + # Initialize a new MatchRequiredNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node value, Prism::node pattern, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node value, Prism::node pattern, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> MatchRequiredNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchRequiredNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchRequiredNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :match_required_node + def type: () -> :match_required_node + + # See `Node.type`. + # -- + # : () -> :match_required_node + def self.type: () -> :match_required_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # value -> Node + # + # Represents the left-hand side of the operator. + # + # foo => bar + # ^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # pattern -> Node + # + # Represents the right-hand side of the operator. The type of the node depends on the expression. + # + # Anything that looks like a local variable name (including `_`) will result in a `LocalVariableTargetNode`. + # + # foo => a # This is equivalent to writing `a = foo` + # ^ + # + # Using an explicit `Array` or combining expressions with `,` will result in a `ArrayPatternNode`. This can be preceded by a constant. + # + # foo => [a] + # ^^^ + # + # foo => a, b + # ^^^^ + # + # foo => Bar[a, b] + # ^^^^^^^^^ + # + # If the array pattern contains at least two wildcard matches, a `FindPatternNode` is created instead. + # + # foo => *, 1, *a + # ^^^^^ + # + # Using an explicit `Hash` or a constant with square brackets and hash keys in the square brackets will result in a `HashPatternNode`. + # + # foo => { a: 1, b: } + # + # foo => Bar[a: 1, b:] + # + # foo => Bar[**] + # + # To use any variable that needs run time evaluation, pinning is required. This results in a `PinnedVariableNode` + # + # foo => ^a + # ^^ + # + # Similar, any expression can be used with pinning. This results in a `PinnedExpressionNode`. + # + # foo => ^(a + 1) + # + # Anything else will result in the regular node for that expression, for example a `ConstantReadNode`. + # + # foo => CONST + # -- + # : () -> Prism::node + def pattern: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the operator. + # + # foo => bar + # ^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents writing local variables using a regular expression match with named capture groups. + # + # /(?bar)/ =~ baz + # ^^^^^^^^^^^^^^^^^^^^ + class MatchWriteNode < Node + @targets: Array[LocalVariableTargetNode] + + @call: CallNode + + # Initialize a new MatchWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, CallNode call, Array[LocalVariableTargetNode] targets) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, CallNode call, Array[LocalVariableTargetNode] targets) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> MatchWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?call: CallNode, ?targets: Array[LocalVariableTargetNode]) -> MatchWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?call: CallNode, ?targets: Array[LocalVariableTargetNode]) -> MatchWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :match_write_node + def type: () -> :match_write_node + + # See `Node.type`. + # -- + # : () -> :match_write_node + def self.type: () -> :match_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # call -> CallNode + # + # Returns the `call` attribute. + # -- + # : () -> CallNode + def call: () -> CallNode + + # :call-seq: + # targets -> Array[LocalVariableTargetNode] + # + # Returns the `targets` attribute. + # -- + # : () -> Array[LocalVariableTargetNode] + def targets: () -> Array[LocalVariableTargetNode] + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a node that is missing from the source and results in a syntax error. + class MissingNode < Node + # Initialize a new MissingNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> MissingNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> MissingNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> MissingNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :missing_node + def type: () -> :missing_node + + # See `Node.type`. + # -- + # : () -> :missing_node + def self.type: () -> :missing_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a module declaration involving the `module` keyword. + # + # module Foo end + # ^^^^^^^^^^^^^^ + class ModuleNode < Node + @name: Symbol + + @end_keyword_loc: Location + + @body: (StatementsNode | BeginNode)? + + @constant_path: ConstantReadNode | ConstantPathNode | MissingNode + + @module_keyword_loc: Location + + @locals: Array[Symbol] + + # Initialize a new ModuleNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location module_keyword_loc, (ConstantReadNode | ConstantPathNode | MissingNode) constant_path, (StatementsNode | BeginNode)? body, Location end_keyword_loc, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location module_keyword_loc, ConstantReadNode | ConstantPathNode | MissingNode constant_path, (StatementsNode | BeginNode)? body, Location end_keyword_loc, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ModuleNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?module_keyword_loc: Location, ?constant_path: (ConstantReadNode | ConstantPathNode | MissingNode), ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ModuleNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?module_keyword_loc: Location, ?constant_path: ConstantReadNode | ConstantPathNode | MissingNode, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ModuleNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :module_node + def type: () -> :module_node + + # See `Node.type`. + # -- + # : () -> :module_node + def self.type: () -> :module_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # locals -> Array[Symbol] + # + # Returns the `locals` attribute. + # -- + # : () -> Array[Symbol] + def locals: () -> Array[Symbol] + + # :category: Locations + # :call-seq: + # module_keyword_loc -> Location + # + # Returns the Location represented by `module_keyword_loc`. + # -- + # : () -> Location + def module_keyword_loc: () -> Location + + # :category: Repository + # Save the module_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_module_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # constant_path -> ConstantReadNode | ConstantPathNode | MissingNode + # + # Returns the `constant_path` attribute. + # -- + # : () -> (ConstantReadNode | ConstantPathNode | MissingNode) + def constant_path: () -> (ConstantReadNode | ConstantPathNode | MissingNode) + + # :call-seq: + # body -> StatementsNode | BeginNode | nil + # + # Returns the `body` attribute. + # -- + # : () -> (StatementsNode | BeginNode)? + def body: () -> (StatementsNode | BeginNode)? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location + # + # Returns the Location represented by `end_keyword_loc`. + # -- + # : () -> Location + def end_keyword_loc: () -> Location + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # module_keyword -> String + # + # Slice the location of module_keyword_loc from the source. + # -- + # : () -> String + def module_keyword: () -> String + + # :call-seq: + # end_keyword -> String + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String + def end_keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # 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]] + # ^^^^ + class MultiTargetNode < Node + @rparen_loc: Location? + + @lparen_loc: Location? + + @rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + + @rest: (ImplicitRestNode | SplatNode)? + + @lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + + # Initialize a new MultiTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] lefts, (ImplicitRestNode | SplatNode)? rest, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] rights, Location? lparen_loc, Location? rparen_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] lefts, (ImplicitRestNode | SplatNode)? rest, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] rights, Location? lparen_loc, Location? rparen_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> MultiTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?) -> MultiTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?) -> MultiTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :multi_target_node + def type: () -> :multi_target_node + + # See `Node.type`. + # -- + # : () -> :multi_target_node + def self.type: () -> :multi_target_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # lefts -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + # + # 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 + # ^^^^ + # -- + # : () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + def lefts: () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + + # :call-seq: + # rest -> ImplicitRestNode | SplatNode | nil + # + # 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 + # ^ + # -- + # : () -> (ImplicitRestNode | SplatNode)? + def rest: () -> (ImplicitRestNode | SplatNode)? + + # :call-seq: + # rights -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + # + # Represents the targets expressions after a splat node. + # + # a, (*, b, c) = 1, 2, 3, 4, 5 + # ^^^^ + # -- + # : () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + def rights: () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + + # :category: Locations + # :call-seq: + # lparen_loc -> Location | nil + # + # The Location of the opening parenthesis. + # + # a, (b, c) = 1, 2, 3 + # ^ + # -- + # : () -> Location? + def lparen_loc: () -> Location? + + # :category: Repository + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_lparen_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # rparen_loc -> Location | nil + # + # The Location of the closing parenthesis. + # + # a, (b, c) = 1, 2, 3 + # ^ + # -- + # : () -> Location? + def rparen_loc: () -> Location? + + # :category: Repository + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_rparen_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # lparen -> String | nil + # + # Slice the location of lparen_loc from the source. + # -- + # : () -> String? + def lparen: () -> String? + + # :call-seq: + # rparen -> String | nil + # + # Slice the location of rparen_loc from the source. + # -- + # : () -> String? + def rparen: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a write to a multi-target expression. + # + # a, b, c = 1, 2, 3 + # ^^^^^^^^^^^^^^^^^ + class MultiWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @rparen_loc: Location? + + @lparen_loc: Location? + + @rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + + @rest: (ImplicitRestNode | SplatNode)? + + @lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + + # Initialize a new MultiWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] lefts, (ImplicitRestNode | SplatNode)? rest, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] rights, Location? lparen_loc, Location? rparen_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] lefts, (ImplicitRestNode | SplatNode)? rest, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] rights, Location? lparen_loc, Location? rparen_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> MultiWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?, ?operator_loc: Location, ?value: Prism::node) -> MultiWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?, ?operator_loc: Location, ?value: Prism::node) -> MultiWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :multi_write_node + def type: () -> :multi_write_node + + # See `Node.type`. + # -- + # : () -> :multi_write_node + def self.type: () -> :multi_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # lefts -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + # + # 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 + # ^^^^^^^ + # -- + # : () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + def lefts: () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + + # :call-seq: + # rest -> ImplicitRestNode | SplatNode | nil + # + # 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 + # ^ + # -- + # : () -> (ImplicitRestNode | SplatNode)? + def rest: () -> (ImplicitRestNode | SplatNode)? + + # :call-seq: + # rights -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + # + # Represents the targets expressions after a splat node. + # + # a, *, b, c = 1, 2, 3, 4, 5 + # ^^^^ + # -- + # : () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + def rights: () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + + # :category: Locations + # :call-seq: + # lparen_loc -> Location | nil + # + # The Location of the opening parenthesis. + # + # (a, b, c) = 1, 2, 3 + # ^ + # -- + # : () -> Location? + def lparen_loc: () -> Location? + + # :category: Repository + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_lparen_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # rparen_loc -> Location | nil + # + # The Location of the closing parenthesis. + # + # (a, b, c) = 1, 2, 3 + # ^ + # -- + # : () -> Location? + def rparen_loc: () -> Location? + + # :category: Repository + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_rparen_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the operator. + # + # a, b, c = 1, 2, 3 + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # 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 + # ^^^^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # lparen -> String | nil + # + # Slice the location of lparen_loc from the source. + # -- + # : () -> String? + def lparen: () -> String? + + # :call-seq: + # rparen -> String | nil + # + # Slice the location of rparen_loc from the source. + # -- + # : () -> String? + def rparen: () -> String? + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `next` keyword. + # + # next 1 + # ^^^^^^ + class NextNode < Node + @keyword_loc: Location + + @arguments: ArgumentsNode? + + # Initialize a new NextNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ArgumentsNode? arguments, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ArgumentsNode? arguments, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> NextNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> NextNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> NextNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :next_node + def type: () -> :next_node + + # See `Node.type`. + # -- + # : () -> :next_node + def self.type: () -> :next_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Returns the `arguments` attribute. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `nil` keyword. + # + # nil + # ^^^ + class NilNode < Node + # Initialize a new NilNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> NilNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> NilNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> NilNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :nil_node + def type: () -> :nil_node + + # See `Node.type`. + # -- + # : () -> :nil_node + def self.type: () -> :nil_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of `&nil` inside method arguments. + # + # def a(&nil) + # ^^^^ + # end + class NoBlockParameterNode < Node + @keyword_loc: Location + + @operator_loc: Location + + # Initialize a new NoBlockParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> NoBlockParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoBlockParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoBlockParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :no_block_parameter_node + def type: () -> :no_block_parameter_node + + # See `Node.type`. + # -- + # : () -> :no_block_parameter_node + def self.type: () -> :no_block_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of `**nil` inside method arguments. + # + # def a(**nil) + # ^^^^^ + # end + class NoKeywordsParameterNode < Node + @keyword_loc: Location + + @operator_loc: Location + + # Initialize a new NoKeywordsParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> NoKeywordsParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoKeywordsParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoKeywordsParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :no_keywords_parameter_node + def type: () -> :no_keywords_parameter_node + + # See `Node.type`. + # -- + # : () -> :no_keywords_parameter_node + def self.type: () -> :no_keywords_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an implicit set of parameters through the use of numbered parameters within a block or lambda. + # + # -> { _1 + _2 } + # ^^^^^^^^^^^^^^ + class NumberedParametersNode < Node + @maximum: Integer + + # Initialize a new NumberedParametersNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Integer maximum) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Integer maximum) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> NumberedParametersNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?maximum: Integer) -> NumberedParametersNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?maximum: Integer) -> NumberedParametersNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :numbered_parameters_node + def type: () -> :numbered_parameters_node + + # See `Node.type`. + # -- + # : () -> :numbered_parameters_node + def self.type: () -> :numbered_parameters_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # maximum -> Integer + # + # Returns the `maximum` attribute. + # -- + # : () -> Integer + def maximum: () -> Integer + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents reading a numbered reference to a capture in the previous match. + # + # $1 + # ^^ + class NumberedReferenceReadNode < Node + @number: Integer + + # Initialize a new NumberedReferenceReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Integer number) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Integer number) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> NumberedReferenceReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?number: Integer) -> NumberedReferenceReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?number: Integer) -> NumberedReferenceReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :numbered_reference_read_node + def type: () -> :numbered_reference_read_node + + # See `Node.type`. + # -- + # : () -> :numbered_reference_read_node + def self.type: () -> :numbered_reference_read_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # number -> Integer + # + # The (1-indexed, from the left) number of the capture group. Numbered references that are too large result in this value being `0`. + # + # $1 # number `1` + # + # $5432 # number `5432` + # + # $4294967296 # number `0` + # -- + # : () -> Integer + def number: () -> Integer + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an optional keyword parameter to a method, block, or lambda definition. + # + # def a(b: 1) + # ^^^^ + # end + class OptionalKeywordParameterNode < Node + @value: Prism::node + + @name_loc: Location + + @name: Symbol + + # Initialize a new OptionalKeywordParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> OptionalKeywordParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node) -> OptionalKeywordParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node) -> OptionalKeywordParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :optional_keyword_parameter_node + def type: () -> :optional_keyword_parameter_node + + # See `Node.type`. + # -- + # : () -> :optional_keyword_parameter_node + def self.type: () -> :optional_keyword_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an optional parameter to a method, block, or lambda definition. + # + # def a(b = 1) + # ^^^^^ + # end + class OptionalParameterNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new OptionalParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> OptionalParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> OptionalParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> OptionalParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :optional_parameter_node + def type: () -> :optional_parameter_node + + # See `Node.type`. + # -- + # : () -> :optional_parameter_node + def self.type: () -> :optional_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `||` operator or the `or` keyword. + # + # left or right + # ^^^^^^^^^^^^^ + class OrNode < Node + @operator_loc: Location + + @right: Prism::node + + @left: Prism::node + + # Initialize a new OrNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node left, Prism::node right, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node left, Prism::node right, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> OrNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> OrNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> OrNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :or_node + def type: () -> :or_node + + # See `Node.type`. + # -- + # : () -> :or_node + def self.type: () -> :or_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # left -> Node + # + # 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). + # + # left or right + # ^^^^ + # + # 1 || 2 + # ^ + # -- + # : () -> Prism::node + def left: () -> Prism::node + + # :call-seq: + # right -> Node + # + # Represents the right side of the expression. + # + # left || right + # ^^^^^ + # + # 1 or 2 + # ^ + # -- + # : () -> Prism::node + def right: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `or` keyword or the `||` operator. + # + # left or right + # ^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the list of parameters on a method, block, or lambda definition. + # + # def a(b, c, d) + # ^^^^^^^ + # end + class ParametersNode < Node + @block: (BlockParameterNode | NoBlockParameterNode)? + + @keyword_rest: (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)? + + @keywords: Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode] + + @posts: Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode] + + @rest: (RestParameterNode | ImplicitRestNode)? + + @optionals: Array[OptionalParameterNode] + + @requireds: Array[RequiredParameterNode | MultiTargetNode] + + # Initialize a new ParametersNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[RequiredParameterNode | MultiTargetNode] requireds, Array[OptionalParameterNode] optionals, (RestParameterNode | ImplicitRestNode)? rest, Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode] posts, Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode] keywords, (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)? keyword_rest, (BlockParameterNode | NoBlockParameterNode)? block) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[RequiredParameterNode | MultiTargetNode] requireds, Array[OptionalParameterNode] optionals, (RestParameterNode | ImplicitRestNode)? rest, Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode] posts, Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode] keywords, (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)? keyword_rest, (BlockParameterNode | NoBlockParameterNode)? block) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ParametersNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?requireds: Array[RequiredParameterNode | MultiTargetNode], ?optionals: Array[OptionalParameterNode], ?rest: (RestParameterNode | ImplicitRestNode)?, ?posts: Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode], ?keywords: Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode], ?keyword_rest: (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)?, ?block: (BlockParameterNode | NoBlockParameterNode)?) -> ParametersNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?requireds: Array[RequiredParameterNode | MultiTargetNode], ?optionals: Array[OptionalParameterNode], ?rest: (RestParameterNode | ImplicitRestNode)?, ?posts: Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode], ?keywords: Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode], ?keyword_rest: (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)?, ?block: (BlockParameterNode | NoBlockParameterNode)?) -> ParametersNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :parameters_node + def type: () -> :parameters_node + + # See `Node.type`. + # -- + # : () -> :parameters_node + def self.type: () -> :parameters_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # requireds -> Array[RequiredParameterNode | MultiTargetNode] + # + # Returns the `requireds` attribute. + # -- + # : () -> Array[RequiredParameterNode | MultiTargetNode] + def requireds: () -> Array[RequiredParameterNode | MultiTargetNode] + + # :call-seq: + # optionals -> Array[OptionalParameterNode] + # + # Returns the `optionals` attribute. + # -- + # : () -> Array[OptionalParameterNode] + def optionals: () -> Array[OptionalParameterNode] + + # :call-seq: + # rest -> RestParameterNode | ImplicitRestNode | nil + # + # Returns the `rest` attribute. + # -- + # : () -> (RestParameterNode | ImplicitRestNode)? + def rest: () -> (RestParameterNode | ImplicitRestNode)? + + # :call-seq: + # posts -> Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode] + # + # Returns the `posts` attribute. + # -- + # : () -> Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode] + def posts: () -> Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode] + + # :call-seq: + # keywords -> Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode] + # + # Returns the `keywords` attribute. + # -- + # : () -> Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode] + def keywords: () -> Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode] + + # :call-seq: + # keyword_rest -> KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode | nil + # + # Returns the `keyword_rest` attribute. + # -- + # : () -> (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)? + def keyword_rest: () -> (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)? + + # :call-seq: + # block -> BlockParameterNode | NoBlockParameterNode | nil + # + # Returns the `block` attribute. + # -- + # : () -> (BlockParameterNode | NoBlockParameterNode)? + def block: () -> (BlockParameterNode | NoBlockParameterNode)? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a parenthesized expression + # + # (10 + 34) + # ^^^^^^^^^ + class ParenthesesNode < Node + @closing_loc: Location + + @opening_loc: Location + + @body: Prism::node? + + # Initialize a new ParenthesesNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? body, Location opening_loc, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? body, Location opening_loc, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ParenthesesNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Prism::node?, ?opening_loc: Location, ?closing_loc: Location) -> ParenthesesNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Prism::node?, ?opening_loc: Location, ?closing_loc: Location) -> ParenthesesNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :parentheses_node + def type: () -> :parentheses_node + + # See `Node.type`. + # -- + # : () -> :parentheses_node + def self.type: () -> :parentheses_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # parentheses that contain multiple potentially void statements + # -- + # : () -> bool + def multiple_statements?: () -> bool + + # :call-seq: + # body -> Node | nil + # + # Returns the `body` attribute. + # -- + # : () -> Prism::node? + def body: () -> Prism::node? + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `^` operator for pinning an expression in a pattern matching expression. + # + # foo in ^(bar) + # ^^^^^^ + class PinnedExpressionNode < Node + @rparen_loc: Location + + @lparen_loc: Location + + @operator_loc: Location + + @expression: Prism::node + + # Initialize a new PinnedExpressionNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node expression, Location operator_loc, Location lparen_loc, Location rparen_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node expression, Location operator_loc, Location lparen_loc, Location rparen_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> PinnedExpressionNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?operator_loc: Location, ?lparen_loc: Location, ?rparen_loc: Location) -> PinnedExpressionNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?operator_loc: Location, ?lparen_loc: Location, ?rparen_loc: Location) -> PinnedExpressionNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :pinned_expression_node + def type: () -> :pinned_expression_node + + # See `Node.type`. + # -- + # : () -> :pinned_expression_node + def self.type: () -> :pinned_expression_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # expression -> Node + # + # The expression used in the pinned expression + # + # foo in ^(bar) + # ^^^ + # -- + # : () -> Prism::node + def expression: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `^` operator + # + # foo in ^(bar) + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # lparen_loc -> Location + # + # The Location of the opening parenthesis. + # + # foo in ^(bar) + # ^ + # -- + # : () -> Location + def lparen_loc: () -> Location + + # :category: Repository + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_lparen_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # rparen_loc -> Location + # + # The Location of the closing parenthesis. + # + # foo in ^(bar) + # ^ + # -- + # : () -> Location + def rparen_loc: () -> Location + + # :category: Repository + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_rparen_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # :call-seq: + # lparen -> String + # + # Slice the location of lparen_loc from the source. + # -- + # : () -> String + def lparen: () -> String + + # :call-seq: + # rparen -> String + # + # Slice the location of rparen_loc from the source. + # -- + # : () -> String + def rparen: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `^` operator for pinning a variable in a pattern matching expression. + # + # foo in ^bar + # ^^^^ + class PinnedVariableNode < Node + @operator_loc: Location + + @variable: LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode + + # Initialize a new PinnedVariableNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode) variable, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode variable, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> PinnedVariableNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?variable: (LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode), ?operator_loc: Location) -> PinnedVariableNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?variable: LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode, ?operator_loc: Location) -> PinnedVariableNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :pinned_variable_node + def type: () -> :pinned_variable_node + + # See `Node.type`. + # -- + # : () -> :pinned_variable_node + def self.type: () -> :pinned_variable_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # variable -> LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode + # + # The variable used in the pinned expression + # + # foo in ^bar + # ^^^ + # -- + # : () -> (LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode) + def variable: () -> (LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode) + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `^` operator + # + # foo in ^bar + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `END` keyword. + # + # END { foo } + # ^^^^^^^^^^^ + class PostExecutionNode < Node + @closing_loc: Location + + @opening_loc: Location + + @keyword_loc: Location + + @statements: StatementsNode? + + # Initialize a new PostExecutionNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, StatementsNode? statements, Location keyword_loc, Location opening_loc, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, StatementsNode? statements, Location keyword_loc, Location opening_loc, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> PostExecutionNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PostExecutionNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PostExecutionNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :post_execution_node + def type: () -> :post_execution_node + + # See `Node.type`. + # -- + # : () -> :post_execution_node + def self.type: () -> :post_execution_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `BEGIN` keyword. + # + # BEGIN { foo } + # ^^^^^^^^^^^^^ + class PreExecutionNode < Node + @closing_loc: Location + + @opening_loc: Location + + @keyword_loc: Location + + @statements: StatementsNode? + + # Initialize a new PreExecutionNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, StatementsNode? statements, Location keyword_loc, Location opening_loc, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, StatementsNode? statements, Location keyword_loc, Location opening_loc, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> PreExecutionNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PreExecutionNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PreExecutionNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :pre_execution_node + def type: () -> :pre_execution_node + + # See `Node.type`. + # -- + # : () -> :pre_execution_node + def self.type: () -> :pre_execution_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # The top level node of any parse tree. + class ProgramNode < Node + @statements: StatementsNode + + @locals: Array[Symbol] + + # Initialize a new ProgramNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, StatementsNode statements) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, StatementsNode statements) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ProgramNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?statements: StatementsNode) -> ProgramNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?statements: StatementsNode) -> ProgramNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :program_node + def type: () -> :program_node + + # See `Node.type`. + # -- + # : () -> :program_node + def self.type: () -> :program_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # locals -> Array[Symbol] + # + # Returns the `locals` attribute. + # -- + # : () -> Array[Symbol] + def locals: () -> Array[Symbol] + + # :call-seq: + # statements -> StatementsNode + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode + def statements: () -> StatementsNode + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `..` or `...` operators. + # + # 1..2 + # ^^^^ + # + # c if a =~ /left/ ... b =~ /right/ + # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + class RangeNode < Node + @operator_loc: Location + + @right: Prism::node? + + @left: Prism::node? + + # Initialize a new RangeNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? left, Prism::node? right, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? left, Prism::node? right, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RangeNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> RangeNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> RangeNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :range_node + def type: () -> :range_node + + # See `Node.type`. + # -- + # : () -> :range_node + def self.type: () -> :range_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # ... operator + # -- + # : () -> bool + def exclude_end?: () -> bool + + # :call-seq: + # left -> Node | nil + # + # 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). + # + # 1... + # ^ + # + # hello...goodbye + # ^^^^^ + # -- + # : () -> Prism::node? + def left: () -> Prism::node? + + # :call-seq: + # right -> Node | nil + # + # 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). + # + # ..5 + # ^ + # + # 1...foo + # ^^^ + # If neither right-hand or left-hand side was included, this will be a MissingNode. + # -- + # : () -> Prism::node? + def right: () -> Prism::node? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `..` or `...` operator. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a rational number literal. + # + # 1.0r + # ^^^^ + class RationalNode < Node + @denominator: Integer + + @numerator: Integer + + # Initialize a new RationalNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Integer numerator, Integer denominator) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Integer numerator, Integer denominator) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RationalNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?numerator: Integer, ?denominator: Integer) -> RationalNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?numerator: Integer, ?denominator: Integer) -> RationalNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :rational_node + def type: () -> :rational_node + + # See `Node.type`. + # -- + # : () -> :rational_node + def self.type: () -> :rational_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # 0b prefix + # -- + # : () -> bool + def binary?: () -> bool + + # :category: Flags + # 0d or no prefix + # -- + # : () -> bool + def decimal?: () -> bool + + # :category: Flags + # 0o or 0 prefix + # -- + # : () -> bool + def octal?: () -> bool + + # :category: Flags + # 0x prefix + # -- + # : () -> bool + def hexadecimal?: () -> bool + + # :call-seq: + # numerator -> Integer + # + # The numerator of the rational number. + # + # 1.5r # numerator 3 + # -- + # : () -> Integer + def numerator: () -> Integer + + # :call-seq: + # denominator -> Integer + # + # The denominator of the rational number. + # + # 1.5r # denominator 2 + # -- + # : () -> Integer + def denominator: () -> Integer + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `redo` keyword. + # + # redo + # ^^^^ + class RedoNode < Node + # Initialize a new RedoNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RedoNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> RedoNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> RedoNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :redo_node + def type: () -> :redo_node + + # See `Node.type`. + # -- + # : () -> :redo_node + def self.type: () -> :redo_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a regular expression literal with no interpolation. + # + # /foo/i + # ^^^^^^ + class RegularExpressionNode < Node + @unescaped: String + + @closing_loc: Location + + @content_loc: Location + + @opening_loc: Location + + # Initialize a new RegularExpressionNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Location content_loc, Location closing_loc, String unescaped) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Location content_loc, Location closing_loc, String unescaped) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RegularExpressionNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> RegularExpressionNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> RegularExpressionNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :regular_expression_node + def type: () -> :regular_expression_node + + # See `Node.type`. + # -- + # : () -> :regular_expression_node + def self.type: () -> :regular_expression_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # i - ignores the case of characters when matching + # -- + # : () -> bool + def ignore_case?: () -> bool + + # :category: Flags + # x - ignores whitespace and allows comments in regular expressions + # -- + # : () -> bool + def extended?: () -> bool + + # :category: Flags + # m - allows $ to match the end of lines within strings + # -- + # : () -> bool + def multi_line?: () -> bool + + # :category: Flags + # o - only interpolates values into the regular expression once + # -- + # : () -> bool + def once?: () -> bool + + # :category: Flags + # e - forces the EUC-JP encoding + # -- + # : () -> bool + def euc_jp?: () -> bool + + # :category: Flags + # n - forces the ASCII-8BIT encoding + # -- + # : () -> bool + def ascii_8bit?: () -> bool + + # :category: Flags + # s - forces the Windows-31J encoding + # -- + # : () -> bool + def windows_31j?: () -> bool + + # :category: Flags + # u - forces the UTF-8 encoding + # -- + # : () -> bool + def utf_8?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to US-ASCII + # -- + # : () -> bool + def forced_us_ascii_encoding?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # content_loc -> Location + # + # Returns the Location represented by `content_loc`. + # -- + # : () -> Location + def content_loc: () -> Location + + # :category: Repository + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_content_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # unescaped -> String + # + # Returns the `unescaped` attribute. + # -- + # : () -> String + def unescaped: () -> String + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # content -> String + # + # Slice the location of content_loc from the source. + # -- + # : () -> String + def content: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a required keyword parameter to a method, block, or lambda definition. + # + # def a(b: ) + # ^^ + # end + class RequiredKeywordParameterNode < Node + @name_loc: Location + + @name: Symbol + + # Initialize a new RequiredKeywordParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RequiredKeywordParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location) -> RequiredKeywordParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location) -> RequiredKeywordParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :required_keyword_parameter_node + def type: () -> :required_keyword_parameter_node + + # See `Node.type`. + # -- + # : () -> :required_keyword_parameter_node + def self.type: () -> :required_keyword_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a required parameter to a method, block, or lambda definition. + # + # def a(b) + # ^ + # end + class RequiredParameterNode < Node + @name: Symbol + + # Initialize a new RequiredParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RequiredParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> RequiredParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> RequiredParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :required_parameter_node + def type: () -> :required_parameter_node + + # See `Node.type`. + # -- + # : () -> :required_parameter_node + def self.type: () -> :required_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an expression modified with a rescue. + # + # foo rescue nil + # ^^^^^^^^^^^^^^ + class RescueModifierNode < Node + @rescue_expression: Prism::node + + @keyword_loc: Location + + @expression: Prism::node + + # Initialize a new RescueModifierNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node expression, Location keyword_loc, Prism::node rescue_expression) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node expression, Location keyword_loc, Prism::node rescue_expression) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RescueModifierNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?keyword_loc: Location, ?rescue_expression: Prism::node) -> RescueModifierNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?keyword_loc: Location, ?rescue_expression: Prism::node) -> RescueModifierNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :rescue_modifier_node + def type: () -> :rescue_modifier_node + + # See `Node.type`. + # -- + # : () -> :rescue_modifier_node + def self.type: () -> :rescue_modifier_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # expression -> Node + # + # Returns the `expression` attribute. + # -- + # : () -> Prism::node + def expression: () -> Prism::node + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # rescue_expression -> Node + # + # Returns the `rescue_expression` attribute. + # -- + # : () -> Prism::node + def rescue_expression: () -> Prism::node + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a rescue statement. + # + # begin + # rescue Foo, *splat, Bar => ex + # foo + # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + # end + # + # `Foo, *splat, Bar` are in the `exceptions` field. `ex` is in the `reference` field. + class RescueNode < Node + @subsequent: RescueNode? + + @statements: StatementsNode? + + @then_keyword_loc: Location? + + @reference: (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)? + + @operator_loc: Location? + + @exceptions: Array[Prism::node] + + @keyword_loc: Location + + # Initialize a new RescueNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Array[Prism::node] exceptions, Location? operator_loc, (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)? reference, Location? then_keyword_loc, StatementsNode? statements, RescueNode? subsequent) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Array[Prism::node] exceptions, Location? operator_loc, (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)? reference, Location? then_keyword_loc, StatementsNode? statements, RescueNode? subsequent) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RescueNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?exceptions: Array[Prism::node], ?operator_loc: Location?, ?reference: (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)?, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: RescueNode?) -> RescueNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?exceptions: Array[Prism::node], ?operator_loc: Location?, ?reference: (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)?, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: RescueNode?) -> RescueNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :rescue_node + def type: () -> :rescue_node + + # See `Node.type`. + # -- + # : () -> :rescue_node + def self.type: () -> :rescue_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # exceptions -> Array[Node] + # + # Returns the `exceptions` attribute. + # -- + # : () -> Array[Prism::node] + def exceptions: () -> Array[Prism::node] + + # :category: Locations + # :call-seq: + # operator_loc -> Location | nil + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location? + def operator_loc: () -> Location? + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # reference -> LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode | nil + # + # Returns the `reference` attribute. + # -- + # : () -> (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)? + def reference: () -> (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)? + + # :category: Locations + # :call-seq: + # then_keyword_loc -> Location | nil + # + # Returns the Location represented by `then_keyword_loc`. + # -- + # : () -> Location? + def then_keyword_loc: () -> Location? + + # :category: Repository + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_then_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :call-seq: + # subsequent -> RescueNode | nil + # + # Returns the `subsequent` attribute. + # -- + # : () -> RescueNode? + def subsequent: () -> RescueNode? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # operator -> String | nil + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String? + def operator: () -> String? + + # :call-seq: + # then_keyword -> String | nil + # + # Slice the location of then_keyword_loc from the source. + # -- + # : () -> String? + def then_keyword: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a rest parameter to a method, block, or lambda definition. + # + # def a(*b) + # ^^ + # end + class RestParameterNode < Node + @operator_loc: Location + + @name_loc: Location? + + @name: Symbol? + + # Initialize a new RestParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol? name, Location? name_loc, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol? name, Location? name_loc, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RestParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> RestParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> RestParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :rest_parameter_node + def type: () -> :rest_parameter_node + + # See `Node.type`. + # -- + # : () -> :rest_parameter_node + def self.type: () -> :rest_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol | nil + # + # Returns the `name` attribute. + # -- + # : () -> Symbol? + def name: () -> Symbol? + + # :category: Locations + # :call-seq: + # name_loc -> Location | nil + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location? + def name_loc: () -> Location? + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_name_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `retry` keyword. + # + # retry + # ^^^^^ + class RetryNode < Node + # Initialize a new RetryNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RetryNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> RetryNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> RetryNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :retry_node + def type: () -> :retry_node + + # See `Node.type`. + # -- + # : () -> :retry_node + def self.type: () -> :retry_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `return` keyword. + # + # return 1 + # ^^^^^^^^ + class ReturnNode < Node + @arguments: ArgumentsNode? + + @keyword_loc: Location + + # Initialize a new ReturnNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, ArgumentsNode? arguments) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, ArgumentsNode? arguments) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ReturnNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?arguments: ArgumentsNode?) -> ReturnNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?arguments: ArgumentsNode?) -> ReturnNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :return_node + def type: () -> :return_node + + # See `Node.type`. + # -- + # : () -> :return_node + def self.type: () -> :return_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Returns the `arguments` attribute. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the `self` keyword. + # + # self + # ^^^^ + class SelfNode < Node + # Initialize a new SelfNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SelfNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> SelfNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> SelfNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :self_node + def type: () -> :self_node + + # See `Node.type`. + # -- + # : () -> :self_node + def self.type: () -> :self_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # This node wraps a constant write to indicate that when the value is written, it should have its shareability state modified. + # + # # shareable_constant_value: literal + # C = { a: 1 } + # ^^^^^^^^^^^^ + class ShareableConstantNode < Node + @write: ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode + + # Initialize a new ShareableConstantNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode) write) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode write) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ShareableConstantNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?write: (ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode)) -> ShareableConstantNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?write: ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode) -> ShareableConstantNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :shareable_constant_node + def type: () -> :shareable_constant_node + + # See `Node.type`. + # -- + # : () -> :shareable_constant_node + def self.type: () -> :shareable_constant_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # constant writes that should be modified with shareable constant value literal + # -- + # : () -> bool + def literal?: () -> bool + + # :category: Flags + # constant writes that should be modified with shareable constant value experimental everything + # -- + # : () -> bool + def experimental_everything?: () -> bool + + # :category: Flags + # constant writes that should be modified with shareable constant value experimental copy + # -- + # : () -> bool + def experimental_copy?: () -> bool + + # :call-seq: + # write -> ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode + # + # The constant write that should be modified with the shareability state. + # -- + # : () -> (ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode) + def write: () -> (ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode) + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a singleton class declaration involving the `class` keyword. + # + # class << self end + # ^^^^^^^^^^^^^^^^^ + class SingletonClassNode < Node + @end_keyword_loc: Location + + @body: (StatementsNode | BeginNode)? + + @expression: Prism::node + + @operator_loc: Location + + @class_keyword_loc: Location + + @locals: Array[Symbol] + + # Initialize a new SingletonClassNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location class_keyword_loc, Location operator_loc, Prism::node expression, (StatementsNode | BeginNode)? body, Location end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location class_keyword_loc, Location operator_loc, Prism::node expression, (StatementsNode | BeginNode)? body, Location end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SingletonClassNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?operator_loc: Location, ?expression: Prism::node, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location) -> SingletonClassNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?operator_loc: Location, ?expression: Prism::node, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location) -> SingletonClassNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :singleton_class_node + def type: () -> :singleton_class_node + + # See `Node.type`. + # -- + # : () -> :singleton_class_node + def self.type: () -> :singleton_class_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # locals -> Array[Symbol] + # + # Returns the `locals` attribute. + # -- + # : () -> Array[Symbol] + def locals: () -> Array[Symbol] + + # :category: Locations + # :call-seq: + # class_keyword_loc -> Location + # + # Returns the Location represented by `class_keyword_loc`. + # -- + # : () -> Location + def class_keyword_loc: () -> Location + + # :category: Repository + # Save the class_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_class_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # expression -> Node + # + # Returns the `expression` attribute. + # -- + # : () -> Prism::node + def expression: () -> Prism::node + + # :call-seq: + # body -> StatementsNode | BeginNode | nil + # + # Returns the `body` attribute. + # -- + # : () -> (StatementsNode | BeginNode)? + def body: () -> (StatementsNode | BeginNode)? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location + # + # Returns the Location represented by `end_keyword_loc`. + # -- + # : () -> Location + def end_keyword_loc: () -> Location + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # class_keyword -> String + # + # Slice the location of class_keyword_loc from the source. + # -- + # : () -> String + def class_keyword: () -> String + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # :call-seq: + # end_keyword -> String + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String + def end_keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `__ENCODING__` keyword. + # + # __ENCODING__ + # ^^^^^^^^^^^^ + class SourceEncodingNode < Node + # Initialize a new SourceEncodingNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SourceEncodingNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> SourceEncodingNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> SourceEncodingNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :source_encoding_node + def type: () -> :source_encoding_node + + # See `Node.type`. + # -- + # : () -> :source_encoding_node + def self.type: () -> :source_encoding_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `__FILE__` keyword. + # + # __FILE__ + # ^^^^^^^^ + class SourceFileNode < Node + @filepath: String + + # Initialize a new SourceFileNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, String filepath) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, String filepath) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SourceFileNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?filepath: String) -> SourceFileNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?filepath: String) -> SourceFileNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :source_file_node + def type: () -> :source_file_node + + # See `Node.type`. + # -- + # : () -> :source_file_node + def self.type: () -> :source_file_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Flags + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal` + # -- + # : () -> bool + def frozen?: () -> bool + + # :category: Flags + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` + # -- + # : () -> bool + def mutable?: () -> bool + + # :call-seq: + # filepath -> String + # + # Represents the file path being parsed. This corresponds directly to the `filepath` option given to the various `Prism.parse*` APIs. + # -- + # : () -> String + def filepath: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `__LINE__` keyword. + # + # __LINE__ + # ^^^^^^^^ + class SourceLineNode < Node + # Initialize a new SourceLineNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SourceLineNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> SourceLineNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> SourceLineNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :source_line_node + def type: () -> :source_line_node + + # See `Node.type`. + # -- + # : () -> :source_line_node + def self.type: () -> :source_line_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the splat operator. + # + # [*a] + # ^^ + class SplatNode < Node + @expression: Prism::node? + + @operator_loc: Location + + # Initialize a new SplatNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, Prism::node? expression) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, Prism::node? expression) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SplatNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?expression: Prism::node?) -> SplatNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?expression: Prism::node?) -> SplatNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :splat_node + def type: () -> :splat_node + + # See `Node.type`. + # -- + # : () -> :splat_node + def self.type: () -> :splat_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # expression -> Node | nil + # + # Returns the `expression` attribute. + # -- + # : () -> Prism::node? + def expression: () -> Prism::node? + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a set of statements contained within some scope. + # + # foo; bar; baz + # ^^^^^^^^^^^^^ + class StatementsNode < Node + @body: Array[Prism::node] + + # Initialize a new StatementsNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Prism::node] body) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Prism::node] body) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> StatementsNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Array[Prism::node]) -> StatementsNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Array[Prism::node]) -> StatementsNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :statements_node + def type: () -> :statements_node + + # See `Node.type`. + # -- + # : () -> :statements_node + def self.type: () -> :statements_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # body -> Array[Node] + # + # Returns the `body` attribute. + # -- + # : () -> Array[Prism::node] + def body: () -> Array[Prism::node] + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a string literal, a string contained within a `%w` list, or plain string content within an interpolated string. + # + # "foo" + # ^^^^^ + # + # %w[foo] + # ^^^ + # + # "foo #{bar} baz" + # ^^^^ ^^^^ + class StringNode < Node + @unescaped: String + + @closing_loc: Location? + + @content_loc: Location + + @opening_loc: Location? + + # Initialize a new StringNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Location content_loc, Location? closing_loc, String unescaped) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Location content_loc, Location? closing_loc, String unescaped) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> StringNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?content_loc: Location, ?closing_loc: Location?, ?unescaped: String) -> StringNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?content_loc: Location, ?closing_loc: Location?, ?unescaped: String) -> StringNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :string_node + def type: () -> :string_node + + # See `Node.type`. + # -- + # : () -> :string_node + def self.type: () -> :string_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Flags + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal` + # -- + # : () -> bool + def frozen?: () -> bool + + # :category: Flags + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` + # -- + # : () -> bool + def mutable?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # content_loc -> Location + # + # Returns the Location represented by `content_loc`. + # -- + # : () -> Location + def content_loc: () -> Location + + # :category: Repository + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_content_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # unescaped -> String + # + # Returns the `unescaped` attribute. + # -- + # : () -> String + def unescaped: () -> String + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # content -> String + # + # Slice the location of content_loc from the source. + # -- + # : () -> String + def content: () -> String + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `super` keyword with parentheses or arguments. + # + # super() + # ^^^^^^^ + # + # super foo, bar + # ^^^^^^^^^^^^^^ + # + # If no arguments are provided (except for a block), it would be a `ForwardingSuperNode` instead. + class SuperNode < Node + @block: (BlockNode | BlockArgumentNode)? + + @rparen_loc: Location? + + @arguments: ArgumentsNode? + + @lparen_loc: Location? + + @keyword_loc: Location + + # Initialize a new SuperNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? lparen_loc, ArgumentsNode? arguments, Location? rparen_loc, (BlockNode | BlockArgumentNode)? block) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? lparen_loc, ArgumentsNode? arguments, Location? rparen_loc, (BlockNode | BlockArgumentNode)? block) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SuperNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> SuperNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> SuperNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :super_node + def type: () -> :super_node + + # See `Node.type`. + # -- + # : () -> :super_node + def self.type: () -> :super_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # lparen_loc -> Location | nil + # + # Returns the Location represented by `lparen_loc`. + # -- + # : () -> Location? + def lparen_loc: () -> Location? + + # :category: Repository + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_lparen_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Can be only `nil` when there are empty parentheses, like `super()`. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # rparen_loc -> Location | nil + # + # Returns the Location represented by `rparen_loc`. + # -- + # : () -> Location? + def rparen_loc: () -> Location? + + # :category: Repository + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_rparen_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # block -> BlockNode | BlockArgumentNode | nil + # + # Returns the `block` attribute. + # -- + # : () -> (BlockNode | BlockArgumentNode)? + def block: () -> (BlockNode | BlockArgumentNode)? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # lparen -> String | nil + # + # Slice the location of lparen_loc from the source. + # -- + # : () -> String? + def lparen: () -> String? + + # :call-seq: + # rparen -> String | nil + # + # Slice the location of rparen_loc from the source. + # -- + # : () -> String? + def rparen: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents a symbol literal or a symbol contained within a `%i` list. + # + # :foo + # ^^^^ + # + # %i[foo] + # ^^^ + class SymbolNode < Node + @unescaped: String + + @closing_loc: Location? + + @value_loc: Location? + + @opening_loc: Location? + + # Initialize a new SymbolNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Location? value_loc, Location? closing_loc, String unescaped) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Location? value_loc, Location? closing_loc, String unescaped) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SymbolNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?value_loc: Location?, ?closing_loc: Location?, ?unescaped: String) -> SymbolNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?value_loc: Location?, ?closing_loc: Location?, ?unescaped: String) -> SymbolNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :symbol_node + def type: () -> :symbol_node + + # See `Node.type`. + # -- + # : () -> :symbol_node + def self.type: () -> :symbol_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to US-ASCII + # -- + # : () -> bool + def forced_us_ascii_encoding?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # value_loc -> Location | nil + # + # Returns the Location represented by `value_loc`. + # -- + # : () -> Location? + def value_loc: () -> Location? + + # :category: Repository + # Save the value_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_value_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # unescaped -> String + # + # Returns the `unescaped` attribute. + # -- + # : () -> String + def unescaped: () -> String + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # value -> String | nil + # + # Slice the location of value_loc from the source. + # -- + # : () -> String? + def value: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the literal `true` keyword. + # + # true + # ^^^^ + class TrueNode < Node + # Initialize a new TrueNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> TrueNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> TrueNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> TrueNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :true_node + def type: () -> :true_node + + # See `Node.type`. + # -- + # : () -> :true_node + def self.type: () -> :true_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `undef` keyword. + # + # undef :foo, :bar, :baz + # ^^^^^^^^^^^^^^^^^^^^^^ + class UndefNode < Node + @keyword_loc: Location + + @names: Array[SymbolNode | InterpolatedSymbolNode] + + # Initialize a new UndefNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[SymbolNode | InterpolatedSymbolNode] names, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[SymbolNode | InterpolatedSymbolNode] names, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> UndefNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?names: Array[SymbolNode | InterpolatedSymbolNode], ?keyword_loc: Location) -> UndefNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?names: Array[SymbolNode | InterpolatedSymbolNode], ?keyword_loc: Location) -> UndefNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :undef_node + def type: () -> :undef_node + + # See `Node.type`. + # -- + # : () -> :undef_node + def self.type: () -> :undef_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # names -> Array[SymbolNode | InterpolatedSymbolNode] + # + # Returns the `names` attribute. + # -- + # : () -> Array[SymbolNode | InterpolatedSymbolNode] + def names: () -> Array[SymbolNode | InterpolatedSymbolNode] + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `unless` keyword, either in the block form or the modifier form. + # + # bar unless foo + # ^^^^^^^^^^^^^^ + # + # unless foo then bar end + # ^^^^^^^^^^^^^^^^^^^^^^^ + class UnlessNode < Node + @end_keyword_loc: Location? + + @else_clause: ElseNode? + + @statements: StatementsNode? + + @then_keyword_loc: Location? + + @predicate: Prism::node + + @keyword_loc: Location + + # Initialize a new UnlessNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Prism::node predicate, Location? then_keyword_loc, StatementsNode? statements, ElseNode? else_clause, Location? end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Prism::node predicate, Location? then_keyword_loc, StatementsNode? statements, ElseNode? else_clause, Location? end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> UnlessNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?else_clause: ElseNode?, ?end_keyword_loc: Location?) -> UnlessNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?else_clause: ElseNode?, ?end_keyword_loc: Location?) -> UnlessNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :unless_node + def type: () -> :unless_node + + # See `Node.type`. + # -- + # : () -> :unless_node + def self.type: () -> :unless_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # The Location of the `unless` keyword. + # + # unless cond then bar end + # ^^^^^^ + # + # bar unless cond + # ^^^^^^ + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # predicate -> Node + # + # 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). + # + # unless cond then bar end + # ^^^^ + # + # bar unless cond + # ^^^^ + # -- + # : () -> Prism::node + def predicate: () -> Prism::node + + # :category: Locations + # :call-seq: + # then_keyword_loc -> Location | nil + # + # The Location of the `then` keyword, if present. + # + # unless cond then bar end + # ^^^^ + # -- + # : () -> Location? + def then_keyword_loc: () -> Location? + + # :category: Repository + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_then_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # statements -> StatementsNode | nil + # + # The body of statements that will executed if the unless condition is + # falsey. Will be `nil` if no body is provided. + # + # unless cond then bar end + # ^^^ + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :call-seq: + # else_clause -> ElseNode | nil + # + # The else clause of the unless expression, if present. + # + # unless cond then bar else baz end + # ^^^^^^^^^^^^ + # -- + # : () -> ElseNode? + def else_clause: () -> ElseNode? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location | nil + # + # The Location of the `end` keyword, if present. + # + # unless cond then bar end + # ^^^ + # -- + # : () -> Location? + def end_keyword_loc: () -> Location? + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # then_keyword -> String | nil + # + # Slice the location of then_keyword_loc from the source. + # -- + # : () -> String? + def then_keyword: () -> String? + + # :call-seq: + # end_keyword -> String | nil + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String? + def end_keyword: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `until` keyword, either in the block form or the modifier form. + # + # bar until foo + # ^^^^^^^^^^^^^ + # + # until foo do bar end + # ^^^^^^^^^^^^^^^^^^^^ + class UntilNode < Node + @statements: StatementsNode? + + @predicate: Prism::node + + @closing_loc: Location? + + @do_keyword_loc: Location? + + @keyword_loc: Location + + # Initialize a new UntilNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? do_keyword_loc, Location? closing_loc, Prism::node predicate, StatementsNode? statements) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? do_keyword_loc, Location? closing_loc, Prism::node predicate, StatementsNode? statements) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> UntilNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> UntilNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> UntilNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :until_node + def type: () -> :until_node + + # See `Node.type`. + # -- + # : () -> :until_node + def self.type: () -> :until_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a loop after a begin statement, so the body is executed first before the condition + # -- + # : () -> bool + def begin_modifier?: () -> bool + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # do_keyword_loc -> Location | nil + # + # Returns the Location represented by `do_keyword_loc`. + # -- + # : () -> Location? + def do_keyword_loc: () -> Location? + + # :category: Repository + # Save the do_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_do_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # predicate -> Node + # + # Returns the `predicate` attribute. + # -- + # : () -> Prism::node + def predicate: () -> Prism::node + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # do_keyword -> String | nil + # + # Slice the location of do_keyword_loc from the source. + # -- + # : () -> String? + def do_keyword: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `when` keyword within a case statement. + # + # case true + # when true + # ^^^^^^^^^ + # end + class WhenNode < Node + @statements: StatementsNode? + + @then_keyword_loc: Location? + + @conditions: Array[Prism::node] + + @keyword_loc: Location + + # Initialize a new WhenNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Array[Prism::node] conditions, Location? then_keyword_loc, StatementsNode? statements) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Array[Prism::node] conditions, Location? then_keyword_loc, StatementsNode? statements) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> WhenNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?conditions: Array[Prism::node], ?then_keyword_loc: Location?, ?statements: StatementsNode?) -> WhenNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?conditions: Array[Prism::node], ?then_keyword_loc: Location?, ?statements: StatementsNode?) -> WhenNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :when_node + def type: () -> :when_node + + # See `Node.type`. + # -- + # : () -> :when_node + def self.type: () -> :when_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # conditions -> Array[Node] + # + # Returns the `conditions` attribute. + # -- + # : () -> Array[Prism::node] + def conditions: () -> Array[Prism::node] + + # :category: Locations + # :call-seq: + # then_keyword_loc -> Location | nil + # + # Returns the Location represented by `then_keyword_loc`. + # -- + # : () -> Location? + def then_keyword_loc: () -> Location? + + # :category: Repository + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_then_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # then_keyword -> String | nil + # + # Slice the location of then_keyword_loc from the source. + # -- + # : () -> String? + def then_keyword: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `while` keyword, either in the block form or the modifier form. + # + # bar while foo + # ^^^^^^^^^^^^^ + # + # while foo do bar end + # ^^^^^^^^^^^^^^^^^^^^ + class WhileNode < Node + @statements: StatementsNode? + + @predicate: Prism::node + + @closing_loc: Location? + + @do_keyword_loc: Location? + + @keyword_loc: Location + + # Initialize a new WhileNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? do_keyword_loc, Location? closing_loc, Prism::node predicate, StatementsNode? statements) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? do_keyword_loc, Location? closing_loc, Prism::node predicate, StatementsNode? statements) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> WhileNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> WhileNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> WhileNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :while_node + def type: () -> :while_node + + # See `Node.type`. + # -- + # : () -> :while_node + def self.type: () -> :while_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a loop after a begin statement, so the body is executed first before the condition + # -- + # : () -> bool + def begin_modifier?: () -> bool + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # do_keyword_loc -> Location | nil + # + # Returns the Location represented by `do_keyword_loc`. + # -- + # : () -> Location? + def do_keyword_loc: () -> Location? + + # :category: Repository + # Save the do_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_do_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # predicate -> Node + # + # Returns the `predicate` attribute. + # -- + # : () -> Prism::node + def predicate: () -> Prism::node + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # do_keyword -> String | nil + # + # Slice the location of do_keyword_loc from the source. + # -- + # : () -> String? + def do_keyword: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents an xstring literal with no interpolation. + # + # `foo` + # ^^^^^ + class XStringNode < Node + @unescaped: String + + @closing_loc: Location + + @content_loc: Location + + @opening_loc: Location + + # Initialize a new XStringNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Location content_loc, Location closing_loc, String unescaped) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Location content_loc, Location closing_loc, String unescaped) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> XStringNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> XStringNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> XStringNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :x_string_node + def type: () -> :x_string_node + + # See `Node.type`. + # -- + # : () -> :x_string_node + def self.type: () -> :x_string_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # content_loc -> Location + # + # Returns the Location represented by `content_loc`. + # -- + # : () -> Location + def content_loc: () -> Location + + # :category: Repository + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_content_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # unescaped -> String + # + # Returns the `unescaped` attribute. + # -- + # : () -> String + def unescaped: () -> String + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # content -> String + # + # Slice the location of content_loc from the source. + # -- + # : () -> String + def content: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Represents the use of the `yield` keyword. + # + # yield 1 + # ^^^^^^^ + class YieldNode < Node + @rparen_loc: Location? + + @arguments: ArgumentsNode? + + @lparen_loc: Location? + + @keyword_loc: Location + + # Initialize a new YieldNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? lparen_loc, ArgumentsNode? arguments, Location? rparen_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? lparen_loc, ArgumentsNode? arguments, Location? rparen_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> YieldNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?) -> YieldNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?) -> YieldNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :yield_node + def type: () -> :yield_node + + # See `Node.type`. + # -- + # : () -> :yield_node + def self.type: () -> :yield_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # lparen_loc -> Location | nil + # + # Returns the Location represented by `lparen_loc`. + # -- + # : () -> Location? + def lparen_loc: () -> Location? + + # :category: Repository + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_lparen_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Returns the `arguments` attribute. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # rparen_loc -> Location | nil + # + # Returns the Location represented by `rparen_loc`. + # -- + # : () -> Location? + def rparen_loc: () -> Location? + + # :category: Repository + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_rparen_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # lparen -> String | nil + # + # Slice the location of lparen_loc from the source. + # -- + # : () -> String? + def lparen: () -> String? + + # :call-seq: + # rparen -> String | nil + # + # Slice the location of rparen_loc from the source. + # -- + # : () -> String? + def rparen: () -> String? + + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish + end + + # Flags for arguments nodes. + module ArgumentsNodeFlags + # if the arguments contain forwarding + CONTAINS_FORWARDING: untyped + + # if the arguments contain keywords + CONTAINS_KEYWORDS: untyped + + # if the arguments contain a keyword splat + CONTAINS_KEYWORD_SPLAT: untyped + + # if the arguments contain a splat + CONTAINS_SPLAT: untyped + + # if the arguments contain multiple splats + CONTAINS_MULTIPLE_SPLATS: untyped + end + + # Flags for array nodes. + module ArrayNodeFlags + # if array contains splat nodes + CONTAINS_SPLAT: untyped + end + + # Flags for call nodes. + module CallNodeFlags + # &. operator + SAFE_NAVIGATION: untyped + + # a call that could have been a local variable + VARIABLE_CALL: untyped + + # a call that is an attribute write, so the value being written should be returned + ATTRIBUTE_WRITE: untyped + + # a call that ignores method visibility + IGNORE_VISIBILITY: untyped + end + + # Flags for nodes that have unescaped content. + module EncodingFlags + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING: untyped + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING: untyped + end + + # Flags for integer nodes that correspond to the base of the integer. + module IntegerBaseFlags + # 0b prefix + BINARY: untyped + + # 0d or no prefix + DECIMAL: untyped + + # 0o or 0 prefix + OCTAL: untyped + + # 0x prefix + HEXADECIMAL: untyped + end + + # Flags for interpolated string nodes that indicated mutability if they are also marked as literals. + module InterpolatedStringNodeFlags + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + FROZEN: untyped + + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + MUTABLE: untyped + end + + # Flags for keyword hash nodes. + module KeywordHashNodeFlags + # a keyword hash which only has `AssocNode` elements all with symbol keys, which means the elements can be treated as keyword arguments + SYMBOL_KEYS: untyped + end + + # Flags for while and until loop nodes. + module LoopFlags + # a loop after a begin statement, so the body is executed first before the condition + BEGIN_MODIFIER: untyped + end + + # Flags for parameter nodes. + module ParameterFlags + # a parameter name that has been repeated in the method signature + REPEATED_PARAMETER: untyped + end + + # Flags for parentheses nodes. + module ParenthesesNodeFlags + # parentheses that contain multiple potentially void statements + MULTIPLE_STATEMENTS: untyped + end + + # Flags for range and flip-flop nodes. + module RangeFlags + # ... operator + EXCLUDE_END: untyped + end + + # Flags for regular expression and match last line nodes. + module RegularExpressionFlags + # i - ignores the case of characters when matching + IGNORE_CASE: untyped + + # x - ignores whitespace and allows comments in regular expressions + EXTENDED: untyped + + # m - allows $ to match the end of lines within strings + MULTI_LINE: untyped + + # o - only interpolates values into the regular expression once + ONCE: untyped + + # e - forces the EUC-JP encoding + EUC_JP: untyped + + # n - forces the ASCII-8BIT encoding + ASCII_8BIT: untyped + + # s - forces the Windows-31J encoding + WINDOWS_31J: untyped + + # u - forces the UTF-8 encoding + UTF_8: untyped + + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING: untyped + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING: untyped + + # internal bytes forced the encoding to US-ASCII + FORCED_US_ASCII_ENCODING: untyped + end + + # Flags for shareable constant nodes. + module ShareableConstantNodeFlags + # constant writes that should be modified with shareable constant value literal + LITERAL: untyped + + # constant writes that should be modified with shareable constant value experimental everything + EXPERIMENTAL_EVERYTHING: untyped + + # constant writes that should be modified with shareable constant value experimental copy + EXPERIMENTAL_COPY: untyped + end + + # Flags for string nodes. + module StringFlags + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING: untyped + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING: untyped + + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal` + FROZEN: untyped + + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` + MUTABLE: untyped + end + + # Flags for symbol nodes. + module SymbolFlags + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING: untyped + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING: untyped + + # internal bytes forced the encoding to US-ASCII + FORCED_US_ASCII_ENCODING: untyped + 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: ::Integer + + # A flag to indicate that the value that the node represents is a value that + # can be determined at parse-time. + STATIC_LITERAL: ::Integer + end +end diff --git a/sig/generated/prism/node_ext.rbs b/sig/generated/prism/node_ext.rbs new file mode 100644 index 0000000000..273e591eb8 --- /dev/null +++ b/sig/generated/prism/node_ext.rbs @@ -0,0 +1,387 @@ +# Generated from lib/prism/node_ext.rb with RBS::Inline + +# -- +# 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 + # : (*String replacements) -> void + def deprecated: (*String replacements) -> void + end + + module RegularExpressionOptions + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + # -- + # : (Integer flags) -> Integer + def self.options: (Integer flags) -> Integer + end + + class InterpolatedMatchLastLineNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + # -- + # : () -> Integer + def options: () -> Integer + end + + class InterpolatedRegularExpressionNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + # -- + # : () -> Integer + def options: () -> Integer + end + + class MatchLastLineNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + # -- + # : () -> Integer + def options: () -> Integer + end + + class RegularExpressionNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + # -- + # : () -> Integer + def options: () -> Integer + end + + module HeredocQuery + # Returns true if this node was represented as a heredoc in the source code. + # -- + # : (String? opening) -> bool? + def self.heredoc?: (String? opening) -> bool? + end + + class InterpolatedStringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + # -- + # : () -> bool? + def heredoc?: () -> bool? + end + + class InterpolatedXStringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + # -- + # : () -> bool? + def heredoc?: () -> bool? + end + + class StringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + # -- + # : () -> bool? + def heredoc?: () -> bool? + + # Occasionally it's helpful to treat a string as if it were interpolated so + # that there's a consistent interface for working with strings. + # -- + # : () -> InterpolatedStringNode + def to_interpolated: () -> InterpolatedStringNode + end + + class XStringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + # -- + # : () -> bool? + def heredoc?: () -> bool? + + # Occasionally it's helpful to treat a string as if it were interpolated so + # that there's a consistent interface for working with strings. + # -- + # : () -> InterpolatedXStringNode + def to_interpolated: () -> InterpolatedXStringNode + end + + class ImaginaryNode < Node + # Returns the value of the node as a Ruby Complex. + # -- + # : () -> Complex + def value: () -> Complex + end + + class RationalNode < Node + # Returns the value of the node as a Ruby Rational. + # -- + # : () -> Rational + def value: () -> Rational + + # Returns the value of the node as an IntegerNode or a FloatNode. This + # method is deprecated in favor of #value or #numerator/#denominator. + # -- + # : () -> (IntegerNode | FloatNode) + def numeric: () -> (IntegerNode | FloatNode) + end + + class ConstantReadNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + # -- + # : () -> Array[Symbol] + def full_name_parts: () -> Array[Symbol] + + # Returns the full name of this constant. For example: "Foo" + # -- + # : () -> String + def full_name: () -> String + end + + class ConstantWriteNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + # -- + # : () -> Array[Symbol] + def full_name_parts: () -> Array[Symbol] + + # Returns the full name of this constant. For example: "Foo" + # -- + # : () -> String + def full_name: () -> String + end + + class ConstantPathNode < Node + # An error class raised when dynamic parts are found while computing a + # constant path's full name. For example: + # Foo::Bar::Baz -> does not raise because all parts of the constant path are + # simple constants + # var::Bar::Baz -> raises because the first part of the constant path is a + # local variable + class DynamicPartsInConstantPathError < StandardError + end + + # An error class raised when missing nodes are found while computing a + # constant path's full name. For example: + # Foo:: -> raises because the constant path is missing the last part + class MissingNodesInConstantPathError < StandardError + end + + # Returns the list of parts for the full name of this constant path. + # For example: [:Foo, :Bar] + # -- + # : () -> Array[Symbol] + def full_name_parts: () -> Array[Symbol] + + # Returns the full name of this constant path. For example: "Foo::Bar" + # -- + # : () -> String + def full_name: () -> String + + # Previously, we had a child node on this class that contained either a + # constant read or a missing node. To not cause a breaking change, we + # continue to supply that API. + # -- + # : () -> (ConstantReadNode | MissingNode) + def child: () -> (ConstantReadNode | MissingNode) + end + + class ConstantPathTargetNode < Node + # Returns the list of parts for the full name of this constant path. + # For example: [:Foo, :Bar] + # -- + # : () -> Array[Symbol] + def full_name_parts: () -> Array[Symbol] + + # Returns the full name of this constant path. For example: "Foo::Bar" + # -- + # : () -> String + def full_name: () -> String + + # Previously, we had a child node on this class that contained either a + # constant read or a missing node. To not cause a breaking change, we + # continue to supply that API. + # -- + # : () -> (ConstantReadNode | MissingNode) + def child: () -> (ConstantReadNode | MissingNode) + end + + class ConstantTargetNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + # -- + # : () -> Array[Symbol] + def full_name_parts: () -> Array[Symbol] + + # Returns the full name of this constant. For example: "Foo" + # -- + # : () -> String + def full_name: () -> String + end + + class ParametersNode < Node + # Mirrors the Method#parameters method. + # -- + # : () -> Array[[Symbol, Symbol] | [Symbol]] + def signature: () -> Array[[ Symbol, Symbol ] | [ Symbol ]] + 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. + # -- + # : () -> Location? + def full_message_loc: () -> Location? + end + + class CallOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class ClassVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class ConstantOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class ConstantPathOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class GlobalVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class IndexOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class InstanceVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class LocalVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class CaseMatchNode < Node + # Returns the else clause of the case match node. This method is deprecated + # in favor of #else_clause. + # -- + # : () -> ElseNode? + def consequent: () -> ElseNode? + end + + class CaseNode < Node + # Returns the else clause of the case node. This method is deprecated in + # favor of #else_clause. + # -- + # : () -> ElseNode? + def consequent: () -> ElseNode? + end + + class IfNode < Node + # Returns the subsequent if/elsif/else clause of the if node. This method is + # deprecated in favor of #subsequent. + # -- + # : () -> (IfNode | ElseNode)? + def consequent: () -> (IfNode | ElseNode)? + end + + class RescueNode < Node + # Returns the subsequent rescue clause of the rescue node. This method is + # deprecated in favor of #subsequent. + # -- + # : () -> RescueNode? + def consequent: () -> RescueNode? + end + + class UnlessNode < Node + # Returns the else clause of the unless node. This method is deprecated in + # favor of #else_clause. + # -- + # : () -> ElseNode? + def consequent: () -> ElseNode? + end +end diff --git a/sig/generated/prism/parse_result.rbs b/sig/generated/prism/parse_result.rbs new file mode 100644 index 0000000000..d2b4035960 --- /dev/null +++ b/sig/generated/prism/parse_result.rbs @@ -0,0 +1,843 @@ +# Generated from lib/prism/parse_result.rb with RBS::Inline + +module Prism + # An internal interface for a cache that can be used to compute code + # units from byte offsets. + interface _CodeUnitsCache + def []: (Integer byte_offset) -> Integer + end + + # This represents a source of Ruby code that has been parsed. It is used in + # conjunction with locations to allow them to resolve line numbers and source + # ranges. + class Source + # Create a new source object with the given source code. This method should + # be used instead of `new` and it will return either a `Source` or a + # specialized and more performant `ASCIISource` if no multibyte characters + # are present in the source code. + # + # Note that if you are calling this method manually, you will need to supply + # the start_line and offsets parameters. start_line is the line number that + # the source starts on, which is typically 1 but can be different if this + # source is a subset of a larger source or if this is an eval. offsets is an + # array of byte offsets for the start of each line in the source code, which + # can be calculated by iterating through the source code and recording the + # byte offset whenever a newline character is encountered. + # -- + # : (String source, Integer start_line, Array[Integer] offsets) -> Source + def self.for: (String source, Integer start_line, Array[Integer] offsets) -> Source + + # The source code that this source object represents. + attr_reader source: String + + # The line number where this source starts. + attr_reader start_line: Integer + + # The list of newline byte offsets in the source code. + attr_reader offsets: Array[Integer] + + # Create a new source object with the given source code. + # -- + # : (String source, Integer start_line, Array[Integer] offsets) -> void + def initialize: (String source, Integer start_line, Array[Integer] offsets) -> void + + # Replace the value of start_line with the given value. + # -- + # : (Integer start_line) -> void + def replace_start_line: (Integer start_line) -> void + + # Replace the value of offsets with the given value. + # -- + # : (Array[Integer] offsets) -> void + def replace_offsets: (Array[Integer] offsets) -> void + + # Returns the encoding of the source code, which is set by parameters to the + # parser or by the encoding magic comment. + # -- + # : () -> Encoding + def encoding: () -> Encoding + + # Returns the lines of the source code as an array of strings. + # -- + # : () -> Array[String] + def lines: () -> Array[String] + + # Perform a byteslice on the source code using the given byte offset and + # byte length. + # -- + # : (Integer byte_offset, Integer length) -> String + def slice: (Integer byte_offset, Integer length) -> String + + # Converts the line number and column in bytes to a byte offset. + # -- + # : (Integer line, Integer column) -> Integer + def byte_offset: (Integer line, Integer column) -> Integer + + # Binary search through the offsets to find the line number for the given + # byte offset. + # -- + # : (Integer byte_offset) -> Integer + def line: (Integer byte_offset) -> Integer + + # Return the byte offset of the start of the line corresponding to the given + # byte offset. + # -- + # : (Integer byte_offset) -> Integer + def line_start: (Integer byte_offset) -> Integer + + # Returns the byte offset of the end of the line corresponding to the given + # byte offset. + # -- + # : (Integer byte_offset) -> Integer + def line_end: (Integer byte_offset) -> Integer + + # Return the column in bytes for the given byte offset. + # -- + # : (Integer byte_offset) -> Integer + def column: (Integer byte_offset) -> Integer + + # Return the character offset for the given byte offset. + # -- + # : (Integer byte_offset) -> Integer + def character_offset: (Integer byte_offset) -> Integer + + # Return the column in characters for the given byte offset. + # -- + # : (Integer byte_offset) -> Integer + def character_column: (Integer byte_offset) -> Integer + + # Returns the offset from the start of the file for the given byte offset + # counting in code units for the given encoding. + # + # 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. + # -- + # : (Integer byte_offset, Encoding encoding) -> Integer + def code_units_offset: (Integer byte_offset, Encoding encoding) -> Integer + + # Generate a cache that targets a specific encoding for calculating code + # unit offsets. + # -- + # : (Encoding encoding) -> CodeUnitsCache + def code_units_cache: (Encoding encoding) -> CodeUnitsCache + + # Returns the column in code units for the given encoding for the + # given byte offset. + # -- + # : (Integer byte_offset, Encoding encoding) -> Integer + def code_units_column: (Integer byte_offset, Encoding encoding) -> Integer + + # Freeze this object and the objects it contains. + # -- + # : () -> void + def deep_freeze: () -> void + + private + + # Binary search through the offsets to find the line number for the given + # byte offset. + # -- + # : (Integer byte_offset) -> Integer + def find_line: (Integer byte_offset) -> Integer + 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 + @source: String + + @encoding: Encoding + + # : (String source, Encoding encoding) -> void + def initialize: (String source, Encoding encoding) -> void + + # : (Integer byte_offset, Integer byte_length) -> Integer + def count: (Integer byte_offset, Integer byte_length) -> Integer + end + + class LengthCounter + @source: String + + @encoding: Encoding + + # : (String source, Encoding encoding) -> void + def initialize: (String source, Encoding encoding) -> void + + # : (Integer byte_offset, Integer byte_length) -> Integer + def count: (Integer byte_offset, Integer byte_length) -> Integer + end + + @source: String + + @counter: UTF16Counter | LengthCounter + + @cache: Hash[Integer, Integer] + + @offsets: Array[Integer] + + # Initialize a new cache with the given source and encoding. + # -- + # : (String source, Encoding encoding) -> void + def initialize: (String source, Encoding encoding) -> void + + # Retrieve the code units offset from the given byte offset. + # -- + # : (Integer byte_offset) -> Integer + def []: (Integer byte_offset) -> Integer + 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. + # + # 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. + # -- + # : (Integer byte_offset) -> Integer + def character_offset: (Integer byte_offset) -> Integer + + # Return the column in characters for the given byte offset. + # -- + # : (Integer byte_offset) -> Integer + def character_column: (Integer byte_offset) -> Integer + + # Returns the offset from the start of the file for the given byte offset + # counting in code units for the given encoding. + # + # 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. + # -- + # : (Integer byte_offset, Encoding encoding) -> Integer + def code_units_offset: (Integer byte_offset, Encoding encoding) -> Integer + + # 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. + # -- + # : (Encoding encoding) -> _CodeUnitsCache + def code_units_cache: (Encoding encoding) -> _CodeUnitsCache + + # Specialized version of `code_units_column` that does not depend on + # `code_units_offset`, which is a more expensive operation. This is + # essentially the same as `Prism::Source#column`. + # -- + # : (Integer byte_offset, Encoding encoding) -> Integer + def code_units_column: (Integer byte_offset, Encoding encoding) -> Integer + end + + # This represents a location in the source. + class Location + # A Source object that is used to determine more information from the given + # offset and length. + attr_reader source: Source + + # The byte offset from the beginning of the source where this location + # starts. + attr_reader start_offset: Integer + + # The length of this location in bytes. + attr_reader length: Integer + + @trailing_comments: Array[Comment]? + + @leading_comments: Array[Comment]? + + # Create a new location object with the given source, start byte offset, and + # byte length. + # -- + # : (Source source, Integer start_offset, Integer length) -> void + def initialize: (Source source, Integer start_offset, Integer length) -> void + + # These are the comments that are associated with this location that exist + # before the start of this location. + # -- + # : () -> Array[Comment] + def leading_comments: () -> Array[Comment] + + # Attach a comment to the leading comments of this location. + # -- + # : (Comment comment) -> void + def leading_comment: (Comment comment) -> void + + # These are the comments that are associated with this location that exist + # after the end of this location. + # -- + # : () -> Array[Comment] + def trailing_comments: () -> Array[Comment] + + # Attach a comment to the trailing comments of this location. + # -- + # : (Comment comment) -> void + def trailing_comment: (Comment comment) -> void + + # Returns all comments that are associated with this location (both leading + # and trailing comments). + # -- + # : () -> Array[Comment] + def comments: () -> Array[Comment] + + # Create a new location object with the given options. + # -- + # : (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location + def copy: (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location + + # Returns a new location that is the result of chopping off the last byte. + # -- + # : () -> Location + def chop: () -> Location + + # Returns a string representation of this location. + # -- + # : () -> String + def inspect: () -> String + + # Returns all of the lines of the source code associated with this location. + # -- + # : () -> Array[String] + def source_lines: () -> Array[String] + + # The source code that this location represents. + # -- + # : () -> String + def slice: () -> String + + # The source code that this location represents starting from the beginning + # of the line that this location starts on to the end of the line that this + # location ends on. + # -- + # : () -> String + def slice_lines: () -> String + + # The character offset from the beginning of the source where this location + # starts. + # -- + # : () -> Integer + def start_character_offset: () -> Integer + + # The offset from the start of the file in code units of the given encoding. + # -- + # : (Encoding encoding) -> Integer + def start_code_units_offset: (Encoding encoding) -> Integer + + # The start offset from the start of the file in code units using the given + # cache to fetch or calculate the value. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_start_code_units_offset: (_CodeUnitsCache cache) -> Integer + + # The byte offset from the beginning of the source where this location ends. + # -- + # : () -> Integer + def end_offset: () -> Integer + + # The character offset from the beginning of the source where this location + # ends. + # -- + # : () -> Integer + def end_character_offset: () -> Integer + + # The offset from the start of the file in code units of the given encoding. + # -- + # : (Encoding encoding) -> Integer + def end_code_units_offset: (Encoding encoding) -> Integer + + # The end offset from the start of the file in code units using the given + # cache to fetch or calculate the value. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_end_code_units_offset: (_CodeUnitsCache cache) -> Integer + + # The line number where this location starts. + # -- + # : () -> Integer + def start_line: () -> Integer + + # The content of the line where this location starts before this location. + # -- + # : () -> String + def start_line_slice: () -> String + + # The line number where this location ends. + # -- + # : () -> Integer + def end_line: () -> Integer + + # The column in bytes where this location starts from the start of + # the line. + # -- + # : () -> Integer + def start_column: () -> Integer + + # The column in characters where this location ends from the start of + # the line. + # -- + # : () -> Integer + def start_character_column: () -> Integer + + # The column in code units of the given encoding where this location + # starts from the start of the line. + # -- + # : (?Encoding encoding) -> Integer + def start_code_units_column: (?Encoding encoding) -> Integer + + # The start column in code units using the given cache to fetch or calculate + # the value. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_start_code_units_column: (_CodeUnitsCache cache) -> Integer + + # The column in bytes where this location ends from the start of the + # line. + # -- + # : () -> Integer + def end_column: () -> Integer + + # The column in characters where this location ends from the start of + # the line. + # -- + # : () -> Integer + def end_character_column: () -> Integer + + # The column in code units of the given encoding where this location + # ends from the start of the line. + # -- + # : (?Encoding encoding) -> Integer + def end_code_units_column: (?Encoding encoding) -> Integer + + # The end column in code units using the given cache to fetch or calculate + # the value. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_end_code_units_column: (_CodeUnitsCache cache) -> Integer + + # Implement the hash pattern matching interface for Location. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # Implement the pretty print interface for Location. + # -- + # : (PP q) -> void + def pretty_print: (PP q) -> void + + # Returns true if the given other location is equal to this location. + # -- + # : (untyped other) -> bool + def ==: (untyped other) -> bool + + # Returns a new location that stretches from this location to the given + # other location. Raises an error if this location is not before the other + # location or if they don't share the same source. + # -- + # : (Location other) -> Location + def join: (Location other) -> Location + + # Join this location with the first occurrence of the string in the source + # that occurs after this location on the same line, and return the new + # location. This will raise an error if the string does not exist. + # -- + # : (String string) -> Location + def adjoin: (String string) -> Location + end + + # This represents a comment that was encountered during parsing. It is the + # base class for all comment types. + class Comment + # The Location of this comment in the source. + attr_reader location: Location + + # Create a new comment object with the given location. + # -- + # : (Location location) -> void + def initialize: (Location location) -> void + + # Implement the hash pattern matching interface for Comment. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # Returns the content of the comment by slicing it from the source code. + # -- + # : () -> String + def slice: () -> String + + # Returns true if this comment happens on the same line as other code and + # false if the comment is by itself. This can only be true for inline + # comments and should be false for block comments. + # -- + # : () -> bool + def trailing?: () -> bool + end + + # InlineComment objects are the most common. They correspond to comments in + # the source file like this one that start with #. + class InlineComment < Comment + # Returns true if this comment happens on the same line as other code and + # false if the comment is by itself. + # -- + # : () -> bool + def trailing?: () -> bool + + # Returns a string representation of this comment. + # -- + # : () -> String + def inspect: () -> String + end + + # EmbDocComment objects correspond to comments that are surrounded by =begin + # and =end. + class EmbDocComment < Comment + # Returns false. This can only be true for inline comments. + # -- + # : () -> bool + def trailing?: () -> bool + + # Returns a string representation of this comment. + # -- + # : () -> String + def inspect: () -> String + end + + # This represents a magic comment that was encountered during parsing. + class MagicComment + # A Location object representing the location of the key in the source. + attr_reader key_loc: Location + + # A Location object representing the location of the value in the source. + attr_reader value_loc: Location + + # Create a new magic comment object with the given key and value locations. + # -- + # : (Location key_loc, Location value_loc) -> void + def initialize: (Location key_loc, Location value_loc) -> void + + # Returns the key of the magic comment by slicing it from the source code. + # -- + # : () -> String + def key: () -> String + + # Returns the value of the magic comment by slicing it from the source code. + # -- + # : () -> String + def value: () -> String + + # Implement the hash pattern matching interface for MagicComment. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # Returns a string representation of this magic comment. + # -- + # : () -> String + def inspect: () -> String + end + + # This represents an error that was encountered during parsing. + class ParseError + # The type of error. This is an _internal_ symbol that is used for + # communicating with translation layers. It is not meant to be public API. + attr_reader type: Symbol + + # The message associated with this error. + attr_reader message: String + + # A Location object representing the location of this error in the source. + attr_reader location: Location + + # The level of this error. + attr_reader level: Symbol + + # Create a new error object with the given message and location. + # -- + # : (Symbol type, String message, Location location, Symbol level) -> void + def initialize: (Symbol type, String message, Location location, Symbol level) -> void + + # Implement the hash pattern matching interface for ParseError. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # Returns a string representation of this error. + # -- + # : () -> String + def inspect: () -> String + end + + # This represents a warning that was encountered during parsing. + class ParseWarning + # The type of warning. This is an _internal_ symbol that is used for + # communicating with translation layers. It is not meant to be public API. + attr_reader type: Symbol + + # The message associated with this warning. + attr_reader message: String + + # A Location object representing the location of this warning in the source. + attr_reader location: Location + + # The level of this warning. + attr_reader level: Symbol + + # Create a new warning object with the given message and location. + # -- + # : (Symbol type, String message, Location location, Symbol level) -> void + def initialize: (Symbol type, String message, Location location, Symbol level) -> void + + # Implement the hash pattern matching interface for ParseWarning. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # Returns a string representation of this warning. + # -- + # : () -> String + def inspect: () -> String + end + + # This represents the result of a call to Prism.parse or Prism.parse_file. + # It contains the requested structure, any comments that were encounters, + # and any errors that were encountered. + class Result + # The list of comments that were encountered during parsing. + attr_reader comments: Array[Comment] + + # The list of magic comments that were encountered during parsing. + attr_reader magic_comments: Array[MagicComment] + + # An optional location that represents the location of the __END__ marker + # and the rest of the content of the file. This content is loaded into the + # DATA constant when the file being parsed is the main file being executed. + attr_reader data_loc: Location? + + # The list of errors that were generated during parsing. + attr_reader errors: Array[ParseError] + + # The list of warnings that were generated during parsing. + attr_reader warnings: Array[ParseWarning] + + # A Source instance that represents the source code that was parsed. + attr_reader source: Source + + # Create a new result object with the given values. + # -- + # : (Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize: (Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + + # Implement the hash pattern matching interface for Result. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # Returns the encoding of the source code that was parsed. + # -- + # : () -> Encoding + def encoding: () -> Encoding + + # Returns true if there were no errors during parsing and false if there + # were. + # -- + # : () -> bool + def success?: () -> bool + + # Returns true if there were errors during parsing and false if there were + # not. + # -- + # : () -> bool + def failure?: () -> bool + + # Returns true if the parsed source is an incomplete expression that could + # become valid with additional input. This is useful for REPL contexts (such + # as IRB) where the user may be entering a multi-line expression one line at + # a time and the implementation needs to determine whether to wait for more + # input or to evaluate what has been entered so far. + # + # Concretely, this returns true when every error present is caused by the + # parser reaching the end of the input before a construct was closed (e.g. + # an unclosed string, array, block, or keyword), and returns false when any + # error is caused by a token that makes the input structurally invalid + # regardless of what might follow (e.g. a stray `end`, `]`, or `)` with no + # matching opener). + # + # Examples: + # + # Prism.parse("1 + [").continuable? #=> true (unclosed array) + # Prism.parse("1 + ]").continuable? #=> false (stray ]) + # Prism.parse("tap do").continuable? #=> true (unclosed block) + # Prism.parse("end.tap do").continuable? #=> false (stray end) + # + # -- + # : () -> bool + def continuable?: () -> bool + + # Create a code units cache for the given encoding. + # -- + # : (Encoding encoding) -> _CodeUnitsCache + def code_units_cache: (Encoding encoding) -> _CodeUnitsCache + end + + # This is a result specific to the `parse` and `parse_file` methods. + class ParseResult < Result + # The syntax tree that was parsed from the source code. + attr_reader value: ProgramNode + + # Create a new parse result object with the given values. + # -- + # : (ProgramNode value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize: (ProgramNode value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + + # Implement the hash pattern matching interface for ParseResult. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # Attach the list of comments to their respective locations in the tree. + # -- + # : () -> void + def attach_comments!: () -> void + + # Walk the tree and mark nodes that are on a new line, loosely emulating + # the behavior of CRuby's `:line` tracepoint event. + # -- + # : () -> void + def mark_newlines!: () -> void + + # Returns a string representation of the syntax tree with the errors + # displayed inline. + # -- + # : () -> String + def errors_format: () -> String + end + + # This is a result specific to the `lex` and `lex_file` methods. + class LexResult < Result + # The list of tokens that were parsed from the source code. + attr_reader value: Array[[ Token, Integer ]] + + # Create a new lex result object with the given values. + # -- + # : (Array[[Token, Integer]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize: (Array[[ Token, Integer ]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + + # Implement the hash pattern matching interface for LexResult. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + end + + # This is a result specific to the `parse_lex` and `parse_lex_file` methods. + class ParseLexResult < Result + # A tuple of the syntax tree and the list of tokens that were parsed from + # the source code. + attr_reader value: [ ProgramNode, Array[[ Token, Integer ]] ] + + # Create a new parse lex result object with the given values. + # -- + # : ([ProgramNode, Array[[Token, Integer]]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize: ([ ProgramNode, Array[[ Token, Integer ]] ] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + + # Implement the hash pattern matching interface for ParseLexResult. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + end + + # This represents a token from the Ruby source. + class Token + # The Source object that represents the source this token came from. + attr_reader source: Source + + # The type of token that this token is. + attr_reader type: Symbol + + # A byteslice of the source that this token represents. + attr_reader value: String + + @location: Location | Integer + + # Create a new token object with the given type, value, and location. + # -- + # : (Source source, Symbol type, String value, Location | Integer location) -> void + def initialize: (Source source, Symbol type, String value, Location | Integer location) -> void + + # Implement the hash pattern matching interface for Token. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # A Location object representing the location of this token in the source. + # -- + # : () -> Location + def location: () -> Location + + # Implement the pretty print interface for Token. + # -- + # : (PP q) -> void + def pretty_print: (PP q) -> void + + # Returns true if the given other token is equal to this token. + # -- + # : (untyped other) -> bool + def ==: (untyped other) -> bool + + # Returns a string representation of this token. + # -- + # : () -> String + def inspect: () -> String + + # Freeze this object and the objects it contains. + # -- + # : () -> void + def deep_freeze: () -> void + end + + # This object is passed to the various Prism.* methods that accept the + # `scopes` option as an element of the list. It defines both the local + # variables visible at that scope as well as the forwarding parameters + # available at that scope. + class Scope + # The list of local variables that are defined in this scope. This should be + # defined as an array of symbols. + attr_reader locals: Array[Symbol] + + # The list of local variables that are forwarded to the next scope. This + # should by defined as an array of symbols containing the specific values of + # :*, :**, :&, or :"...". + attr_reader forwarding: Array[Symbol] + + # Create a new scope object with the given locals and forwarding. + # -- + # : (Array[Symbol] locals, Array[Symbol] forwarding) -> void + def initialize: (Array[Symbol] locals, Array[Symbol] forwarding) -> void + end + + # Create a new scope with the given locals and forwarding options that is + # suitable for passing into one of the Prism.* methods that accepts the + # `scopes` option. + # -- + # : (?locals: Array[Symbol], ?forwarding: Array[Symbol]) -> Scope + def self.scope: (?locals: Array[Symbol], ?forwarding: Array[Symbol]) -> Scope +end diff --git a/sig/generated/prism/parse_result/comments.rbs b/sig/generated/prism/parse_result/comments.rbs new file mode 100644 index 0000000000..1dc7ae974b --- /dev/null +++ b/sig/generated/prism/parse_result/comments.rbs @@ -0,0 +1,108 @@ +# Generated from lib/prism/parse_result/comments.rb with RBS::Inline + +module Prism + 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. + # + # It does this by first finding the nearest locations to each comment. + # Locations can either come from nodes directly or from location fields on + # nodes. For example, a `ClassNode` has an overall location encompassing the + # entire class, but it also has a location for the `class` keyword. + # + # Once the nearest locations are found, it determines which one to attach + # to. If it's a trailing comment (a comment on the same line as other source + # code), it will favor attaching to the nearest location that occurs before + # the comment. Otherwise it will favor attaching to the nearest location + # that is after the comment. + class Comments + # An internal interface for a target that comments can be attached + # to. This is either going to be a NodeTarget or a CommentTarget. + interface _CommentTarget + def start_offset: () -> Integer + + def end_offset: () -> Integer + + def encloses?: (Comment) -> bool + + def leading_comment: (Comment) -> void + + def trailing_comment: (Comment) -> void + end + + # A target for attaching comments that is based on a specific node's + # location. + class NodeTarget + # :nodoc: + attr_reader node: node + + # : (node node) -> void + def initialize: (node node) -> void + + # : () -> Integer + def start_offset: () -> Integer + + # : () -> Integer + def end_offset: () -> Integer + + # : (Comment comment) -> bool + def encloses?: (Comment comment) -> bool + + # : (Comment comment) -> void + def leading_comment: (Comment comment) -> void + + # : (Comment comment) -> void + def trailing_comment: (Comment comment) -> void + end + + # A target for attaching comments that is based on a location field on a + # node. For example, the `end` token of a ClassNode. + class LocationTarget + # :nodoc: + attr_reader location: Location + + # : (Location location) -> void + def initialize: (Location location) -> void + + # : () -> Integer + def start_offset: () -> Integer + + # : () -> Integer + def end_offset: () -> Integer + + # : (Comment comment) -> bool + def encloses?: (Comment comment) -> bool + + # : (Comment comment) -> void + def leading_comment: (Comment comment) -> void + + # : (Comment comment) -> void + def trailing_comment: (Comment comment) -> void + end + + # The parse result that we are attaching comments to. + attr_reader parse_result: ParseResult + + # Create a new Comments object that will attach comments to the given + # parse result. + # -- + # : (ParseResult parse_result) -> void + def initialize: (ParseResult parse_result) -> void + + # Attach the comments to their respective locations in the tree by + # mutating the parse result. + # -- + # : () -> void + def attach!: () -> void + + private + + # Responsible for finding the nearest targets to the given comment within + # the context of the given encapsulating node. + # -- + # : (node node, Comment comment) -> [_CommentTarget?, _CommentTarget?, _CommentTarget?] + def nearest_targets: (node node, Comment comment) -> [ _CommentTarget?, _CommentTarget?, _CommentTarget? ] + end + end +end diff --git a/sig/generated/prism/parse_result/errors.rbs b/sig/generated/prism/parse_result/errors.rbs new file mode 100644 index 0000000000..1b97d8a763 --- /dev/null +++ b/sig/generated/prism/parse_result/errors.rbs @@ -0,0 +1,22 @@ +# Generated from lib/prism/parse_result/errors.rb with RBS::Inline + +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: ParseResult + + # Initialize a new set of errors from the given parse result. + # -- + # : (ParseResult parse_result) -> void + def initialize: (ParseResult parse_result) -> void + + # Formats the errors in a human-readable way and return them as a string. + # -- + # : () -> String + def format: () -> String + end + end +end diff --git a/sig/generated/prism/parse_result/newlines.rbs b/sig/generated/prism/parse_result/newlines.rbs new file mode 100644 index 0000000000..45c04783d0 --- /dev/null +++ b/sig/generated/prism/parse_result/newlines.rbs @@ -0,0 +1,129 @@ +# Generated from lib/prism/parse_result/newlines.rb with RBS::Inline + +module Prism + 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: + # + # * if statements + # * unless statements + # * nodes that are children of statements lists + # + # In order to keep track of the newlines, we have a list of offsets that + # come back from the parser. We assign these offsets to the first nodes that + # we find in the tree that are on those lines. + # + # 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 + @lines: Array[bool] + + # Create a new Newlines visitor with the given newline offsets. + # -- + # : (Integer lines) -> void + def initialize: (Integer lines) -> void + + # Permit block nodes to mark newlines within themselves. + # -- + # : (BlockNode node) -> void + def visit_block_node: (BlockNode node) -> void + + # Permit lambda nodes to mark newlines within themselves. + # -- + # : (LambdaNode node) -> void + def visit_lambda_node: (LambdaNode node) -> void + + # Mark if nodes as newlines. + # -- + # : (IfNode node) -> void + def visit_if_node: (IfNode node) -> void + + # Mark unless nodes as newlines. + # -- + # : (UnlessNode node) -> void + def visit_unless_node: (UnlessNode node) -> void + + # Permit statements lists to mark newlines within themselves. + # -- + # : (StatementsNode node) -> void + def visit_statements_node: (StatementsNode node) -> void + end + end + + class Node + @newline_flag: bool + + # : () -> bool + def newline_flag?: () -> bool + + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void + end + + class BeginNode < Node + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void + end + + class ParenthesesNode < Node + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void + end + + class IfNode < Node + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void + end + + class UnlessNode < Node + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void + end + + class UntilNode < Node + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void + end + + class WhileNode < Node + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void + end + + class RescueModifierNode < Node + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void + end + + class InterpolatedMatchLastLineNode < Node + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void + end + + class InterpolatedRegularExpressionNode < Node + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void + end + + class InterpolatedStringNode < Node + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void + end + + class InterpolatedSymbolNode < Node + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void + end + + class InterpolatedXStringNode < Node + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void + end +end diff --git a/sig/generated/prism/pattern.rbs b/sig/generated/prism/pattern.rbs new file mode 100644 index 0000000000..7ea2808da4 --- /dev/null +++ b/sig/generated/prism/pattern.rbs @@ -0,0 +1,156 @@ +# Generated from lib/prism/pattern.rb with RBS::Inline + +module Prism + # A pattern is an object that wraps a Ruby pattern matching expression. The + # expression would normally be passed to an `in` clause within a `case` + # expression or a rightward assignment expression. For example, in the + # following snippet: + # + # case node + # in ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]] + # end + # + # the pattern is the ConstantPathNode[...] expression. + # + # The pattern gets compiled into an object that responds to #call by running + # the #compile method. This method itself will run back through Prism to + # parse the expression into a tree, then walk the tree to generate the + # necessary callable objects. For example, if you wanted to compile the + # expression above into a callable, you would: + # + # callable = Prism::Pattern.new("ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]]").compile + # callable.call(node) + # + # The callable object returned by #compile is guaranteed to respond to #call + # with a single argument, which is the node to match against. It also is + # guaranteed to respond to #===, which means it itself can be used in a `case` + # expression, as in: + # + # case node + # when callable + # end + # + # If the query given to the initializer cannot be compiled into a valid + # matcher (either because of a syntax error or because it is using syntax we + # do not yet support) then a Prism::Pattern::CompilationError will be + # raised. + class Pattern + # Raised when the query given to a pattern is either invalid Ruby syntax or + # is using syntax that we don't yet support. + class CompilationError < StandardError + # Create a new CompilationError with the given representation of the node + # that caused the error. + # -- + # : (String repr) -> void + def initialize: (String repr) -> void + end + + # The query that this pattern was initialized with. + attr_reader query: String + + @compiled: Proc? + + # Create a new pattern with the given query. The query should be a string + # containing a Ruby pattern matching expression. + # -- + # : (String query) -> void + def initialize: (String query) -> void + + # Compile the query into a callable object that can be used to match against + # nodes. + # -- + # : () -> Proc + def compile: () -> Proc + + # Scan the given node and all of its children for nodes that match the + # pattern. If a block is given, it will be called with each node that + # matches the pattern. If no block is given, an enumerator will be returned + # that will yield each node that matches the pattern. + # -- + # : (node root) -> Enumerator[node, void] + # : (node root) { (node) -> void } -> void + def scan: (node root) -> Enumerator[node, void] + | (node root) { (node) -> void } -> void + + private + + # Shortcut for combining two procs into one that returns true if both return + # true. + # -- + # : (Proc left, Proc right) -> Proc + def combine_and: (Proc left, Proc right) -> Proc + + # Shortcut for combining two procs into one that returns true if either + # returns true. + # -- + # : (Proc left, Proc right) -> Proc + def combine_or: (Proc left, Proc right) -> Proc + + # Raise an error because the given node is not supported. Note purposefully + # not typing this method since it is a no return method that Steep does not + # understand. + # -- + # : (node node) -> bot + def compile_error: (node node) -> bot + + # in [foo, bar, baz] + # -- + # : (ArrayPatternNode node) -> Proc + def compile_array_pattern_node: (ArrayPatternNode node) -> Proc + + # in foo | bar + # -- + # : (AlternationPatternNode node) -> Proc + def compile_alternation_pattern_node: (AlternationPatternNode node) -> Proc + + # in Prism::ConstantReadNode + # -- + # : (ConstantPathNode node) -> Proc + def compile_constant_path_node: (ConstantPathNode node) -> Proc + + # in ConstantReadNode + # in String + # -- + # : (ConstantReadNode node) -> Proc + def compile_constant_read_node: (ConstantReadNode node) -> Proc + + # Compile a name associated with a constant. + # -- + # : ((ConstantPathNode | ConstantReadNode) node, Symbol name) -> Proc + def compile_constant_name: (ConstantPathNode | ConstantReadNode node, Symbol name) -> Proc + + # in InstanceVariableReadNode[name: Symbol] + # in { name: Symbol } + # -- + # : (HashPatternNode node) -> Proc + def compile_hash_pattern_node: (HashPatternNode node) -> Proc + + # in nil + # -- + # : (NilNode node) -> Proc + def compile_nil_node: (NilNode node) -> Proc + + # in /foo/ + # -- + # : (RegularExpressionNode node) -> Proc + def compile_regular_expression_node: (RegularExpressionNode node) -> Proc + + # in "" + # in "foo" + # -- + # : (StringNode node) -> Proc + def compile_string_node: (StringNode node) -> Proc + + # in :+ + # in :foo + # -- + # : (SymbolNode node) -> Proc + def compile_symbol_node: (SymbolNode node) -> Proc + + # Compile any kind of node. Dispatch out to the individual compilation + # methods based on the type of node. + # -- + # : (node node) -> Proc + def compile_node: (node node) -> Proc + end +end diff --git a/sig/generated/prism/reflection.rbs b/sig/generated/prism/reflection.rbs new file mode 100644 index 0000000000..8237da3a2e --- /dev/null +++ b/sig/generated/prism/reflection.rbs @@ -0,0 +1,101 @@ +# Generated from lib/prism/reflection.rb with RBS::Inline + +module Prism + # The Reflection module provides the ability to reflect on the structure of + # the syntax tree itself, as opposed to looking at a single syntax tree. This + # is useful in metaprogramming contexts. + module Reflection + # A field represents a single piece of data on a node. It is the base class + # for all other field types. + class Field + # The name of the field. + attr_reader name: Symbol + + # Initializes the field with the given name. + # -- + # : (Symbol name) -> void + def initialize: (Symbol name) -> void + end + + # A node field represents a single child node in the syntax tree. It + # resolves to a Prism::Node in Ruby. + class NodeField < Field + end + + # An optional node field represents a single child node in the syntax tree + # that may or may not be present. It resolves to either a Prism::Node or nil + # in Ruby. + class OptionalNodeField < Field + end + + # A node list field represents a list of child nodes in the syntax tree. It + # resolves to an array of Prism::Node instances in Ruby. + class NodeListField < Field + end + + # A constant field represents a constant value on a node. Effectively, it + # represents an identifier found within the source. It resolves to a symbol + # in Ruby. + class ConstantField < Field + end + + # An optional constant field represents a constant value on a node that may + # or may not be present. It resolves to either a symbol or nil in Ruby. + class OptionalConstantField < Field + end + + # A constant list field represents a list of constant values on a node. It + # resolves to an array of symbols in Ruby. + class ConstantListField < Field + end + + # A string field represents a string value on a node. It almost always + # represents the unescaped value of a string-like literal. It resolves to a + # string in Ruby. + class StringField < Field + end + + # A location field represents the location of some part of the node in the + # source code. For example, the location of a keyword or an operator. It + # resolves to a Prism::Location in Ruby. + class LocationField < Field + end + + # An optional location field represents the location of some part of the + # node in the source code that may or may not be present. It resolves to + # either a Prism::Location or nil in Ruby. + class OptionalLocationField < Field + end + + # An integer field represents an integer value. It is used to represent the + # value of an integer literal, the depth of local variables, and the number + # of a numbered reference. It resolves to an Integer in Ruby. + class IntegerField < Field + end + + # A float field represents a double-precision floating point value. It is + # used exclusively to represent the value of a floating point literal. It + # resolves to a Float in Ruby. + class FloatField < Field + end + + # A flags field represents a bitset of flags on a node. It resolves to an + # integer in Ruby. Note that the flags cannot be accessed directly on the + # node because the integer is kept private. Instead, the various flags in + # the bitset should be accessed through their query methods. + class FlagsField < Field + # The names of the flags in the bitset. + attr_reader flags: Array[Symbol] + + # Initializes the flags field with the given name and flags. + # -- + # : (Symbol name, Array[Symbol] flags) -> void + def initialize: (Symbol name, Array[Symbol] flags) -> void + end + + # Returns the fields for the given node. + # -- + # : (singleton(Node) node) -> Array[Field] + def self.fields_for: (singleton(Node) node) -> Array[Field] + end +end diff --git a/sig/generated/prism/relocation.rbs b/sig/generated/prism/relocation.rbs new file mode 100644 index 0000000000..35238609ca --- /dev/null +++ b/sig/generated/prism/relocation.rbs @@ -0,0 +1,502 @@ +# Generated from lib/prism/relocation.rb with RBS::Inline + +module Prism + # Prism parses deterministically for the same input. This provides a nice + # property that is exposed through the #node_id API on nodes. Effectively this + # means that for the same input, these values will remain consistent every + # time the source is parsed. This means we can reparse the source same with a + # #node_id value and find the exact same node again. + # + # The Relocation module provides an API around this property. It allows you to + # "save" nodes and locations using a minimal amount of memory (just the + # node_id and a field identifier) and then reify them later. + module Relocation + type entry_value = untyped + + type entry_values = Hash[Symbol, entry_value] + + interface _Value + def start_line: () -> Integer + + def end_line: () -> Integer + + def start_offset: () -> Integer + + def end_offset: () -> Integer + + def start_character_offset: () -> Integer + + def end_character_offset: () -> Integer + + def cached_start_code_units_offset: (_CodeUnitsCache cache) -> Integer + + def cached_end_code_units_offset: (_CodeUnitsCache cache) -> Integer + + def start_column: () -> Integer + + def end_column: () -> Integer + + def start_character_column: () -> Integer + + def end_character_column: () -> Integer + + def cached_start_code_units_column: (_CodeUnitsCache cache) -> Integer + + def cached_end_code_units_column: (_CodeUnitsCache cache) -> Integer + + def leading_comments: () -> Array[Comment] + + def trailing_comments: () -> Array[Comment] + end + + interface _Field + def fields: (_Value value) -> entry_values + end + + # An entry in a repository that will lazily reify its values when they are + # first accessed. + class Entry + # Raised if a value that could potentially be on an entry is missing + # because it was either not configured on the repository or it has not yet + # been fetched. + class MissingValueError < StandardError + end + + @values: Hash[Symbol, untyped]? + + @repository: Repository? + + # Initialize a new entry with the given repository. + # -- + # : (Repository repository) -> void + def initialize: (Repository repository) -> void + + # Fetch the filepath of the value. + # -- + # : () -> String + def filepath: () -> String + + # Fetch the start line of the value. + # -- + # : () -> Integer + def start_line: () -> Integer + + # Fetch the end line of the value. + # -- + # : () -> Integer + def end_line: () -> Integer + + # Fetch the start byte offset of the value. + # -- + # : () -> Integer + def start_offset: () -> Integer + + # Fetch the end byte offset of the value. + # -- + # : () -> Integer + def end_offset: () -> Integer + + # Fetch the start character offset of the value. + # -- + # : () -> Integer + def start_character_offset: () -> Integer + + # Fetch the end character offset of the value. + # -- + # : () -> Integer + def end_character_offset: () -> Integer + + # Fetch the start code units offset of the value, for the encoding that + # was configured on the repository. + # -- + # : () -> Integer + def start_code_units_offset: () -> Integer + + # Fetch the end code units offset of the value, for the encoding that was + # configured on the repository. + # -- + # : () -> Integer + def end_code_units_offset: () -> Integer + + # Fetch the start byte column of the value. + # -- + # : () -> Integer + def start_column: () -> Integer + + # Fetch the end byte column of the value. + # -- + # : () -> Integer + def end_column: () -> Integer + + # Fetch the start character column of the value. + # -- + # : () -> Integer + def start_character_column: () -> Integer + + # Fetch the end character column of the value. + # -- + # : () -> Integer + def end_character_column: () -> Integer + + # Fetch the start code units column of the value, for the encoding that + # was configured on the repository. + # -- + # : () -> Integer + def start_code_units_column: () -> Integer + + # Fetch the end code units column of the value, for the encoding that was + # configured on the repository. + # -- + # : () -> Integer + def end_code_units_column: () -> Integer + + # Fetch the leading comments of the value. + # -- + # : () -> Array[CommentsField::Comment] + def leading_comments: () -> Array[CommentsField::Comment] + + # Fetch the trailing comments of the value. + # -- + # : () -> Array[CommentsField::Comment] + def trailing_comments: () -> Array[CommentsField::Comment] + + # Fetch the leading and trailing comments of the value. + # -- + # : () -> Array[CommentsField::Comment] + def comments: () -> Array[CommentsField::Comment] + + # Reify the values on this entry with the given values. This is an + # internal-only API that is called from the repository when it is time to + # reify the values. + # -- + # : (entry_values values) -> void + def reify!: (entry_values values) -> void + + private + + # Fetch a value from the entry, raising an error if it is missing. + # -- + # : (Symbol name) -> entry_value + def fetch_value: (Symbol name) -> entry_value + + # Return the values from the repository, reifying them if necessary. + # -- + # : () -> entry_values + def values: () -> entry_values + end + + # Represents the source of a repository that will be reparsed. + class Source + # The value that will need to be reparsed. + attr_reader value: untyped + + # Initialize the source with the given value. + # -- + # : (untyped value) -> void + def initialize: (untyped value) -> void + + # Reparse the value and return the parse result. + # -- + # : () -> ParseResult + def result: () -> ParseResult + + # Create a code units cache for the given encoding. + # -- + # : (Encoding encoding) -> _CodeUnitsCache + def code_units_cache: (Encoding encoding) -> _CodeUnitsCache + end + + # A source that is represented by a file path. + class SourceFilepath < Source + # Reparse the file and return the parse result. + # -- + # : () -> ParseResult + def result: () -> ParseResult + end + + # A source that is represented by a string. + class SourceString < Source + # Reparse the string and return the parse result. + # -- + # : () -> ParseResult + def result: () -> ParseResult + end + + # A field that represents the file path. + class FilepathField + # The file path that this field represents. + attr_reader value: String + + # Initialize a new field with the given file path. + # -- + # : (String value) -> void + def initialize: (String value) -> void + + # Fetch the file path. + # -- + # : (_Value _value) -> entry_values + def fields: (_Value _value) -> entry_values + end + + # A field representing the start and end lines. + class LinesField + # Fetches the start and end line of a value. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + end + + # A field representing the start and end byte offsets. + class OffsetsField + # Fetches the start and end byte offset of a value. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + end + + # A field representing the start and end character offsets. + class CharacterOffsetsField + # Fetches the start and end character offset of a value. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + end + + # A field representing the start and end code unit offsets. + class CodeUnitOffsetsField + # A pointer to the repository object that is used for lazily creating a + # code units cache. + attr_reader repository: Repository + + # The associated encoding for the code units. + attr_reader encoding: Encoding + + @cache: _CodeUnitsCache? + + # Initialize a new field with the associated repository and encoding. + # -- + # : (Repository repository, Encoding encoding) -> void + def initialize: (Repository repository, Encoding encoding) -> void + + # Fetches the start and end code units offset of a value for a particular + # encoding. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + + private + + # Lazily create a code units cache for the associated encoding. + # -- + # : () -> _CodeUnitsCache + def cache: () -> _CodeUnitsCache + end + + # A field representing the start and end byte columns. + class ColumnsField + # Fetches the start and end byte column of a value. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + end + + # A field representing the start and end character columns. + class CharacterColumnsField + # Fetches the start and end character column of a value. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + end + + # A field representing the start and end code unit columns for a specific + # encoding. + class CodeUnitColumnsField + # The repository object that is used for lazily creating a code units + # cache. + attr_reader repository: Repository + + # The associated encoding for the code units. + attr_reader encoding: Encoding + + @cache: _CodeUnitsCache? + + # Initialize a new field with the associated repository and encoding. + # -- + # : (Repository repository, Encoding encoding) -> void + def initialize: (Repository repository, Encoding encoding) -> void + + # Fetches the start and end code units column of a value for a particular + # encoding. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + + private + + # Lazily create a code units cache for the associated encoding. + # -- + # : () -> _CodeUnitsCache + def cache: () -> _CodeUnitsCache + end + + # An abstract field used as the parent class of the two comments fields. + class CommentsField + # An object that represents a slice of a comment. + class Comment + # The slice of the comment. + attr_reader slice: String + + # Initialize a new comment with the given slice. + # + # : (String slice) -> void + def initialize: (String slice) -> void + end + + private + + # Create comment objects from the given values. + # -- + # : (entry_value values) -> Array[Comment] + def comments: (entry_value values) -> Array[Comment] + end + + # A field representing the leading comments. + class LeadingCommentsField < CommentsField + # Fetches the leading comments of a value. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + end + + # A field representing the trailing comments. + class TrailingCommentsField < CommentsField + # Fetches the trailing comments of a value. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + end + + # A repository is a configured collection of fields and a set of entries + # that knows how to reparse a source and reify the values. + class Repository + # Raised when multiple fields of the same type are configured on the same + # repository. + class ConfigurationError < StandardError + end + + # The source associated with this repository. This will be either a + # SourceFilepath (the most common use case) or a SourceString. + attr_reader source: Source + + # The fields that have been configured on this repository. + attr_reader fields: Hash[Symbol, _Field] + + # The entries that have been saved on this repository. + attr_reader entries: Hash[Integer, Hash[Symbol, Entry]] + + # Initialize a new repository with the given source. + # -- + # : (Source source) -> void + def initialize: (Source source) -> void + + # Create a code units cache for the given encoding from the source. + # -- + # : (Encoding encoding) -> _CodeUnitsCache + def code_units_cache: (Encoding encoding) -> _CodeUnitsCache + + # Configure the filepath field for this repository and return self. + # -- + # : () -> self + def filepath: () -> self + + # Configure the lines field for this repository and return self. + # -- + # : () -> self + def lines: () -> self + + # Configure the offsets field for this repository and return self. + # -- + # : () -> self + def offsets: () -> self + + # Configure the character offsets field for this repository and return + # self. + # -- + # : () -> self + def character_offsets: () -> self + + # Configure the code unit offsets field for this repository for a specific + # encoding and return self. + # -- + # : (Encoding encoding) -> self + def code_unit_offsets: (Encoding encoding) -> self + + # Configure the columns field for this repository and return self. + # -- + # : () -> self + def columns: () -> self + + # Configure the character columns field for this repository and return + # self. + # -- + # : () -> self + def character_columns: () -> self + + # Configure the code unit columns field for this repository for a specific + # encoding and return self. + # -- + # : (Encoding encoding) -> self + def code_unit_columns: (Encoding encoding) -> self + + # Configure the leading comments field for this repository and return + # self. + # -- + # : () -> self + def leading_comments: () -> self + + # Configure the trailing comments field for this repository and return + # self. + # -- + # : () -> self + def trailing_comments: () -> self + + # Configure both the leading and trailing comment fields for this + # repository and return self. + # -- + # : () -> self + def comments: () -> self + + # This method is called from nodes and locations when they want to enter + # themselves into the repository. It it internal-only and meant to be + # called from the #save* APIs. + # -- + # : (Integer node_id, Symbol field_name) -> Entry + def enter: (Integer node_id, Symbol field_name) -> Entry + + # This method is called from the entries in the repository when they need + # to reify their values. It is internal-only and meant to be called from + # the various value APIs. + # -- + # : () -> void + def reify!: () -> void + + private + + # Append the given field to the repository and return the repository so + # that these calls can be chained. + # -- + # : (Symbol name, _Field) -> self + def field: (Symbol name, _Field) -> self + end + + # Create a new repository for the given filepath. + # -- + # : (String value) -> Repository + def self.filepath: (String value) -> Repository + + # Create a new repository for the given string. + # -- + # : (String value) -> Repository + def self.string: (String value) -> Repository + end +end diff --git a/sig/generated/prism/serialize.rbs b/sig/generated/prism/serialize.rbs new file mode 100644 index 0000000000..a83dae70d8 --- /dev/null +++ b/sig/generated/prism/serialize.rbs @@ -0,0 +1,184 @@ +# Generated from lib/prism/serialize.rb with RBS::Inline + +module Prism + # A module responsible for deserializing parse results. + module Serialize + # The major version of prism that we are expecting to find in the serialized + # strings. + MAJOR_VERSION: ::Integer + + # The minor version of prism that we are expecting to find in the serialized + # strings. + MINOR_VERSION: ::Integer + + # The patch version of prism that we are expecting to find in the serialized + # strings. + PATCH_VERSION: ::Integer + + # Deserialize the dumped output from a request to parse or parse_file. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + # -- + # : (String input, String serialized, bool freeze) -> ParseResult + def self.load_parse: (String input, String serialized, bool freeze) -> ParseResult + + # Deserialize the dumped output from a request to lex or lex_file. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + # -- + # : (String input, String serialized, bool freeze) -> LexResult + def self.load_lex: (String input, String serialized, bool freeze) -> LexResult + + # Deserialize the dumped output from a request to parse_comments or + # parse_file_comments. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + # -- + # : (String input, String serialized, bool freeze) -> Array[Comment] + def self.load_parse_comments: (String input, String serialized, bool freeze) -> Array[Comment] + + # Deserialize the dumped output from a request to parse_lex or + # parse_lex_file. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + # -- + # : (String input, String serialized, bool freeze) -> ParseLexResult + def self.load_parse_lex: (String input, String serialized, bool freeze) -> ParseLexResult + + class ConstantPool + # :nodoc: + attr_reader size: Integer + + @serialized: String + + @base: Integer + + @pool: Array[Symbol?] + + # : (String serialized, Integer base, Integer size) -> void + def initialize: (String serialized, Integer base, Integer size) -> void + + # : (Integer index, Encoding encoding) -> Symbol + def get: (Integer index, Encoding encoding) -> Symbol + end + + FastStringIO: untyped + + class Loader + # :nodoc: + attr_reader input: String + + attr_reader io: StringIO + + attr_reader source: Source + + # : (Source source, String serialized) -> void + def initialize: (Source source, String serialized) -> void + + # : () -> bool + def eof?: () -> bool + + # : (ConstantPool constant_pool) -> void + def load_constant_pool: (ConstantPool constant_pool) -> void + + # : () -> void + def load_header: () -> void + + # : () -> Encoding + def load_encoding: () -> Encoding + + # : (bool freeze) -> Array[Integer] + def load_line_offsets: (bool freeze) -> Array[Integer] + + # : (bool freeze) -> Array[Comment] + def load_comments: (bool freeze) -> Array[Comment] + + # : (bool freeze) -> Array[MagicComment] + def load_magic_comments: (bool freeze) -> Array[MagicComment] + + DIAGNOSTIC_TYPES: Array[Symbol] + + # : () -> Symbol + def load_error_level: () -> Symbol + + # : (Encoding encoding, bool freeze) -> Array[ParseError] + def load_errors: (Encoding encoding, bool freeze) -> Array[ParseError] + + # : () -> Symbol + def load_warning_level: () -> Symbol + + # : (Encoding encoding, bool freeze) -> Array[ParseWarning] + def load_warnings: (Encoding encoding, bool freeze) -> Array[ParseWarning] + + # : () -> Array[[Token, Integer]] + def load_tokens: () -> Array[[ Token, Integer ]] + + # variable-length integer using https://en.wikipedia.org/wiki/LEB128 + # This is also what protobuf uses: https://protobuf.dev/programming-guides/encoding/#varints + # -- + # : () -> Integer + def load_varuint: () -> Integer + + # : () -> Integer + def load_varsint: () -> Integer + + # : () -> Integer + def load_integer: () -> Integer + + # : () -> Float + def load_double: () -> Float + + # : () -> bool + def load_bool: () -> bool + + # : () -> Integer + def load_uint32: () -> Integer + + # : (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node? + def load_optional_node: (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node? + + # : (Encoding encoding) -> String + def load_string: (Encoding encoding) -> String + + # : (bool freeze) -> Location + def load_location_object: (bool freeze) -> Location + + # Load a location object from the serialized data. Note that we are lying + # about the signature a bit here, because we sometimes load it as a packed + # integer instead of an object. + # -- + # : (bool freeze) -> Location + def load_location: (bool freeze) -> Location + + # Load an optional location object from the serialized data if it is + # present. Note that we are lying about the signature a bit here, because + # we sometimes load it as a packed integer instead of an object. + # -- + # : (bool freeze) -> Location? + def load_optional_location: (bool freeze) -> Location? + + # : (bool freeze) -> Location? + def load_optional_location_object: (bool freeze) -> Location? + + # : (ConstantPool constant_pool, Encoding encoding) -> Symbol + def load_constant: (ConstantPool constant_pool, Encoding encoding) -> Symbol + + # : (ConstantPool constant_pool, Encoding encoding) -> Symbol? + def load_optional_constant: (ConstantPool constant_pool, Encoding encoding) -> Symbol? + + # : (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node + def load_node: (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node + + @load_node_lambdas: Array[Proc] + + def define_load_node_lambdas: () -> void + end + + # The token types that can be indexed by their enum values. + TOKEN_TYPES: Array[Symbol?] + end +end diff --git a/sig/generated/prism/string_query.rbs b/sig/generated/prism/string_query.rbs new file mode 100644 index 0000000000..de2183a731 --- /dev/null +++ b/sig/generated/prism/string_query.rbs @@ -0,0 +1,36 @@ +# Generated from lib/prism/string_query.rb with RBS::Inline + +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 + def self.local?: (String string) -> bool + + def self.constant?: (String string) -> bool + + def self.method_name?: (String string) -> bool + + # The string that this query is wrapping. + attr_reader string: String + + # Initialize a new query with the given string. + # -- + # : (String string) -> void + def initialize: (String string) -> void + + # Whether or not this string is a valid local variable name. + # -- + # : () -> bool + def local?: () -> bool + + # Whether or not this string is a valid constant name. + # -- + # : () -> bool + def constant?: () -> bool + + # Whether or not this string is a valid method name. + # -- + # : () -> bool + def method_name?: () -> bool + end +end diff --git a/sig/generated/prism/translation.rbs b/sig/generated/prism/translation.rbs new file mode 100644 index 0000000000..09971a2971 --- /dev/null +++ b/sig/generated/prism/translation.rbs @@ -0,0 +1,8 @@ +# Generated from lib/prism/translation.rb with RBS::Inline + +module Prism + # This module is responsible for converting the prism syntax tree into other + # syntax trees. + module Translation + end +end diff --git a/sig/generated/prism/visitor.rbs b/sig/generated/prism/visitor.rbs new file mode 100644 index 0000000000..ec65adbb29 --- /dev/null +++ b/sig/generated/prism/visitor.rbs @@ -0,0 +1,1111 @@ +# Generated from lib/prism/visitor.rb with RBS::Inline + +module Prism + interface _Visitor + def visit_alias_global_variable_node: (AliasGlobalVariableNode) -> void + + def visit_alias_method_node: (AliasMethodNode) -> void + + def visit_alternation_pattern_node: (AlternationPatternNode) -> void + + def visit_and_node: (AndNode) -> void + + def visit_arguments_node: (ArgumentsNode) -> void + + def visit_array_node: (ArrayNode) -> void + + def visit_array_pattern_node: (ArrayPatternNode) -> void + + def visit_assoc_node: (AssocNode) -> void + + def visit_assoc_splat_node: (AssocSplatNode) -> void + + def visit_back_reference_read_node: (BackReferenceReadNode) -> void + + def visit_begin_node: (BeginNode) -> void + + def visit_block_argument_node: (BlockArgumentNode) -> void + + def visit_block_local_variable_node: (BlockLocalVariableNode) -> void + + def visit_block_node: (BlockNode) -> void + + def visit_block_parameter_node: (BlockParameterNode) -> void + + def visit_block_parameters_node: (BlockParametersNode) -> void + + def visit_break_node: (BreakNode) -> void + + def visit_call_and_write_node: (CallAndWriteNode) -> void + + def visit_call_node: (CallNode) -> void + + def visit_call_operator_write_node: (CallOperatorWriteNode) -> void + + def visit_call_or_write_node: (CallOrWriteNode) -> void + + def visit_call_target_node: (CallTargetNode) -> void + + def visit_capture_pattern_node: (CapturePatternNode) -> void + + def visit_case_match_node: (CaseMatchNode) -> void + + def visit_case_node: (CaseNode) -> void + + def visit_class_node: (ClassNode) -> void + + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode) -> void + + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode) -> void + + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode) -> void + + def visit_class_variable_read_node: (ClassVariableReadNode) -> void + + def visit_class_variable_target_node: (ClassVariableTargetNode) -> void + + def visit_class_variable_write_node: (ClassVariableWriteNode) -> void + + def visit_constant_and_write_node: (ConstantAndWriteNode) -> void + + def visit_constant_operator_write_node: (ConstantOperatorWriteNode) -> void + + def visit_constant_or_write_node: (ConstantOrWriteNode) -> void + + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode) -> void + + def visit_constant_path_node: (ConstantPathNode) -> void + + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode) -> void + + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode) -> void + + def visit_constant_path_target_node: (ConstantPathTargetNode) -> void + + def visit_constant_path_write_node: (ConstantPathWriteNode) -> void + + def visit_constant_read_node: (ConstantReadNode) -> void + + def visit_constant_target_node: (ConstantTargetNode) -> void + + def visit_constant_write_node: (ConstantWriteNode) -> void + + def visit_def_node: (DefNode) -> void + + def visit_defined_node: (DefinedNode) -> void + + def visit_else_node: (ElseNode) -> void + + def visit_embedded_statements_node: (EmbeddedStatementsNode) -> void + + def visit_embedded_variable_node: (EmbeddedVariableNode) -> void + + def visit_ensure_node: (EnsureNode) -> void + + def visit_false_node: (FalseNode) -> void + + def visit_find_pattern_node: (FindPatternNode) -> void + + def visit_flip_flop_node: (FlipFlopNode) -> void + + def visit_float_node: (FloatNode) -> void + + def visit_for_node: (ForNode) -> void + + def visit_forwarding_arguments_node: (ForwardingArgumentsNode) -> void + + def visit_forwarding_parameter_node: (ForwardingParameterNode) -> void + + def visit_forwarding_super_node: (ForwardingSuperNode) -> void + + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode) -> void + + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode) -> void + + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode) -> void + + def visit_global_variable_read_node: (GlobalVariableReadNode) -> void + + def visit_global_variable_target_node: (GlobalVariableTargetNode) -> void + + def visit_global_variable_write_node: (GlobalVariableWriteNode) -> void + + def visit_hash_node: (HashNode) -> void + + def visit_hash_pattern_node: (HashPatternNode) -> void + + def visit_if_node: (IfNode) -> void + + def visit_imaginary_node: (ImaginaryNode) -> void + + def visit_implicit_node: (ImplicitNode) -> void + + def visit_implicit_rest_node: (ImplicitRestNode) -> void + + def visit_in_node: (InNode) -> void + + def visit_index_and_write_node: (IndexAndWriteNode) -> void + + def visit_index_operator_write_node: (IndexOperatorWriteNode) -> void + + def visit_index_or_write_node: (IndexOrWriteNode) -> void + + def visit_index_target_node: (IndexTargetNode) -> void + + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode) -> void + + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode) -> void + + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode) -> void + + def visit_instance_variable_read_node: (InstanceVariableReadNode) -> void + + def visit_instance_variable_target_node: (InstanceVariableTargetNode) -> void + + def visit_instance_variable_write_node: (InstanceVariableWriteNode) -> void + + def visit_integer_node: (IntegerNode) -> void + + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode) -> void + + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode) -> void + + def visit_interpolated_string_node: (InterpolatedStringNode) -> void + + def visit_interpolated_symbol_node: (InterpolatedSymbolNode) -> void + + def visit_interpolated_x_string_node: (InterpolatedXStringNode) -> void + + def visit_it_local_variable_read_node: (ItLocalVariableReadNode) -> void + + def visit_it_parameters_node: (ItParametersNode) -> void + + def visit_keyword_hash_node: (KeywordHashNode) -> void + + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode) -> void + + def visit_lambda_node: (LambdaNode) -> void + + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode) -> void + + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode) -> void + + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode) -> void + + def visit_local_variable_read_node: (LocalVariableReadNode) -> void + + def visit_local_variable_target_node: (LocalVariableTargetNode) -> void + + def visit_local_variable_write_node: (LocalVariableWriteNode) -> void + + def visit_match_last_line_node: (MatchLastLineNode) -> void + + def visit_match_predicate_node: (MatchPredicateNode) -> void + + def visit_match_required_node: (MatchRequiredNode) -> void + + def visit_match_write_node: (MatchWriteNode) -> void + + def visit_missing_node: (MissingNode) -> void + + def visit_module_node: (ModuleNode) -> void + + def visit_multi_target_node: (MultiTargetNode) -> void + + def visit_multi_write_node: (MultiWriteNode) -> void + + def visit_next_node: (NextNode) -> void + + def visit_nil_node: (NilNode) -> void + + def visit_no_block_parameter_node: (NoBlockParameterNode) -> void + + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode) -> void + + def visit_numbered_parameters_node: (NumberedParametersNode) -> void + + def visit_numbered_reference_read_node: (NumberedReferenceReadNode) -> void + + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode) -> void + + def visit_optional_parameter_node: (OptionalParameterNode) -> void + + def visit_or_node: (OrNode) -> void + + def visit_parameters_node: (ParametersNode) -> void + + def visit_parentheses_node: (ParenthesesNode) -> void + + def visit_pinned_expression_node: (PinnedExpressionNode) -> void + + def visit_pinned_variable_node: (PinnedVariableNode) -> void + + def visit_post_execution_node: (PostExecutionNode) -> void + + def visit_pre_execution_node: (PreExecutionNode) -> void + + def visit_program_node: (ProgramNode) -> void + + def visit_range_node: (RangeNode) -> void + + def visit_rational_node: (RationalNode) -> void + + def visit_redo_node: (RedoNode) -> void + + def visit_regular_expression_node: (RegularExpressionNode) -> void + + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode) -> void + + def visit_required_parameter_node: (RequiredParameterNode) -> void + + def visit_rescue_modifier_node: (RescueModifierNode) -> void + + def visit_rescue_node: (RescueNode) -> void + + def visit_rest_parameter_node: (RestParameterNode) -> void + + def visit_retry_node: (RetryNode) -> void + + def visit_return_node: (ReturnNode) -> void + + def visit_self_node: (SelfNode) -> void + + def visit_shareable_constant_node: (ShareableConstantNode) -> void + + def visit_singleton_class_node: (SingletonClassNode) -> void + + def visit_source_encoding_node: (SourceEncodingNode) -> void + + def visit_source_file_node: (SourceFileNode) -> void + + def visit_source_line_node: (SourceLineNode) -> void + + def visit_splat_node: (SplatNode) -> void + + def visit_statements_node: (StatementsNode) -> void + + def visit_string_node: (StringNode) -> void + + def visit_super_node: (SuperNode) -> void + + def visit_symbol_node: (SymbolNode) -> void + + def visit_true_node: (TrueNode) -> void + + def visit_undef_node: (UndefNode) -> void + + def visit_unless_node: (UnlessNode) -> void + + def visit_until_node: (UntilNode) -> void + + def visit_when_node: (WhenNode) -> void + + def visit_while_node: (WhileNode) -> void + + def visit_x_string_node: (XStringNode) -> void + + def visit_yield_node: (YieldNode) -> void + end + + # A class that knows how to walk down the tree. None of the individual visit + # methods are implemented on this visitor, so it forces the consumer to + # implement each one that they need. For a default implementation that + # continues walking the tree, see the Visitor class. + class BasicVisitor + # Calls `accept` on the given node if it is not `nil`, which in turn should + # call back into this visitor by calling the appropriate `visit_*` method. + # -- + # : (node? node) -> void + def visit: (node? node) -> void + + # Visits each node in `nodes` by calling `accept` on each one. + # -- + # : (Array[node?] nodes) -> void + def visit_all: (Array[node?] nodes) -> void + + # Visits the child nodes of `node` by calling `accept` on each one. + # -- + # : (node node) -> void + def visit_child_nodes: (node node) -> void + end + + # A visitor is a class that provides a default implementation for every accept + # method defined on the nodes. This means it can walk a tree without the + # caller needing to define any special handling. This allows you to handle a + # subset of the tree, while still walking the whole tree. + # + # For example, to find all of the method calls that call the `foo` method, you + # could write: + # + # class FooCalls < Prism::Visitor + # def visit_call_node(node) + # if node.name == :foo + # # Do something with the node + # end + # + # # Call super so that the visitor continues walking the tree + # super + # end + # end + class Visitor < BasicVisitor + # Visit a AliasGlobalVariableNode node + # -- + # : (AliasGlobalVariableNode node) -> void + def visit_alias_global_variable_node: (AliasGlobalVariableNode node) -> void + + # Visit a AliasMethodNode node + # -- + # : (AliasMethodNode node) -> void + def visit_alias_method_node: (AliasMethodNode node) -> void + + # Visit a AlternationPatternNode node + # -- + # : (AlternationPatternNode node) -> void + def visit_alternation_pattern_node: (AlternationPatternNode node) -> void + + # Visit a AndNode node + # -- + # : (AndNode node) -> void + def visit_and_node: (AndNode node) -> void + + # Visit a ArgumentsNode node + # -- + # : (ArgumentsNode node) -> void + def visit_arguments_node: (ArgumentsNode node) -> void + + # Visit a ArrayNode node + # -- + # : (ArrayNode node) -> void + def visit_array_node: (ArrayNode node) -> void + + # Visit a ArrayPatternNode node + # -- + # : (ArrayPatternNode node) -> void + def visit_array_pattern_node: (ArrayPatternNode node) -> void + + # Visit a AssocNode node + # -- + # : (AssocNode node) -> void + def visit_assoc_node: (AssocNode node) -> void + + # Visit a AssocSplatNode node + # -- + # : (AssocSplatNode node) -> void + def visit_assoc_splat_node: (AssocSplatNode node) -> void + + # Visit a BackReferenceReadNode node + # -- + # : (BackReferenceReadNode node) -> void + def visit_back_reference_read_node: (BackReferenceReadNode node) -> void + + # Visit a BeginNode node + # -- + # : (BeginNode node) -> void + def visit_begin_node: (BeginNode node) -> void + + # Visit a BlockArgumentNode node + # -- + # : (BlockArgumentNode node) -> void + def visit_block_argument_node: (BlockArgumentNode node) -> void + + # Visit a BlockLocalVariableNode node + # -- + # : (BlockLocalVariableNode node) -> void + def visit_block_local_variable_node: (BlockLocalVariableNode node) -> void + + # Visit a BlockNode node + # -- + # : (BlockNode node) -> void + def visit_block_node: (BlockNode node) -> void + + # Visit a BlockParameterNode node + # -- + # : (BlockParameterNode node) -> void + def visit_block_parameter_node: (BlockParameterNode node) -> void + + # Visit a BlockParametersNode node + # -- + # : (BlockParametersNode node) -> void + def visit_block_parameters_node: (BlockParametersNode node) -> void + + # Visit a BreakNode node + # -- + # : (BreakNode node) -> void + def visit_break_node: (BreakNode node) -> void + + # Visit a CallAndWriteNode node + # -- + # : (CallAndWriteNode node) -> void + def visit_call_and_write_node: (CallAndWriteNode node) -> void + + # Visit a CallNode node + # -- + # : (CallNode node) -> void + def visit_call_node: (CallNode node) -> void + + # Visit a CallOperatorWriteNode node + # -- + # : (CallOperatorWriteNode node) -> void + def visit_call_operator_write_node: (CallOperatorWriteNode node) -> void + + # Visit a CallOrWriteNode node + # -- + # : (CallOrWriteNode node) -> void + def visit_call_or_write_node: (CallOrWriteNode node) -> void + + # Visit a CallTargetNode node + # -- + # : (CallTargetNode node) -> void + def visit_call_target_node: (CallTargetNode node) -> void + + # Visit a CapturePatternNode node + # -- + # : (CapturePatternNode node) -> void + def visit_capture_pattern_node: (CapturePatternNode node) -> void + + # Visit a CaseMatchNode node + # -- + # : (CaseMatchNode node) -> void + def visit_case_match_node: (CaseMatchNode node) -> void + + # Visit a CaseNode node + # -- + # : (CaseNode node) -> void + def visit_case_node: (CaseNode node) -> void + + # Visit a ClassNode node + # -- + # : (ClassNode node) -> void + def visit_class_node: (ClassNode node) -> void + + # Visit a ClassVariableAndWriteNode node + # -- + # : (ClassVariableAndWriteNode node) -> void + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode node) -> void + + # Visit a ClassVariableOperatorWriteNode node + # -- + # : (ClassVariableOperatorWriteNode node) -> void + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode node) -> void + + # Visit a ClassVariableOrWriteNode node + # -- + # : (ClassVariableOrWriteNode node) -> void + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode node) -> void + + # Visit a ClassVariableReadNode node + # -- + # : (ClassVariableReadNode node) -> void + def visit_class_variable_read_node: (ClassVariableReadNode node) -> void + + # Visit a ClassVariableTargetNode node + # -- + # : (ClassVariableTargetNode node) -> void + def visit_class_variable_target_node: (ClassVariableTargetNode node) -> void + + # Visit a ClassVariableWriteNode node + # -- + # : (ClassVariableWriteNode node) -> void + def visit_class_variable_write_node: (ClassVariableWriteNode node) -> void + + # Visit a ConstantAndWriteNode node + # -- + # : (ConstantAndWriteNode node) -> void + def visit_constant_and_write_node: (ConstantAndWriteNode node) -> void + + # Visit a ConstantOperatorWriteNode node + # -- + # : (ConstantOperatorWriteNode node) -> void + def visit_constant_operator_write_node: (ConstantOperatorWriteNode node) -> void + + # Visit a ConstantOrWriteNode node + # -- + # : (ConstantOrWriteNode node) -> void + def visit_constant_or_write_node: (ConstantOrWriteNode node) -> void + + # Visit a ConstantPathAndWriteNode node + # -- + # : (ConstantPathAndWriteNode node) -> void + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode node) -> void + + # Visit a ConstantPathNode node + # -- + # : (ConstantPathNode node) -> void + def visit_constant_path_node: (ConstantPathNode node) -> void + + # Visit a ConstantPathOperatorWriteNode node + # -- + # : (ConstantPathOperatorWriteNode node) -> void + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode node) -> void + + # Visit a ConstantPathOrWriteNode node + # -- + # : (ConstantPathOrWriteNode node) -> void + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode node) -> void + + # Visit a ConstantPathTargetNode node + # -- + # : (ConstantPathTargetNode node) -> void + def visit_constant_path_target_node: (ConstantPathTargetNode node) -> void + + # Visit a ConstantPathWriteNode node + # -- + # : (ConstantPathWriteNode node) -> void + def visit_constant_path_write_node: (ConstantPathWriteNode node) -> void + + # Visit a ConstantReadNode node + # -- + # : (ConstantReadNode node) -> void + def visit_constant_read_node: (ConstantReadNode node) -> void + + # Visit a ConstantTargetNode node + # -- + # : (ConstantTargetNode node) -> void + def visit_constant_target_node: (ConstantTargetNode node) -> void + + # Visit a ConstantWriteNode node + # -- + # : (ConstantWriteNode node) -> void + def visit_constant_write_node: (ConstantWriteNode node) -> void + + # Visit a DefNode node + # -- + # : (DefNode node) -> void + def visit_def_node: (DefNode node) -> void + + # Visit a DefinedNode node + # -- + # : (DefinedNode node) -> void + def visit_defined_node: (DefinedNode node) -> void + + # Visit a ElseNode node + # -- + # : (ElseNode node) -> void + def visit_else_node: (ElseNode node) -> void + + # Visit a EmbeddedStatementsNode node + # -- + # : (EmbeddedStatementsNode node) -> void + def visit_embedded_statements_node: (EmbeddedStatementsNode node) -> void + + # Visit a EmbeddedVariableNode node + # -- + # : (EmbeddedVariableNode node) -> void + def visit_embedded_variable_node: (EmbeddedVariableNode node) -> void + + # Visit a EnsureNode node + # -- + # : (EnsureNode node) -> void + def visit_ensure_node: (EnsureNode node) -> void + + # Visit a FalseNode node + # -- + # : (FalseNode node) -> void + def visit_false_node: (FalseNode node) -> void + + # Visit a FindPatternNode node + # -- + # : (FindPatternNode node) -> void + def visit_find_pattern_node: (FindPatternNode node) -> void + + # Visit a FlipFlopNode node + # -- + # : (FlipFlopNode node) -> void + def visit_flip_flop_node: (FlipFlopNode node) -> void + + # Visit a FloatNode node + # -- + # : (FloatNode node) -> void + def visit_float_node: (FloatNode node) -> void + + # Visit a ForNode node + # -- + # : (ForNode node) -> void + def visit_for_node: (ForNode node) -> void + + # Visit a ForwardingArgumentsNode node + # -- + # : (ForwardingArgumentsNode node) -> void + def visit_forwarding_arguments_node: (ForwardingArgumentsNode node) -> void + + # Visit a ForwardingParameterNode node + # -- + # : (ForwardingParameterNode node) -> void + def visit_forwarding_parameter_node: (ForwardingParameterNode node) -> void + + # Visit a ForwardingSuperNode node + # -- + # : (ForwardingSuperNode node) -> void + def visit_forwarding_super_node: (ForwardingSuperNode node) -> void + + # Visit a GlobalVariableAndWriteNode node + # -- + # : (GlobalVariableAndWriteNode node) -> void + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode node) -> void + + # Visit a GlobalVariableOperatorWriteNode node + # -- + # : (GlobalVariableOperatorWriteNode node) -> void + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode node) -> void + + # Visit a GlobalVariableOrWriteNode node + # -- + # : (GlobalVariableOrWriteNode node) -> void + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode node) -> void + + # Visit a GlobalVariableReadNode node + # -- + # : (GlobalVariableReadNode node) -> void + def visit_global_variable_read_node: (GlobalVariableReadNode node) -> void + + # Visit a GlobalVariableTargetNode node + # -- + # : (GlobalVariableTargetNode node) -> void + def visit_global_variable_target_node: (GlobalVariableTargetNode node) -> void + + # Visit a GlobalVariableWriteNode node + # -- + # : (GlobalVariableWriteNode node) -> void + def visit_global_variable_write_node: (GlobalVariableWriteNode node) -> void + + # Visit a HashNode node + # -- + # : (HashNode node) -> void + def visit_hash_node: (HashNode node) -> void + + # Visit a HashPatternNode node + # -- + # : (HashPatternNode node) -> void + def visit_hash_pattern_node: (HashPatternNode node) -> void + + # Visit a IfNode node + # -- + # : (IfNode node) -> void + def visit_if_node: (IfNode node) -> void + + # Visit a ImaginaryNode node + # -- + # : (ImaginaryNode node) -> void + def visit_imaginary_node: (ImaginaryNode node) -> void + + # Visit a ImplicitNode node + # -- + # : (ImplicitNode node) -> void + def visit_implicit_node: (ImplicitNode node) -> void + + # Visit a ImplicitRestNode node + # -- + # : (ImplicitRestNode node) -> void + def visit_implicit_rest_node: (ImplicitRestNode node) -> void + + # Visit a InNode node + # -- + # : (InNode node) -> void + def visit_in_node: (InNode node) -> void + + # Visit a IndexAndWriteNode node + # -- + # : (IndexAndWriteNode node) -> void + def visit_index_and_write_node: (IndexAndWriteNode node) -> void + + # Visit a IndexOperatorWriteNode node + # -- + # : (IndexOperatorWriteNode node) -> void + def visit_index_operator_write_node: (IndexOperatorWriteNode node) -> void + + # Visit a IndexOrWriteNode node + # -- + # : (IndexOrWriteNode node) -> void + def visit_index_or_write_node: (IndexOrWriteNode node) -> void + + # Visit a IndexTargetNode node + # -- + # : (IndexTargetNode node) -> void + def visit_index_target_node: (IndexTargetNode node) -> void + + # Visit a InstanceVariableAndWriteNode node + # -- + # : (InstanceVariableAndWriteNode node) -> void + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode node) -> void + + # Visit a InstanceVariableOperatorWriteNode node + # -- + # : (InstanceVariableOperatorWriteNode node) -> void + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode node) -> void + + # Visit a InstanceVariableOrWriteNode node + # -- + # : (InstanceVariableOrWriteNode node) -> void + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode node) -> void + + # Visit a InstanceVariableReadNode node + # -- + # : (InstanceVariableReadNode node) -> void + def visit_instance_variable_read_node: (InstanceVariableReadNode node) -> void + + # Visit a InstanceVariableTargetNode node + # -- + # : (InstanceVariableTargetNode node) -> void + def visit_instance_variable_target_node: (InstanceVariableTargetNode node) -> void + + # Visit a InstanceVariableWriteNode node + # -- + # : (InstanceVariableWriteNode node) -> void + def visit_instance_variable_write_node: (InstanceVariableWriteNode node) -> void + + # Visit a IntegerNode node + # -- + # : (IntegerNode node) -> void + def visit_integer_node: (IntegerNode node) -> void + + # Visit a InterpolatedMatchLastLineNode node + # -- + # : (InterpolatedMatchLastLineNode node) -> void + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode node) -> void + + # Visit a InterpolatedRegularExpressionNode node + # -- + # : (InterpolatedRegularExpressionNode node) -> void + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode node) -> void + + # Visit a InterpolatedStringNode node + # -- + # : (InterpolatedStringNode node) -> void + def visit_interpolated_string_node: (InterpolatedStringNode node) -> void + + # Visit a InterpolatedSymbolNode node + # -- + # : (InterpolatedSymbolNode node) -> void + def visit_interpolated_symbol_node: (InterpolatedSymbolNode node) -> void + + # Visit a InterpolatedXStringNode node + # -- + # : (InterpolatedXStringNode node) -> void + def visit_interpolated_x_string_node: (InterpolatedXStringNode node) -> void + + # Visit a ItLocalVariableReadNode node + # -- + # : (ItLocalVariableReadNode node) -> void + def visit_it_local_variable_read_node: (ItLocalVariableReadNode node) -> void + + # Visit a ItParametersNode node + # -- + # : (ItParametersNode node) -> void + def visit_it_parameters_node: (ItParametersNode node) -> void + + # Visit a KeywordHashNode node + # -- + # : (KeywordHashNode node) -> void + def visit_keyword_hash_node: (KeywordHashNode node) -> void + + # Visit a KeywordRestParameterNode node + # -- + # : (KeywordRestParameterNode node) -> void + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode node) -> void + + # Visit a LambdaNode node + # -- + # : (LambdaNode node) -> void + def visit_lambda_node: (LambdaNode node) -> void + + # Visit a LocalVariableAndWriteNode node + # -- + # : (LocalVariableAndWriteNode node) -> void + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode node) -> void + + # Visit a LocalVariableOperatorWriteNode node + # -- + # : (LocalVariableOperatorWriteNode node) -> void + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode node) -> void + + # Visit a LocalVariableOrWriteNode node + # -- + # : (LocalVariableOrWriteNode node) -> void + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode node) -> void + + # Visit a LocalVariableReadNode node + # -- + # : (LocalVariableReadNode node) -> void + def visit_local_variable_read_node: (LocalVariableReadNode node) -> void + + # Visit a LocalVariableTargetNode node + # -- + # : (LocalVariableTargetNode node) -> void + def visit_local_variable_target_node: (LocalVariableTargetNode node) -> void + + # Visit a LocalVariableWriteNode node + # -- + # : (LocalVariableWriteNode node) -> void + def visit_local_variable_write_node: (LocalVariableWriteNode node) -> void + + # Visit a MatchLastLineNode node + # -- + # : (MatchLastLineNode node) -> void + def visit_match_last_line_node: (MatchLastLineNode node) -> void + + # Visit a MatchPredicateNode node + # -- + # : (MatchPredicateNode node) -> void + def visit_match_predicate_node: (MatchPredicateNode node) -> void + + # Visit a MatchRequiredNode node + # -- + # : (MatchRequiredNode node) -> void + def visit_match_required_node: (MatchRequiredNode node) -> void + + # Visit a MatchWriteNode node + # -- + # : (MatchWriteNode node) -> void + def visit_match_write_node: (MatchWriteNode node) -> void + + # Visit a MissingNode node + # -- + # : (MissingNode node) -> void + def visit_missing_node: (MissingNode node) -> void + + # Visit a ModuleNode node + # -- + # : (ModuleNode node) -> void + def visit_module_node: (ModuleNode node) -> void + + # Visit a MultiTargetNode node + # -- + # : (MultiTargetNode node) -> void + def visit_multi_target_node: (MultiTargetNode node) -> void + + # Visit a MultiWriteNode node + # -- + # : (MultiWriteNode node) -> void + def visit_multi_write_node: (MultiWriteNode node) -> void + + # Visit a NextNode node + # -- + # : (NextNode node) -> void + def visit_next_node: (NextNode node) -> void + + # Visit a NilNode node + # -- + # : (NilNode node) -> void + def visit_nil_node: (NilNode node) -> void + + # Visit a NoBlockParameterNode node + # -- + # : (NoBlockParameterNode node) -> void + def visit_no_block_parameter_node: (NoBlockParameterNode node) -> void + + # Visit a NoKeywordsParameterNode node + # -- + # : (NoKeywordsParameterNode node) -> void + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode node) -> void + + # Visit a NumberedParametersNode node + # -- + # : (NumberedParametersNode node) -> void + def visit_numbered_parameters_node: (NumberedParametersNode node) -> void + + # Visit a NumberedReferenceReadNode node + # -- + # : (NumberedReferenceReadNode node) -> void + def visit_numbered_reference_read_node: (NumberedReferenceReadNode node) -> void + + # Visit a OptionalKeywordParameterNode node + # -- + # : (OptionalKeywordParameterNode node) -> void + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode node) -> void + + # Visit a OptionalParameterNode node + # -- + # : (OptionalParameterNode node) -> void + def visit_optional_parameter_node: (OptionalParameterNode node) -> void + + # Visit a OrNode node + # -- + # : (OrNode node) -> void + def visit_or_node: (OrNode node) -> void + + # Visit a ParametersNode node + # -- + # : (ParametersNode node) -> void + def visit_parameters_node: (ParametersNode node) -> void + + # Visit a ParenthesesNode node + # -- + # : (ParenthesesNode node) -> void + def visit_parentheses_node: (ParenthesesNode node) -> void + + # Visit a PinnedExpressionNode node + # -- + # : (PinnedExpressionNode node) -> void + def visit_pinned_expression_node: (PinnedExpressionNode node) -> void + + # Visit a PinnedVariableNode node + # -- + # : (PinnedVariableNode node) -> void + def visit_pinned_variable_node: (PinnedVariableNode node) -> void + + # Visit a PostExecutionNode node + # -- + # : (PostExecutionNode node) -> void + def visit_post_execution_node: (PostExecutionNode node) -> void + + # Visit a PreExecutionNode node + # -- + # : (PreExecutionNode node) -> void + def visit_pre_execution_node: (PreExecutionNode node) -> void + + # Visit a ProgramNode node + # -- + # : (ProgramNode node) -> void + def visit_program_node: (ProgramNode node) -> void + + # Visit a RangeNode node + # -- + # : (RangeNode node) -> void + def visit_range_node: (RangeNode node) -> void + + # Visit a RationalNode node + # -- + # : (RationalNode node) -> void + def visit_rational_node: (RationalNode node) -> void + + # Visit a RedoNode node + # -- + # : (RedoNode node) -> void + def visit_redo_node: (RedoNode node) -> void + + # Visit a RegularExpressionNode node + # -- + # : (RegularExpressionNode node) -> void + def visit_regular_expression_node: (RegularExpressionNode node) -> void + + # Visit a RequiredKeywordParameterNode node + # -- + # : (RequiredKeywordParameterNode node) -> void + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode node) -> void + + # Visit a RequiredParameterNode node + # -- + # : (RequiredParameterNode node) -> void + def visit_required_parameter_node: (RequiredParameterNode node) -> void + + # Visit a RescueModifierNode node + # -- + # : (RescueModifierNode node) -> void + def visit_rescue_modifier_node: (RescueModifierNode node) -> void + + # Visit a RescueNode node + # -- + # : (RescueNode node) -> void + def visit_rescue_node: (RescueNode node) -> void + + # Visit a RestParameterNode node + # -- + # : (RestParameterNode node) -> void + def visit_rest_parameter_node: (RestParameterNode node) -> void + + # Visit a RetryNode node + # -- + # : (RetryNode node) -> void + def visit_retry_node: (RetryNode node) -> void + + # Visit a ReturnNode node + # -- + # : (ReturnNode node) -> void + def visit_return_node: (ReturnNode node) -> void + + # Visit a SelfNode node + # -- + # : (SelfNode node) -> void + def visit_self_node: (SelfNode node) -> void + + # Visit a ShareableConstantNode node + # -- + # : (ShareableConstantNode node) -> void + def visit_shareable_constant_node: (ShareableConstantNode node) -> void + + # Visit a SingletonClassNode node + # -- + # : (SingletonClassNode node) -> void + def visit_singleton_class_node: (SingletonClassNode node) -> void + + # Visit a SourceEncodingNode node + # -- + # : (SourceEncodingNode node) -> void + def visit_source_encoding_node: (SourceEncodingNode node) -> void + + # Visit a SourceFileNode node + # -- + # : (SourceFileNode node) -> void + def visit_source_file_node: (SourceFileNode node) -> void + + # Visit a SourceLineNode node + # -- + # : (SourceLineNode node) -> void + def visit_source_line_node: (SourceLineNode node) -> void + + # Visit a SplatNode node + # -- + # : (SplatNode node) -> void + def visit_splat_node: (SplatNode node) -> void + + # Visit a StatementsNode node + # -- + # : (StatementsNode node) -> void + def visit_statements_node: (StatementsNode node) -> void + + # Visit a StringNode node + # -- + # : (StringNode node) -> void + def visit_string_node: (StringNode node) -> void + + # Visit a SuperNode node + # -- + # : (SuperNode node) -> void + def visit_super_node: (SuperNode node) -> void + + # Visit a SymbolNode node + # -- + # : (SymbolNode node) -> void + def visit_symbol_node: (SymbolNode node) -> void + + # Visit a TrueNode node + # -- + # : (TrueNode node) -> void + def visit_true_node: (TrueNode node) -> void + + # Visit a UndefNode node + # -- + # : (UndefNode node) -> void + def visit_undef_node: (UndefNode node) -> void + + # Visit a UnlessNode node + # -- + # : (UnlessNode node) -> void + def visit_unless_node: (UnlessNode node) -> void + + # Visit a UntilNode node + # -- + # : (UntilNode node) -> void + def visit_until_node: (UntilNode node) -> void + + # Visit a WhenNode node + # -- + # : (WhenNode node) -> void + def visit_when_node: (WhenNode node) -> void + + # Visit a WhileNode node + # -- + # : (WhileNode node) -> void + def visit_while_node: (WhileNode node) -> void + + # Visit a XStringNode node + # -- + # : (XStringNode node) -> void + def visit_x_string_node: (XStringNode node) -> void + + # Visit a YieldNode node + # -- + # : (YieldNode node) -> void + def visit_yield_node: (YieldNode node) -> void + end +end diff --git a/sig/prism/_private/node.rbs b/sig/prism/_private/node.rbs deleted file mode 100644 index b5918a7133..0000000000 --- a/sig/prism/_private/node.rbs +++ /dev/null @@ -1,8 +0,0 @@ -module Prism - class Node - @newline_flag: bool - - def newline_flag?: () -> bool - def newline_flag!: (Array[bool] lines) -> void - end -end diff --git a/sig/prism/_private/node_ext.rbs b/sig/prism/_private/node_ext.rbs deleted file mode 100644 index 82e08f4263..0000000000 --- a/sig/prism/_private/node_ext.rbs +++ /dev/null @@ -1,9 +0,0 @@ -module Prism - module RegularExpressionOptions: InterpolatedMatchLastLineNode, InterpolatedRegularExpressionNode, MatchLastLineNode, RegularExpressionNode - def options: () -> Integer - end - - module HeredocQuery: InterpolatedStringNode, InterpolatedXStringNode, StringNode, XStringNode - def heredoc?: () -> bool? - end -end diff --git a/sig/prism/_private/pack.rbs b/sig/prism/_private/pack.rbs deleted file mode 100644 index ef1eb43d04..0000000000 --- a/sig/prism/_private/pack.rbs +++ /dev/null @@ -1,69 +0,0 @@ -module Prism - module Pack - SPACE: :SPACE - COMMENT: :COMMENT - INTEGER: :INTEGER - UTF8: :UTF8 - BER: :BER - FLOAT: :FLOAT - STRING_SPACE_PADDED: :STRING_SPACE_PADDED - STRING_NULL_PADDED: :STRING_NULL_PADDED - STRING_NULL_TERMINATED: :STRING_NULL_TERMINATED - STRING_MSB: :STRING_MSB - STRING_LSB: :STRING_LSB - STRING_HEX_HIGH: :STRING_HEX_HIGH - STRING_HEX_LOW: :STRING_HEX_LOW - STRING_UU: :STRING_UU - STRING_MIME: :STRING_MIME - STRING_BASE64: :STRING_BASE64 - STRING_FIXED: :STRING_FIXED - STRING_POINTER: :STRING_POINTER - MOVE: :MOVE - BACK: :BACK - NULL: :NULL - UNSIGNED: :UNSIGNED - SIGNED: :SIGNED - SIGNED_NA: :SIGNED_NA - AGNOSTIC_ENDIAN: :AGNOSTIC_ENDIAN - LITTLE_ENDIAN: :LITTLE_ENDIAN - BIG_ENDIAN: :BIG_ENDIAN - NATIVE_ENDIAN: :NATIVE_ENDIAN - ENDIAN_NA: :ENDIAN_NA - SIZE_SHORT: :SIZE_SHORT - SIZE_INT: :SIZE_INT - SIZE_LONG: :SIZE_LONG - SIZE_LONG_LONG: :SIZE_LONG_LONG - SIZE_8: :SIZE_8 - SIZE_16: :SIZE_16 - SIZE_32: :SIZE_32 - SIZE_64: :SIZE_64 - SIZE_P: :SIZE_P - SIZE_NA: :SIZE_NA - LENGTH_FIXED: :LENGTH_FIXED - LENGTH_MAX: :LENGTH_MAX - LENGTH_RELATIVE: :LENGTH_RELATIVE - LENGTH_NA: :LENGTH_NA - - class Directive - ENDIAN_DESCRIPTIONS: Hash[endianness, String] - SIGNED_DESCRIPTIONS: Hash[signness, String] - SIZE_DESCRIPTIONS: Hash[size, String] - - def initialize: ( - Symbol version, - variant variant, - String source, - directive_type type, - signness signed, - endianness endian, - size size, - length_type length_type, - Integer length - ) -> void - end - - class Format - def initialize: (Array[Directive] directives, Encoding encoding) -> void - end - end -end diff --git a/sig/prism/_private/parse_result.rbs b/sig/prism/_private/parse_result.rbs deleted file mode 100644 index 380b6f9dd6..0000000000 --- a/sig/prism/_private/parse_result.rbs +++ /dev/null @@ -1,50 +0,0 @@ -module Prism - class Source - private - - 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 - - def source!: () -> Source - end - - class ParseResult - def attach_comments!: () -> void - def mark_newlines!: () -> untyped - - class Errors - attr_reader parse_result: ParseResult - - def initialize: (ParseResult parse_result) -> void - def format: () -> String - end - - class Newlines < Visitor - @newline_marked: Array[bool] - - # Create a new Newlines visitor with the given newline offsets. - def initialize: (Array[bool] newline_marked) -> void - - def visit_block_node: (BlockNode node) -> void - def visit_lambda_node: (LambdaNode node) -> void - def visit_if_node: (IfNode node) -> void - def visit_unless_node: (UnlessNode node) -> void - def visit_statements_node: (StatementsNode node) -> void - end - end -end diff --git a/sig/prism/_private/pattern.rbs b/sig/prism/_private/pattern.rbs deleted file mode 100644 index 244206d15d..0000000000 --- a/sig/prism/_private/pattern.rbs +++ /dev/null @@ -1,26 +0,0 @@ -module Prism - class Pattern - class CompilationError < StandardError - def initialize: (String) -> void - end - - @compiled: Proc? - - private - - def combine_and: (Proc, Proc) -> Proc - def combine_or: (Proc, Proc) -> Proc - def compile_error: (Prism::node?) -> Proc - def compile_array_pattern_node: (ArrayPatternNode) -> Proc - def compile_alternation_pattern_node: (AlternationPatternNode) -> Proc - def compile_constant_path_node: (ConstantPathNode) -> Proc - def compile_constant_read_node: (ConstantReadNode) -> Proc - def compile_constant_name: (Prism::node, Symbol) -> Proc - def compile_hash_pattern_node: (HashPatternNode) -> Proc - def compile_nil_node: (NilNode) -> Proc - def compile_regular_expression_node: (RegularExpressionNode) -> Proc - def compile_string_node: (StringNode) -> Proc - def compile_symbol_node: (SymbolNode) -> Proc - def compile_node: (Prism::node?) -> Proc - end -end diff --git a/sig/prism/_private/relocation.rbs b/sig/prism/_private/relocation.rbs deleted file mode 100644 index fda123bb37..0000000000 --- a/sig/prism/_private/relocation.rbs +++ /dev/null @@ -1,12 +0,0 @@ -module Prism - module Relocation - class Entry - def reify!: (entry_values values) -> void - end - - class Repository - def enter: (Integer node_id, Symbol field_name) -> Entry - def reify!: () -> void - end - end -end diff --git a/sig/prism/_private/string_query.rbs b/sig/prism/_private/string_query.rbs deleted file mode 100644 index 47ea2ca1a0..0000000000 --- a/sig/prism/_private/string_query.rbs +++ /dev/null @@ -1,7 +0,0 @@ -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/compiler.rbs b/sig/prism/compiler.rbs deleted file mode 100644 index 1afa7db74d..0000000000 --- a/sig/prism/compiler.rbs +++ /dev/null @@ -1,9 +0,0 @@ -module Prism - class Compiler - include _Visitor - - def visit: (Prism::node?) -> untyped - def visit_all: (Array[Prism::node?]) -> untyped - def visit_child_nodes: (Prism::node) -> void - end -end diff --git a/sig/prism/dispatcher.rbs b/sig/prism/dispatcher.rbs deleted file mode 100644 index f58b8661f3..0000000000 --- a/sig/prism/dispatcher.rbs +++ /dev/null @@ -1,19 +0,0 @@ -module Prism - class Dispatcher < Visitor - attr_reader listeners: Hash[Symbol, Array[untyped]] - - def initialize: () -> void - def register: (untyped, *Symbol) -> void - def register_public_methods: (untyped) -> void - def dispatch: (Prism::node) -> void - def dispatch_once: (Prism::node) -> void - - private def register_events: (untyped, Array[Symbol]) -> void - - class DispatchOnce < Visitor - attr_reader listeners: Hash[Symbol, Array[untyped]] - - def initialize: (Hash[Symbol, Array[untyped]]) -> void - end - end -end diff --git a/sig/prism/dot_visitor.rbs b/sig/prism/dot_visitor.rbs deleted file mode 100644 index 46b3dbf419..0000000000 --- a/sig/prism/dot_visitor.rbs +++ /dev/null @@ -1,6 +0,0 @@ -module Prism - class DotVisitor < Visitor - def initialize: () -> void - def to_dot: () -> String - end -end diff --git a/sig/prism/inspect_visitor.rbs b/sig/prism/inspect_visitor.rbs deleted file mode 100644 index 70fa878ac3..0000000000 --- a/sig/prism/inspect_visitor.rbs +++ /dev/null @@ -1,22 +0,0 @@ -module Prism - class InspectVisitor < Visitor - class Replace - attr_reader value: String - - def initialize: (String value) -> void - end - - attr_reader indent: String - attr_reader commands: Array[[String | node | Replace, String]] - - def initialize: (?String indent) -> void - def compose: () -> String - - def self.compose: (node node) -> String - - private - - def inspect_node: (String name, node node) -> String - def inspect_location: (Location? location) -> String - end -end diff --git a/sig/prism/lex_compat.rbs b/sig/prism/lex_compat.rbs deleted file mode 100644 index 5dc1f8764e..0000000000 --- a/sig/prism/lex_compat.rbs +++ /dev/null @@ -1,10 +0,0 @@ -module Prism - class LexCompat - class Result < Prism::Result - attr_reader value: Array[[[Integer, Integer], Symbol, String, untyped]] - - def initialize: (Array[[[Integer, Integer], Symbol, String, untyped]] value, Array[comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - end - end -end diff --git a/sig/prism/node_ext.rbs b/sig/prism/node_ext.rbs deleted file mode 100644 index a187c1d246..0000000000 --- a/sig/prism/node_ext.rbs +++ /dev/null @@ -1,149 +0,0 @@ -module Prism - class Node - def deprecated: (*String replacements) -> void - end - - class InterpolatedMatchLastLineNode < Node - def options: () -> Integer - end - - class InterpolatedRegularExpressionNode < Node - def options: () -> Integer - end - - class MatchLastLineNode < Node - def options: () -> Integer - end - - class RegularExpressionNode < Node - def options: () -> Integer - end - - class InterpolatedStringNode < Node - def heredoc?: () -> bool - end - - class InterpolatedXStringNode < Node - def heredoc?: () -> bool - end - - class StringNode < Node - def heredoc?: () -> bool - def to_interpolated: () -> InterpolatedStringNode - end - - class XStringNode < Node - def heredoc?: () -> bool - def to_interpolated: () -> InterpolatedXStringNode - end - - class ImaginaryNode < Node - def value: () -> Complex - end - - class RationalNode < Node - def value: () -> Rational - def numeric: () -> (IntegerNode | FloatNode) - end - - class ConstantReadNode < Node - def full_name_parts: () -> Array[Symbol] - def full_name: () -> String - end - - class ConstantWriteNode < Node - def full_name_parts: () -> Array[Symbol] - def full_name: () -> String - end - - class ConstantPathNode < Node - class DynamicPartsInConstantPathError < StandardError - end - - class MissingNodesInConstantPathError < StandardError - end - - def full_name_parts: () -> Array[Symbol] - def full_name: () -> String - def child: () -> (ConstantReadNode | MissingNode) - end - - class ConstantPathTargetNode < Node - def full_name_parts: () -> Array[Symbol] - def full_name: () -> String - def child: () -> (ConstantReadNode | MissingNode) - end - - class ConstantTargetNode < Node - def full_name_parts: () -> Array[Symbol] - def full_name: () -> String - end - - class ParametersNode < Node - def signature: () -> Array[[Symbol, Symbol] | [Symbol]] - end - - class CallNode < Node - def full_message_loc: () -> Location? - end - - class CallOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class ClassVariableOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class ConstantOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class ConstantPathOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class GlobalVariableOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class IndexOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class InstanceVariableOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class LocalVariableOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class CaseMatchNode < Node - def consequent: () -> ElseNode? - end - - class CaseNode < Node - def consequent: () -> ElseNode? - end - - class IfNode < Node - def consequent: () -> (ElseNode | IfNode | nil) - end - - class RescueNode < Node - def consequent: () -> RescueNode? - end - - class UnlessNode < Node - def consequent: () -> ElseNode? - end -end diff --git a/sig/prism/pack.rbs b/sig/prism/pack.rbs deleted file mode 100644 index acbc92b69e..0000000000 --- a/sig/prism/pack.rbs +++ /dev/null @@ -1,43 +0,0 @@ -module Prism - module Pack - type variant = :pack | :unpack - - def self.parse: (Symbol version, variant variant, String source) -> Format - - class Directive - type directive_type = :SPACE | :COMMENT | :INTEGER | :UTF8 | :BER | :FLOAT | :STRING_SPACE_PADDED | - :STRING_NULL_PADDED | :STRING_NULL_TERMINATED | :STRING_MSB | :STRING_LSB | - :STRING_HEX_HIGH | :STRING_HEX_LOW | :STRING_UU | :STRING_MIME | :STRING_BASE64 | - :STRING_FIXED | :STRING_POINTER | :MOVE | :BACK | :NULL - - type signness = :UNSIGNED | :SIGNED | :SIGNED_NA - - type endianness = :AGNOSTIC_ENDIAN | :LITTLE_ENDIAN | :BIG_ENDIAN | :NATIVE_ENDIAN | :ENDIAN_NA - - type size = :SIZE_SHORT | :SIZE_INT | :SIZE_LONG | :SIZE_LONG_LONG | :SIZE_8 | :SIZE_16 | :SIZE_32 | - :SIZE_64 | :SIZE_P | :SIZE_NA - - type length_type = :LENGTH_FIXED | :LENGTH_MAX | :LENGTH_RELATIVE | :LENGTH_NA - - - attr_reader version: Symbol - attr_reader variant: variant - attr_reader source: String - attr_reader type: directive_type - attr_reader signed: signness - attr_reader endian: endianness - attr_reader size: size - attr_reader length_type: length_type - attr_reader length: Integer - - def describe: () -> String - end - - class Format - attr_reader directives: Array[Directive] - attr_reader encoding: Encoding - - def describe: () -> String - end - end -end diff --git a/sig/prism/parse_result.rbs b/sig/prism/parse_result.rbs deleted file mode 100644 index cbcf3fc2f8..0000000000 --- a/sig/prism/parse_result.rbs +++ /dev/null @@ -1,197 +0,0 @@ -module Prism - interface _CodeUnitsCache - def []: (Integer byte_offset) -> Integer - end - - class Source - attr_reader source: String - attr_reader start_line: Integer - attr_reader offsets: Array[Integer] - - def initialize: (String source, ?Integer start_line, ?Array[Integer] offsets) -> void - def replace_start_line: (Integer start_line) -> void - def replace_offsets: (Array[Integer] offsets) -> void - def encoding: () -> Encoding - def lines: () -> Array[String] - def slice: (Integer byte_offset, Integer length) -> String - def byte_offset: (Integer line, Integer column) -> Integer - def line: (Integer byte_offset) -> Integer - def line_start: (Integer byte_offset) -> Integer - def line_end: (Integer byte_offset) -> Integer - def line_offset: (Integer byte_offset) -> Integer - def column: (Integer byte_offset) -> Integer - 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 deep_freeze: () -> void - - 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 - - class Location - attr_reader source: Source - attr_reader start_offset: Integer - attr_reader length: Integer - - def initialize: (Source source, Integer start_offset, Integer length) -> void - def leading_comments: () -> Array[comment] - def leading_comment: (comment) -> void - def trailing_comments: () -> Array[comment] - def trailing_comment: (comment) -> void - def comments: () -> Array[comment] - def copy: (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location - def chop: () -> Location - def source_lines: () -> Array[String] - 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 - def adjoin: (String string) -> Location - end - - class Comment - attr_reader location: Location - - def initialize: (Location location) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - def slice: () -> String - end - - interface _Comment - def trailing?: () -> bool - end - - type comment = Comment & _Comment - - class InlineComment < Comment - include _Comment - end - - class EmbDocComment < Comment - include _Comment - end - - class MagicComment - attr_reader key_loc: Location - attr_reader value_loc: Location - - def initialize: (Location key_loc, Location value_loc) -> void - - def key: () -> String - def value: () -> String - - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - end - - class ParseError - attr_reader type: Symbol - attr_reader message: String - attr_reader location: Location - attr_reader level: Symbol - - def initialize: (Symbol type, String message, Location location, Symbol level) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - end - - class ParseWarning - attr_reader type: Symbol - attr_reader message: String - attr_reader location: Location - attr_reader level: Symbol - - def initialize: (Symbol type, String message, Location location, Symbol level) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - end - - class Result - attr_reader comments: Array[comment] - attr_reader magic_comments: Array[MagicComment] - attr_reader data_loc: Location? - attr_reader errors: Array[ParseError] - attr_reader warnings: Array[ParseWarning] - attr_reader source: Source - - def initialize: (Array[comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - def encoding: () -> Encoding - def success?: () -> bool - def failure?: () -> bool - def code_units_cache: (Encoding encoding) -> _CodeUnitsCache - end - - class ParseResult < Result - attr_reader value: ProgramNode - - def initialize: (ProgramNode value, Array[comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - def errors_format: () -> String - end - - class LexResult < Result - attr_reader value: Array[[Token, Integer]] - - def initialize: (Array[[Token, Integer]] value, Array[comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - end - - class ParseLexResult < Result - attr_reader value: [ProgramNode, Array[[Token, Integer]]] - - def initialize: ([ProgramNode, Array[[Token, Integer]]] value, Array[comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - end - - class Token - attr_reader source: Source - attr_reader type: Symbol - attr_reader value: String - attr_reader location: Location - - def initialize: (Source source, Symbol type, String value, Location location) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - def pretty_print: (untyped q) -> untyped - def ==: (untyped other) -> bool - def deep_freeze: () -> void - end - - class Scope - attr_reader locals: Array[Symbol] - attr_reader forwarding: Array[Symbol] - - def initialize: (Array[Symbol] locals, Array[Symbol] forwarding) -> void - end -end diff --git a/sig/prism/parse_result/comments.rbs b/sig/prism/parse_result/comments.rbs deleted file mode 100644 index 5b9e315063..0000000000 --- a/sig/prism/parse_result/comments.rbs +++ /dev/null @@ -1,38 +0,0 @@ -module Prism - class ParseResult < Result - class Comments - interface _Target - def start_offset: () -> Integer - def end_offset: () -> Integer - def encloses?: (comment) -> bool - def leading_comment: (comment) -> void - def trailing_comment: (comment) -> void - end - - class NodeTarget - include _Target - - attr_reader node: node - - def initialize: (node) -> void - end - - class LocationTarget - include _Target - - attr_reader location: Location - - def initialize: (Location location) -> void - end - - attr_reader parse_result: ParseResult - - def initialize: (ParseResult parse_result) -> void - def attach!: () -> void - - private - - def nearest_targets: (node, comment) -> [_Target?, _Target, _Target?] - end - end -end diff --git a/sig/prism/pattern.rbs b/sig/prism/pattern.rbs deleted file mode 100644 index a70293e18b..0000000000 --- a/sig/prism/pattern.rbs +++ /dev/null @@ -1,13 +0,0 @@ -module Prism - class Pattern - class CompilationError < StandardError - end - - attr_reader query: String - - def initialize: (String query) -> void - def compile: () -> Proc - def scan: (Prism::node root) { (Prism::node) -> void } -> void - | (Prism::node root) -> ::Enumerator[Prism::node, void] - end -end diff --git a/sig/prism/reflection.rbs b/sig/prism/reflection.rbs deleted file mode 100644 index 047ea32a50..0000000000 --- a/sig/prism/reflection.rbs +++ /dev/null @@ -1,50 +0,0 @@ -module Prism - module Reflection - class Field - attr_reader name: Symbol - - def initialize: (Symbol name) -> void - end - - class NodeField < Field - end - - class OptionalNodeField < Field - end - - class NodeListField < Field - end - - class ConstantField < Field - end - - class OptionalConstantField < Field - end - - class ConstantListField < Field - end - - class StringField < Field - end - - class LocationField < Field - end - - class OptionalLocationField < Field - end - - class IntegerField < Field - end - - class FloatField < Field - end - - class FlagsField < Field - attr_reader flags: Array[Symbol] - - def initialize: (Symbol name, Array[Symbol] flags) -> void - end - - def self.fields_for: (singleton(Node) node) -> Array[Field] - end -end diff --git a/sig/prism/relocation.rbs b/sig/prism/relocation.rbs deleted file mode 100644 index 7f5637d5fa..0000000000 --- a/sig/prism/relocation.rbs +++ /dev/null @@ -1,185 +0,0 @@ -module Prism - module Relocation - interface _Value - def start_line: () -> Integer - def end_line: () -> Integer - def start_offset: () -> Integer - def end_offset: () -> Integer - def start_character_offset: () -> Integer - def end_character_offset: () -> Integer - def cached_start_code_units_offset: (_CodeUnitsCache cache) -> Integer - def cached_end_code_units_offset: (_CodeUnitsCache cache) -> Integer - def start_column: () -> Integer - def end_column: () -> Integer - def start_character_column: () -> Integer - def end_character_column: () -> Integer - def cached_start_code_units_column: (_CodeUnitsCache cache) -> Integer - def cached_end_code_units_column: (_CodeUnitsCache cache) -> Integer - def leading_comments: () -> Array[Comment] - def trailing_comments: () -> Array[Comment] - end - - interface _Field - def fields: (_Value value) -> entry_values - end - - type entry_value = untyped - type entry_values = Hash[Symbol, entry_value] - - class Entry - class MissingValueError < StandardError - end - - def initialize: (Repository repository) -> void - - def filepath: () -> String - - def start_line: () -> Integer - def end_line: () -> Integer - - def start_offset: () -> Integer - def end_offset: () -> Integer - def start_character_offset: () -> Integer - def end_character_offset: () -> Integer - def start_code_units_offset: () -> Integer - def end_code_units_offset: () -> Integer - - def start_column: () -> Integer - def end_column: () -> Integer - def start_character_column: () -> Integer - def end_character_column: () -> Integer - def start_code_units_column: () -> Integer - def end_code_units_column: () -> Integer - - def leading_comments: () -> Array[CommentsField::Comment] - def trailing_comments: () -> Array[CommentsField::Comment] - def comments: () -> Array[CommentsField::Comment] - - private - - def fetch_value: (Symbol name) -> entry_value - def values: () -> entry_values - end - - class Source - attr_reader value: untyped - - def initialize: (untyped value) -> void - - def result: () -> ParseResult - def code_units_cache: (Encoding encoding) -> _CodeUnitsCache - end - - class SourceFilepath < Source - def result: () -> ParseResult - end - - class SourceString < Source - def result: () -> ParseResult - end - - class FilepathField - attr_reader value: String - - def initialize: (String value) -> void - - def fields: (_Value value) -> entry_values - end - - class LinesField - def fields: (_Value value) -> entry_values - end - - class OffsetsField - def fields: (_Value value) -> entry_values - end - - class CharacterOffsetsField - def fields: (_Value value) -> entry_values - end - - class CodeUnitOffsetsField - attr_reader repository: Repository - attr_reader encoding: Encoding - - def initialize: (Repository repository, Encoding encoding) -> void - def fields: (_Value value) -> entry_values - - private - - def cache: () -> _CodeUnitsCache - end - - class ColumnsField - def fields: (_Value value) -> entry_values - end - - class CharacterColumnsField - def fields: (_Value value) -> entry_values - end - - class CodeUnitColumnsField - attr_reader repository: Repository - attr_reader encoding: Encoding - - def initialize: (Repository repository, Encoding encoding) -> void - def fields: (_Value value) -> entry_values - - private - - def cache: () -> _CodeUnitsCache - end - - class CommentsField - class Comment - attr_reader slice: String - - def initialize: (String slice) -> void - end - - private - - def comments: (entry_value value) -> Array[Comment] - end - - class LeadingCommentsField < CommentsField - def fields: (_Value value) -> entry_values - end - - class TrailingCommentsField < CommentsField - def fields: (_Value value) -> entry_values - end - - class Repository - class ConfigurationError < StandardError - end - - attr_reader source: Source - attr_reader fields: Hash[Symbol, _Field] - attr_reader entries: Hash[Integer, Hash[Symbol, Entry]] - - def initialize: (Source source) -> void - - def code_units_cache: (Encoding encoding) -> _CodeUnitsCache - - def filepath: () -> self - def lines: () -> self - def offsets: () -> self - def character_offsets: () -> self - def code_unit_offsets: (Encoding encoding) -> self - def columns: () -> self - def character_columns: () -> self - def code_unit_columns: (Encoding encoding) -> self - def leading_comments: () -> self - def trailing_comments: () -> self - def comments: () -> self - - private - - def field: (Symbol name, _Field) -> self - end - - def self.filepath: (String value) -> Repository - def self.string: (String value) -> Repository - end -end diff --git a/sig/prism/serialize.rbs b/sig/prism/serialize.rbs deleted file mode 100644 index 71a7c5c1c9..0000000000 --- a/sig/prism/serialize.rbs +++ /dev/null @@ -1,8 +0,0 @@ -module Prism - module Serialize - def self.load_parse: (String, String, bool) -> ParseResult - def self.load_lex: (String, String, bool) -> LexResult - def self.load_parse_comments: (String, String, bool) -> Array[comment] - def self.load_parse_lex: (String, String, bool) -> ParseLexResult - end -end diff --git a/sig/prism/string_query.rbs b/sig/prism/string_query.rbs deleted file mode 100644 index 098746e552..0000000000 --- a/sig/prism/string_query.rbs +++ /dev/null @@ -1,11 +0,0 @@ -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/snapshots/4.0/endless_methods_command_call.txt b/snapshots/4.0/endless_methods_command_call.txt index d2c58ec8b0..cb819358ef 100644 --- a/snapshots/4.0/endless_methods_command_call.txt +++ b/snapshots/4.0/endless_methods_command_call.txt @@ -1,10 +1,10 @@ -@ ProgramNode (location: (1,0)-(8,31)) +@ ProgramNode (location: (1,0)-(11,37)) ├── flags: ∅ ├── locals: [] └── statements: - @ StatementsNode (location: (1,0)-(8,31)) + @ StatementsNode (location: (1,0)-(11,37)) ├── flags: ∅ - └── body: (length: 8) + └── body: (length: 10) ├── @ CallNode (location: (1,0)-(1,30)) │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ @@ -421,75 +421,208 @@ │ ├── closing_loc: ∅ │ ├── equal_loc: ∅ │ └── block: ∅ - └── @ CallNode (location: (8,0)-(8,31)) + ├── @ CallNode (location: (8,0)-(8,31)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :private + │ ├── message_loc: (8,0)-(8,7) = "private" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (8,8)-(8,31)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ DefNode (location: (8,8)-(8,31)) + │ │ ├── flags: ∅ + │ │ ├── name: :foo + │ │ ├── name_loc: (8,16)-(8,19) = "foo" + │ │ ├── receiver: + │ │ │ @ CallNode (location: (8,12)-(8,15)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :obj + │ │ │ ├── message_loc: (8,12)-(8,15) = "obj" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── parameters: + │ │ │ @ ParametersNode (location: (8,20)-(8,21)) + │ │ │ ├── flags: ∅ + │ │ │ ├── requireds: (length: 1) + │ │ │ │ └── @ RequiredParameterNode (location: (8,20)-(8,21)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :x + │ │ │ ├── optionals: (length: 0) + │ │ │ ├── rest: ∅ + │ │ │ ├── posts: (length: 0) + │ │ │ ├── keywords: (length: 0) + │ │ │ ├── keyword_rest: ∅ + │ │ │ └── block: ∅ + │ │ ├── body: + │ │ │ @ StatementsNode (location: (8,25)-(8,31)) + │ │ │ ├── flags: ∅ + │ │ │ └── body: (length: 1) + │ │ │ └── @ CallNode (location: (8,25)-(8,31)) + │ │ │ ├── flags: ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :puts + │ │ │ ├── message_loc: (8,25)-(8,29) = "puts" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: + │ │ │ │ @ ArgumentsNode (location: (8,30)-(8,31)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── arguments: (length: 1) + │ │ │ │ └── @ LocalVariableReadNode (location: (8,30)-(8,31)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── name: :x + │ │ │ │ └── depth: 0 + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── locals: [:x] + │ │ ├── def_keyword_loc: (8,8)-(8,11) = "def" + │ │ ├── operator_loc: (8,15)-(8,16) = "." + │ │ ├── lparen_loc: (8,19)-(8,20) = "(" + │ │ ├── rparen_loc: (8,21)-(8,22) = ")" + │ │ ├── equal_loc: (8,23)-(8,24) = "=" + │ │ └── end_keyword_loc: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (10,0)-(10,25)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :private + │ ├── message_loc: (10,0)-(10,7) = "private" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (10,8)-(10,25)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ DefNode (location: (10,8)-(10,25)) + │ │ ├── flags: ∅ + │ │ ├── name: :foo + │ │ ├── name_loc: (10,12)-(10,15) = "foo" + │ │ ├── receiver: ∅ + │ │ ├── parameters: ∅ + │ │ ├── body: + │ │ │ @ StatementsNode (location: (10,18)-(10,25)) + │ │ │ ├── flags: ∅ + │ │ │ └── body: (length: 1) + │ │ │ └── @ CallNode (location: (10,18)-(10,25)) + │ │ │ ├── flags: ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :bar + │ │ │ ├── message_loc: (10,18)-(10,21) = "bar" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: + │ │ │ │ @ ArgumentsNode (location: (10,22)-(10,25)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── arguments: (length: 1) + │ │ │ │ └── @ CallNode (location: (10,22)-(10,25)) + │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── receiver: ∅ + │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ ├── name: :baz + │ │ │ │ ├── message_loc: (10,22)-(10,25) = "baz" + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── arguments: ∅ + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ ├── equal_loc: ∅ + │ │ │ │ └── block: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── locals: [] + │ │ ├── def_keyword_loc: (10,8)-(10,11) = "def" + │ │ ├── operator_loc: ∅ + │ │ ├── lparen_loc: ∅ + │ │ ├── rparen_loc: ∅ + │ │ ├── equal_loc: (10,16)-(10,17) = "=" + │ │ └── end_keyword_loc: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + └── @ CallNode (location: (11,0)-(11,37)) ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :private - ├── message_loc: (8,0)-(8,7) = "private" + ├── message_loc: (11,0)-(11,7) = "private" ├── opening_loc: ∅ ├── arguments: - │ @ ArgumentsNode (location: (8,8)-(8,31)) + │ @ ArgumentsNode (location: (11,8)-(11,25)) │ ├── flags: ∅ │ └── arguments: (length: 1) - │ └── @ DefNode (location: (8,8)-(8,31)) + │ └── @ DefNode (location: (11,8)-(11,25)) │ ├── flags: ∅ │ ├── name: :foo - │ ├── name_loc: (8,16)-(8,19) = "foo" - │ ├── receiver: - │ │ @ CallNode (location: (8,12)-(8,15)) - │ │ ├── flags: variable_call, ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :obj - │ │ ├── message_loc: (8,12)-(8,15) = "obj" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: ∅ - │ │ ├── closing_loc: ∅ - │ │ ├── equal_loc: ∅ - │ │ └── block: ∅ - │ ├── parameters: - │ │ @ ParametersNode (location: (8,20)-(8,21)) - │ │ ├── flags: ∅ - │ │ ├── requireds: (length: 1) - │ │ │ └── @ RequiredParameterNode (location: (8,20)-(8,21)) - │ │ │ ├── flags: ∅ - │ │ │ └── name: :x - │ │ ├── optionals: (length: 0) - │ │ ├── rest: ∅ - │ │ ├── posts: (length: 0) - │ │ ├── keywords: (length: 0) - │ │ ├── keyword_rest: ∅ - │ │ └── block: ∅ + │ ├── name_loc: (11,12)-(11,15) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: ∅ │ ├── body: - │ │ @ StatementsNode (location: (8,25)-(8,31)) + │ │ @ StatementsNode (location: (11,18)-(11,25)) │ │ ├── flags: ∅ │ │ └── body: (length: 1) - │ │ └── @ CallNode (location: (8,25)-(8,31)) + │ │ └── @ CallNode (location: (11,18)-(11,25)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :puts - │ │ ├── message_loc: (8,25)-(8,29) = "puts" + │ │ ├── name: :bar + │ │ ├── message_loc: (11,18)-(11,21) = "bar" │ │ ├── opening_loc: ∅ │ │ ├── arguments: - │ │ │ @ ArgumentsNode (location: (8,30)-(8,31)) + │ │ │ @ ArgumentsNode (location: (11,22)-(11,25)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) - │ │ │ └── @ LocalVariableReadNode (location: (8,30)-(8,31)) - │ │ │ ├── flags: ∅ - │ │ │ ├── name: :x - │ │ │ └── depth: 0 + │ │ │ └── @ CallNode (location: (11,22)-(11,25)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :baz + │ │ │ ├── message_loc: (11,22)-(11,25) = "baz" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ │ │ ├── closing_loc: ∅ │ │ ├── equal_loc: ∅ │ │ └── block: ∅ - │ ├── locals: [:x] - │ ├── def_keyword_loc: (8,8)-(8,11) = "def" - │ ├── operator_loc: (8,15)-(8,16) = "." - │ ├── lparen_loc: (8,19)-(8,20) = "(" - │ ├── rparen_loc: (8,21)-(8,22) = ")" - │ ├── equal_loc: (8,23)-(8,24) = "=" + │ ├── locals: [] + │ ├── def_keyword_loc: (11,8)-(11,11) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: ∅ + │ ├── rparen_loc: ∅ + │ ├── equal_loc: (11,16)-(11,17) = "=" │ └── end_keyword_loc: ∅ ├── closing_loc: ∅ ├── equal_loc: ∅ - └── block: ∅ + └── block: + @ BlockNode (location: (11,26)-(11,37)) + ├── flags: ∅ + ├── locals: [] + ├── parameters: ∅ + ├── body: + │ @ StatementsNode (location: (11,29)-(11,33)) + │ ├── flags: ∅ + │ └── body: (length: 1) + │ └── @ CallNode (location: (11,29)-(11,33)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :expr + │ ├── message_loc: (11,29)-(11,33) = "expr" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── opening_loc: (11,26)-(11,28) = "do" + └── closing_loc: (11,34)-(11,37) = "end" diff --git a/snapshots/4.0/leading_logical.txt b/snapshots/4.0/leading_logical.txt index 9e043a88ce..c8ecaa40ba 100644 --- a/snapshots/4.0/leading_logical.txt +++ b/snapshots/4.0/leading_logical.txt @@ -1,10 +1,10 @@ -@ ProgramNode (location: (1,0)-(21,5)) +@ ProgramNode (location: (1,0)-(15,4)) ├── flags: ∅ ├── locals: [] └── statements: - @ StatementsNode (location: (1,0)-(21,5)) + @ StatementsNode (location: (1,0)-(15,4)) ├── flags: ∅ - └── body: (length: 8) + └── body: (length: 4) ├── @ AndNode (location: (1,0)-(3,4)) │ ├── flags: newline │ ├── left: @@ -62,50 +62,22 @@ │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ └── operator_loc: (11,0)-(11,3) = "and" - ├── @ OrNode (location: (13,0)-(15,4)) - │ ├── flags: newline - │ ├── left: - │ │ @ OrNode (location: (13,0)-(14,4)) - │ │ ├── flags: ∅ - │ │ ├── left: - │ │ │ @ IntegerNode (location: (13,0)-(13,1)) - │ │ │ ├── flags: static_literal, decimal - │ │ │ └── value: 1 - │ │ ├── right: - │ │ │ @ IntegerNode (location: (14,3)-(14,4)) - │ │ │ ├── flags: static_literal, decimal - │ │ │ └── value: 2 - │ │ └── operator_loc: (14,0)-(14,2) = "or" - │ ├── right: - │ │ @ IntegerNode (location: (15,3)-(15,4)) - │ │ ├── flags: static_literal, decimal - │ │ └── value: 3 - │ └── operator_loc: (15,0)-(15,2) = "or" - ├── @ IntegerNode (location: (17,0)-(17,1)) - │ ├── flags: newline, static_literal, decimal - │ └── value: 1 - ├── @ CallNode (location: (18,0)-(18,6)) - │ ├── flags: newline, variable_call, ignore_visibility - │ ├── receiver: ∅ - │ ├── call_operator_loc: ∅ - │ ├── name: :andfoo - │ ├── message_loc: (18,0)-(18,6) = "andfoo" - │ ├── opening_loc: ∅ - │ ├── arguments: ∅ - │ ├── closing_loc: ∅ - │ ├── equal_loc: ∅ - │ └── block: ∅ - ├── @ IntegerNode (location: (20,0)-(20,1)) - │ ├── flags: newline, static_literal, decimal - │ └── value: 2 - └── @ CallNode (location: (21,0)-(21,5)) - ├── flags: newline, variable_call, ignore_visibility - ├── receiver: ∅ - ├── call_operator_loc: ∅ - ├── name: :orfoo - ├── message_loc: (21,0)-(21,5) = "orfoo" - ├── opening_loc: ∅ - ├── arguments: ∅ - ├── closing_loc: ∅ - ├── equal_loc: ∅ - └── block: ∅ + └── @ OrNode (location: (13,0)-(15,4)) + ├── flags: newline + ├── left: + │ @ OrNode (location: (13,0)-(14,4)) + │ ├── flags: ∅ + │ ├── left: + │ │ @ IntegerNode (location: (13,0)-(13,1)) + │ │ ├── flags: static_literal, decimal + │ │ └── value: 1 + │ ├── right: + │ │ @ IntegerNode (location: (14,3)-(14,4)) + │ │ ├── flags: static_literal, decimal + │ │ └── value: 2 + │ └── operator_loc: (14,0)-(14,2) = "or" + ├── right: + │ @ IntegerNode (location: (15,3)-(15,4)) + │ ├── flags: static_literal, decimal + │ └── value: 3 + └── operator_loc: (15,0)-(15,2) = "or" diff --git a/snapshots/4.1/noblock.txt b/snapshots/4.1/noblock.txt new file mode 100644 index 0000000000..ce2827c24f --- /dev/null +++ b/snapshots/4.1/noblock.txt @@ -0,0 +1,61 @@ +@ ProgramNode (location: (1,0)-(4,12)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(4,12)) + ├── flags: ∅ + └── body: (length: 2) + ├── @ 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: 0) + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: + │ │ @ NoBlockParameterNode (location: (1,8)-(1,12)) + │ │ ├── flags: ∅ + │ │ ├── operator_loc: (1,8)-(1,9) = "&" + │ │ └── keyword_loc: (1,9)-(1,12) = "nil" + │ ├── body: ∅ + │ ├── locals: [] + │ ├── def_keyword_loc: (1,0)-(1,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (1,7)-(1,8) = "(" + │ ├── rparen_loc: (1,12)-(1,13) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (2,0)-(2,3) = "end" + └── @ LambdaNode (location: (4,0)-(4,12)) + ├── flags: newline + ├── locals: [] + ├── operator_loc: (4,0)-(4,2) = "->" + ├── opening_loc: (4,10)-(4,11) = "{" + ├── closing_loc: (4,11)-(4,12) = "}" + ├── parameters: + │ @ BlockParametersNode (location: (4,3)-(4,9)) + │ ├── flags: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (4,4)-(4,8)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 0) + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: + │ │ @ NoBlockParameterNode (location: (4,4)-(4,8)) + │ │ ├── flags: ∅ + │ │ ├── operator_loc: (4,4)-(4,5) = "&" + │ │ └── keyword_loc: (4,5)-(4,8) = "nil" + │ ├── locals: (length: 0) + │ ├── opening_loc: (4,3)-(4,4) = "(" + │ └── closing_loc: (4,8)-(4,9) = ")" + └── body: ∅ diff --git a/snapshots/4.1/trailing_comma_after_method_arguments.txt b/snapshots/4.1/trailing_comma_after_method_arguments.txt new file mode 100644 index 0000000000..b71459ff54 --- /dev/null +++ b/snapshots/4.1/trailing_comma_after_method_arguments.txt @@ -0,0 +1,207 @@ +@ ProgramNode (location: (1,0)-(15,5)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(15,5)) + ├── flags: ∅ + └── body: (length: 6) + ├── @ DefNode (location: (1,0)-(1,19)) + │ ├── flags: newline + │ ├── name: :foo + │ ├── name_loc: (1,4)-(1,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (1,8)-(1,13)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 3) + │ │ │ ├── @ RequiredParameterNode (location: (1,8)-(1,9)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :a + │ │ │ ├── @ RequiredParameterNode (location: (1,10)-(1,11)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :b + │ │ │ └── @ RequiredParameterNode (location: (1,12)-(1,13)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :c + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :b, :c] + │ ├── def_keyword_loc: (1,0)-(1,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (1,7)-(1,8) = "(" + │ ├── rparen_loc: (1,14)-(1,15) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (1,16)-(1,19) = "end" + ├── @ DefNode (location: (3,0)-(3,20)) + │ ├── flags: newline + │ ├── name: :foo + │ ├── name_loc: (3,4)-(3,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (3,8)-(3,14)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 2) + │ │ │ ├── @ RequiredParameterNode (location: (3,8)-(3,9)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :a + │ │ │ └── @ RequiredParameterNode (location: (3,10)-(3,11)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :b + │ │ ├── optionals: (length: 0) + │ │ ├── rest: + │ │ │ @ RestParameterNode (location: (3,12)-(3,14)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :c + │ │ │ ├── name_loc: (3,13)-(3,14) = "c" + │ │ │ └── operator_loc: (3,12)-(3,13) = "*" + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :b, :c] + │ ├── def_keyword_loc: (3,0)-(3,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (3,7)-(3,8) = "(" + │ ├── rparen_loc: (3,15)-(3,16) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (3,17)-(3,20) = "end" + ├── @ DefNode (location: (5,0)-(5,19)) + │ ├── flags: newline + │ ├── name: :foo + │ ├── name_loc: (5,4)-(5,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (5,8)-(5,13)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 2) + │ │ │ ├── @ RequiredParameterNode (location: (5,8)-(5,9)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :a + │ │ │ └── @ RequiredParameterNode (location: (5,10)-(5,11)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :b + │ │ ├── optionals: (length: 0) + │ │ ├── rest: + │ │ │ @ RestParameterNode (location: (5,12)-(5,13)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: ∅ + │ │ │ ├── name_loc: ∅ + │ │ │ └── operator_loc: (5,12)-(5,13) = "*" + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :b] + │ ├── def_keyword_loc: (5,0)-(5,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (5,7)-(5,8) = "(" + │ ├── rparen_loc: (5,14)-(5,15) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (5,16)-(5,19) = "end" + ├── @ DefNode (location: (7,0)-(7,21)) + │ ├── flags: newline + │ ├── name: :foo + │ ├── name_loc: (7,4)-(7,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (7,8)-(7,15)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 2) + │ │ │ ├── @ RequiredParameterNode (location: (7,8)-(7,9)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :a + │ │ │ └── @ RequiredParameterNode (location: (7,10)-(7,11)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :b + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: + │ │ │ @ KeywordRestParameterNode (location: (7,12)-(7,15)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :c + │ │ │ ├── name_loc: (7,14)-(7,15) = "c" + │ │ │ └── operator_loc: (7,12)-(7,14) = "**" + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :b, :c] + │ ├── def_keyword_loc: (7,0)-(7,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (7,7)-(7,8) = "(" + │ ├── rparen_loc: (7,16)-(7,17) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (7,18)-(7,21) = "end" + ├── @ DefNode (location: (9,0)-(9,20)) + │ ├── flags: newline + │ ├── name: :foo + │ ├── name_loc: (9,4)-(9,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (9,8)-(9,14)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 2) + │ │ │ ├── @ RequiredParameterNode (location: (9,8)-(9,9)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :a + │ │ │ └── @ RequiredParameterNode (location: (9,10)-(9,11)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :b + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: + │ │ │ @ KeywordRestParameterNode (location: (9,12)-(9,14)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: ∅ + │ │ │ ├── name_loc: ∅ + │ │ │ └── operator_loc: (9,12)-(9,14) = "**" + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :b] + │ ├── def_keyword_loc: (9,0)-(9,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (9,7)-(9,8) = "(" + │ ├── rparen_loc: (9,15)-(9,16) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (9,17)-(9,20) = "end" + └── @ DefNode (location: (11,0)-(15,5)) + ├── flags: newline + ├── name: :foo + ├── name_loc: (11,4)-(11,7) = "foo" + ├── receiver: ∅ + ├── parameters: + │ @ ParametersNode (location: (12,2)-(14,3)) + │ ├── flags: ∅ + │ ├── requireds: (length: 3) + │ │ ├── @ RequiredParameterNode (location: (12,2)-(12,3)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :a + │ │ ├── @ RequiredParameterNode (location: (13,2)-(13,3)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :b + │ │ └── @ RequiredParameterNode (location: (14,2)-(14,3)) + │ │ ├── flags: ∅ + │ │ └── name: :c + │ ├── optionals: (length: 0) + │ ├── rest: ∅ + │ ├── posts: (length: 0) + │ ├── keywords: (length: 0) + │ ├── keyword_rest: ∅ + │ └── block: ∅ + ├── body: ∅ + ├── locals: [:a, :b, :c] + ├── def_keyword_loc: (11,0)-(11,3) = "def" + ├── operator_loc: ∅ + ├── lparen_loc: (11,7)-(11,8) = "(" + ├── rparen_loc: (15,0)-(15,1) = ")" + ├── equal_loc: ∅ + └── end_keyword_loc: (15,2)-(15,5) = "end" diff --git a/snapshots/and_or_with_suffix.txt b/snapshots/and_or_with_suffix.txt new file mode 100644 index 0000000000..593dee1766 --- /dev/null +++ b/snapshots/and_or_with_suffix.txt @@ -0,0 +1,139 @@ +@ ProgramNode (location: (1,0)-(17,5)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(17,5)) + ├── flags: ∅ + └── body: (length: 12) + ├── @ CallNode (location: (1,0)-(1,3)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (1,0)-(1,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (2,0)-(2,4)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :and? + │ ├── message_loc: (2,0)-(2,4) = "and?" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (4,0)-(4,3)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (4,0)-(4,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (5,0)-(5,3)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :or? + │ ├── message_loc: (5,0)-(5,3) = "or?" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (7,0)-(7,3)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (7,0)-(7,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (8,0)-(8,4)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :and! + │ ├── message_loc: (8,0)-(8,4) = "and!" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (10,0)-(10,3)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (10,0)-(10,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (11,0)-(11,3)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :or! + │ ├── message_loc: (11,0)-(11,3) = "or!" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (13,0)-(13,3)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (13,0)-(13,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (14,0)-(14,6)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :andbar + │ ├── message_loc: (14,0)-(14,6) = "andbar" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (16,0)-(16,3)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (16,0)-(16,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + └── @ CallNode (location: (17,0)-(17,5)) + ├── flags: newline, variable_call, ignore_visibility + ├── receiver: ∅ + ├── call_operator_loc: ∅ + ├── name: :orbar + ├── message_loc: (17,0)-(17,5) = "orbar" + ├── opening_loc: ∅ + ├── arguments: ∅ + ├── closing_loc: ∅ + ├── equal_loc: ∅ + └── block: ∅ diff --git a/snapshots/blocks.txt b/snapshots/blocks.txt index 62943535e1..03148044f9 100644 --- a/snapshots/blocks.txt +++ b/snapshots/blocks.txt @@ -1,10 +1,10 @@ -@ ProgramNode (location: (1,0)-(54,17)) +@ ProgramNode (location: (1,0)-(62,25)) ├── flags: ∅ ├── locals: [:fork] └── statements: - @ StatementsNode (location: (1,0)-(54,17)) + @ StatementsNode (location: (1,0)-(62,25)) ├── flags: ∅ - └── body: (length: 20) + └── body: (length: 24) ├── @ CallNode (location: (1,0)-(1,16)) │ ├── flags: newline │ ├── receiver: @@ -829,41 +829,284 @@ │ ├── closing_loc: ∅ │ ├── equal_loc: ∅ │ └── block: ∅ - └── @ CallNode (location: (54,0)-(54,17)) + ├── @ CallNode (location: (54,0)-(54,17)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (54,0)-(54,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_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: ∅ + │ │ │ │ └── name: :bar + │ │ │ ├── optionals: (length: 0) + │ │ │ ├── rest: + │ │ │ │ @ ImplicitRestNode (location: (54,11)-(54,12)) + │ │ │ │ └── flags: ∅ + │ │ │ ├── posts: (length: 0) + │ │ │ ├── keywords: (length: 0) + │ │ │ ├── keyword_rest: ∅ + │ │ │ └── block: ∅ + │ │ ├── locals: (length: 0) + │ │ ├── opening_loc: (54,7)-(54,8) = "|" + │ │ └── closing_loc: (54,12)-(54,13) = "|" + │ ├── body: ∅ + │ ├── opening_loc: (54,4)-(54,6) = "do" + │ └── closing_loc: (54,14)-(54,17) = "end" + ├── @ CallNode (location: (56,0)-(56,23)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (56,0)-(56,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (56,4)-(56,16)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ CallNode (location: (56,4)-(56,16)) + │ │ ├── flags: ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :bar + │ │ ├── message_loc: (56,4)-(56,7) = "bar" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: + │ │ │ @ ArgumentsNode (location: (56,8)-(56,16)) + │ │ │ ├── flags: ∅ + │ │ │ └── arguments: (length: 2) + │ │ │ ├── @ CallNode (location: (56,8)-(56,11)) + │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── receiver: ∅ + │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ ├── name: :baz + │ │ │ │ ├── message_loc: (56,8)-(56,11) = "baz" + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── arguments: ∅ + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ ├── equal_loc: ∅ + │ │ │ │ └── block: ∅ + │ │ │ └── @ CallNode (location: (56,13)-(56,16)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :qux + │ │ │ ├── message_loc: (56,13)-(56,16) = "qux" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: + │ @ BlockNode (location: (56,17)-(56,23)) + │ ├── flags: ∅ + │ ├── locals: [] + │ ├── parameters: ∅ + │ ├── body: ∅ + │ ├── opening_loc: (56,17)-(56,19) = "do" + │ └── closing_loc: (56,20)-(56,23) = "end" + ├── @ CallNode (location: (58,0)-(58,18)) + │ ├── flags: newline + │ ├── receiver: + │ │ @ CallNode (location: (58,0)-(58,3)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :foo + │ │ ├── message_loc: (58,0)-(58,3) = "foo" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ ├── call_operator_loc: (58,3)-(58,4) = "." + │ ├── name: :bar + │ ├── message_loc: (58,4)-(58,7) = "bar" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (58,8)-(58,11)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ CallNode (location: (58,8)-(58,11)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :baz + │ │ ├── message_loc: (58,8)-(58,11) = "baz" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: + │ @ BlockNode (location: (58,12)-(58,18)) + │ ├── flags: ∅ + │ ├── locals: [] + │ ├── parameters: ∅ + │ ├── body: ∅ + │ ├── opening_loc: (58,12)-(58,14) = "do" + │ └── closing_loc: (58,15)-(58,18) = "end" + ├── @ CallNode (location: (60,0)-(60,34)) + │ ├── flags: newline + │ ├── receiver: + │ │ @ CallNode (location: (60,0)-(60,18)) + │ │ ├── flags: ∅ + │ │ ├── receiver: + │ │ │ @ CallNode (location: (60,0)-(60,3)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :foo + │ │ │ ├── message_loc: (60,0)-(60,3) = "foo" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── call_operator_loc: (60,3)-(60,4) = "." + │ │ ├── name: :bar + │ │ ├── message_loc: (60,4)-(60,7) = "bar" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: + │ │ │ @ ArgumentsNode (location: (60,8)-(60,11)) + │ │ │ ├── flags: ∅ + │ │ │ └── arguments: (length: 1) + │ │ │ └── @ CallNode (location: (60,8)-(60,11)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :baz + │ │ │ ├── message_loc: (60,8)-(60,11) = "baz" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: + │ │ @ BlockNode (location: (60,12)-(60,18)) + │ │ ├── flags: ∅ + │ │ ├── locals: [] + │ │ ├── parameters: ∅ + │ │ ├── body: ∅ + │ │ ├── opening_loc: (60,12)-(60,14) = "do" + │ │ └── closing_loc: (60,15)-(60,18) = "end" + │ ├── call_operator_loc: (60,18)-(60,19) = "." + │ ├── name: :qux + │ ├── message_loc: (60,19)-(60,22) = "qux" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (60,23)-(60,27)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ CallNode (location: (60,23)-(60,27)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :quux + │ │ ├── message_loc: (60,23)-(60,27) = "quux" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: + │ @ BlockNode (location: (60,28)-(60,34)) + │ ├── flags: ∅ + │ ├── locals: [] + │ ├── parameters: ∅ + │ ├── body: ∅ + │ ├── opening_loc: (60,28)-(60,30) = "do" + │ └── closing_loc: (60,31)-(60,34) = "end" + └── @ CallNode (location: (62,0)-(62,25)) ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :foo - ├── message_loc: (54,0)-(54,3) = "foo" + ├── message_loc: (62,0)-(62,3) = "foo" ├── opening_loc: ∅ - ├── arguments: ∅ + ├── arguments: + │ @ ArgumentsNode (location: (62,4)-(62,12)) + │ ├── flags: ∅ + │ └── arguments: (length: 2) + │ ├── @ CallNode (location: (62,4)-(62,7)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :bar + │ │ ├── message_loc: (62,4)-(62,7) = "bar" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ └── @ CallNode (location: (62,9)-(62,12)) + │ ├── flags: variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :baz + │ ├── message_loc: (62,9)-(62,12) = "baz" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ ├── closing_loc: ∅ ├── equal_loc: ∅ └── block: - @ BlockNode (location: (54,4)-(54,17)) + @ BlockNode (location: (62,13)-(62,25)) ├── flags: ∅ - ├── locals: [:bar] + ├── locals: [:x] ├── parameters: - │ @ BlockParametersNode (location: (54,7)-(54,13)) + │ @ BlockParametersNode (location: (62,16)-(62,19)) │ ├── flags: ∅ │ ├── parameters: - │ │ @ ParametersNode (location: (54,8)-(54,12)) + │ │ @ ParametersNode (location: (62,17)-(62,18)) │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) - │ │ │ └── @ RequiredParameterNode (location: (54,8)-(54,11)) + │ │ │ └── @ RequiredParameterNode (location: (62,17)-(62,18)) │ │ │ ├── flags: ∅ - │ │ │ └── name: :bar + │ │ │ └── name: :x │ │ ├── optionals: (length: 0) - │ │ ├── rest: - │ │ │ @ ImplicitRestNode (location: (54,11)-(54,12)) - │ │ │ └── flags: ∅ + │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ │ ├── locals: (length: 0) - │ ├── opening_loc: (54,7)-(54,8) = "|" - │ └── closing_loc: (54,12)-(54,13) = "|" - ├── body: ∅ - ├── opening_loc: (54,4)-(54,6) = "do" - └── closing_loc: (54,14)-(54,17) = "end" + │ ├── opening_loc: (62,16)-(62,17) = "|" + │ └── closing_loc: (62,18)-(62,19) = "|" + ├── body: + │ @ StatementsNode (location: (62,20)-(62,21)) + │ ├── flags: ∅ + │ └── body: (length: 1) + │ └── @ LocalVariableReadNode (location: (62,20)-(62,21)) + │ ├── flags: newline + │ ├── name: :x + │ └── depth: 0 + ├── opening_loc: (62,13)-(62,15) = "do" + └── closing_loc: (62,22)-(62,25) = "end" diff --git a/snapshots/case_in_in.txt b/snapshots/case_in_in.txt new file mode 100644 index 0000000000..0fcedb0e89 --- /dev/null +++ b/snapshots/case_in_in.txt @@ -0,0 +1,81 @@ +@ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ +├── locals: [:event] +└── statements: + @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ + └── body: (length: 1) + └── @ CaseMatchNode (location: (1,0)-(4,3)) + ├── flags: newline + ├── predicate: + │ @ CallNode (location: (1,5)-(1,9)) + │ ├── flags: variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :args + │ ├── message_loc: (1,5)-(1,9) = "args" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── conditions: (length: 1) + │ └── @ InNode (location: (2,0)-(3,25)) + │ ├── flags: ∅ + │ ├── pattern: + │ │ @ ArrayPatternNode (location: (2,3)-(2,10)) + │ │ ├── flags: ∅ + │ │ ├── constant: ∅ + │ │ ├── requireds: (length: 1) + │ │ │ └── @ LocalVariableTargetNode (location: (2,4)-(2,9)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :event + │ │ │ └── depth: 0 + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── opening_loc: (2,3)-(2,4) = "[" + │ │ └── closing_loc: (2,9)-(2,10) = "]" + │ ├── statements: + │ │ @ StatementsNode (location: (3,2)-(3,25)) + │ │ ├── flags: ∅ + │ │ └── body: (length: 1) + │ │ └── @ MatchPredicateNode (location: (3,2)-(3,25)) + │ │ ├── flags: newline + │ │ ├── value: + │ │ │ @ CallNode (location: (3,2)-(3,15)) + │ │ │ ├── flags: ∅ + │ │ │ ├── receiver: + │ │ │ │ @ CallNode (location: (3,2)-(3,9)) + │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── receiver: ∅ + │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ ├── name: :context + │ │ │ │ ├── message_loc: (3,2)-(3,9) = "context" + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── arguments: ∅ + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ ├── equal_loc: ∅ + │ │ │ │ └── block: ∅ + │ │ │ ├── call_operator_loc: (3,9)-(3,10) = "." + │ │ │ ├── name: :event + │ │ │ ├── message_loc: (3,10)-(3,15) = "event" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── pattern: + │ │ │ @ PinnedVariableNode (location: (3,19)-(3,25)) + │ │ │ ├── flags: ∅ + │ │ │ ├── variable: + │ │ │ │ @ LocalVariableReadNode (location: (3,20)-(3,25)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── name: :event + │ │ │ │ └── depth: 0 + │ │ │ └── operator_loc: (3,19)-(3,20) = "^" + │ │ └── operator_loc: (3,16)-(3,18) = "in" + │ ├── in_loc: (2,0)-(2,2) = "in" + │ └── then_loc: ∅ + ├── else_clause: ∅ + ├── case_keyword_loc: (1,0)-(1,4) = "case" + └── end_keyword_loc: (4,0)-(4,3) = "end" diff --git a/snapshots/command_method_call_2.txt b/snapshots/command_method_call_2.txt index ef3e73201c..8b52d4b368 100644 --- a/snapshots/command_method_call_2.txt +++ b/snapshots/command_method_call_2.txt @@ -1,95 +1,49 @@ -@ ProgramNode (location: (1,0)-(3,17)) +@ ProgramNode (location: (1,0)-(1,17)) ├── flags: ∅ ├── locals: [] └── statements: - @ StatementsNode (location: (1,0)-(3,17)) + @ StatementsNode (location: (1,0)-(1,17)) ├── flags: ∅ - └── body: (length: 2) - ├── @ CallNode (location: (1,0)-(1,19)) - │ ├── flags: newline, ignore_visibility - │ ├── receiver: ∅ - │ ├── call_operator_loc: ∅ - │ ├── name: :foo - │ ├── message_loc: (1,0)-(1,3) = "foo" - │ ├── opening_loc: (1,3)-(1,4) = "(" - │ ├── arguments: - │ │ @ ArgumentsNode (location: (1,4)-(1,18)) - │ │ ├── flags: ∅ - │ │ └── arguments: (length: 1) - │ │ └── @ CallNode (location: (1,4)-(1,18)) - │ │ ├── flags: ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :bar - │ │ ├── message_loc: (1,4)-(1,7) = "bar" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: - │ │ │ @ ArgumentsNode (location: (1,8)-(1,11)) - │ │ │ ├── flags: ∅ - │ │ │ └── arguments: (length: 1) - │ │ │ └── @ CallNode (location: (1,8)-(1,11)) - │ │ │ ├── flags: variable_call, ignore_visibility - │ │ │ ├── receiver: ∅ - │ │ │ ├── call_operator_loc: ∅ - │ │ │ ├── name: :baz - │ │ │ ├── message_loc: (1,8)-(1,11) = "baz" - │ │ │ ├── opening_loc: ∅ - │ │ │ ├── arguments: ∅ - │ │ │ ├── closing_loc: ∅ - │ │ │ ├── equal_loc: ∅ - │ │ │ └── block: ∅ - │ │ ├── closing_loc: ∅ - │ │ ├── equal_loc: ∅ - │ │ └── block: - │ │ @ BlockNode (location: (1,12)-(1,18)) - │ │ ├── flags: ∅ - │ │ ├── locals: [] - │ │ ├── parameters: ∅ - │ │ ├── body: ∅ - │ │ ├── opening_loc: (1,12)-(1,14) = "do" - │ │ └── closing_loc: (1,15)-(1,18) = "end" - │ ├── closing_loc: (1,18)-(1,19) = ")" - │ ├── equal_loc: ∅ - │ └── block: ∅ - └── @ CallNode (location: (3,0)-(3,17)) + └── body: (length: 1) + └── @ CallNode (location: (1,0)-(1,17)) ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :foo - ├── message_loc: (3,0)-(3,3) = "foo" - ├── opening_loc: (3,3)-(3,4) = "(" + ├── message_loc: (1,0)-(1,3) = "foo" + ├── opening_loc: (1,3)-(1,4) = "(" ├── arguments: - │ @ ArgumentsNode (location: (3,4)-(3,16)) + │ @ ArgumentsNode (location: (1,4)-(1,16)) │ ├── flags: ∅ │ └── arguments: (length: 1) - │ └── @ CallNode (location: (3,4)-(3,16)) + │ └── @ CallNode (location: (1,4)-(1,16)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :bar - │ ├── message_loc: (3,4)-(3,7) = "bar" + │ ├── message_loc: (1,4)-(1,7) = "bar" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (3,8)-(3,16)) + │ │ @ ArgumentsNode (location: (1,8)-(1,16)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ CallNode (location: (3,8)-(3,11)) + │ │ ├── @ CallNode (location: (1,8)-(1,11)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz - │ │ │ ├── message_loc: (3,8)-(3,11) = "baz" + │ │ │ ├── message_loc: (1,8)-(1,11) = "baz" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ ├── equal_loc: ∅ │ │ │ └── block: ∅ - │ │ └── @ CallNode (location: (3,13)-(3,16)) + │ │ └── @ CallNode (location: (1,13)-(1,16)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bat - │ │ ├── message_loc: (3,13)-(3,16) = "bat" + │ │ ├── message_loc: (1,13)-(1,16) = "bat" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ @@ -98,6 +52,6 @@ │ ├── closing_loc: ∅ │ ├── equal_loc: ∅ │ └── block: ∅ - ├── closing_loc: (3,16)-(3,17) = ")" + ├── closing_loc: (1,16)-(1,17) = ")" ├── equal_loc: ∅ └── block: ∅ diff --git a/snapshots/endless_methods.txt b/snapshots/endless_methods.txt index 938ec25a56..9334abec63 100644 --- a/snapshots/endless_methods.txt +++ b/snapshots/endless_methods.txt @@ -1,10 +1,10 @@ -@ ProgramNode (location: (1,0)-(7,15)) +@ ProgramNode (location: (1,0)-(11,18)) ├── flags: ∅ ├── locals: [:x] └── statements: - @ StatementsNode (location: (1,0)-(7,15)) + @ StatementsNode (location: (1,0)-(11,18)) ├── flags: ∅ - └── body: (length: 4) + └── body: (length: 6) ├── @ DefNode (location: (1,0)-(1,11)) │ ├── flags: newline │ ├── name: :foo @@ -116,44 +116,128 @@ │ ├── rparen_loc: ∅ │ ├── equal_loc: (5,11)-(5,12) = "=" │ └── end_keyword_loc: ∅ - └── @ LocalVariableWriteNode (location: (7,0)-(7,15)) + ├── @ LocalVariableWriteNode (location: (7,0)-(7,15)) + │ ├── flags: newline + │ ├── name: :x + │ ├── depth: 0 + │ ├── name_loc: (7,0)-(7,1) = "x" + │ ├── value: + │ │ @ DefNode (location: (7,4)-(7,15)) + │ │ ├── flags: ∅ + │ │ ├── name: :f + │ │ ├── name_loc: (7,8)-(7,9) = "f" + │ │ ├── receiver: ∅ + │ │ ├── parameters: ∅ + │ │ ├── body: + │ │ │ @ StatementsNode (location: (7,12)-(7,15)) + │ │ │ ├── flags: ∅ + │ │ │ └── body: (length: 1) + │ │ │ └── @ CallNode (location: (7,12)-(7,15)) + │ │ │ ├── flags: ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :p + │ │ │ ├── message_loc: (7,12)-(7,13) = "p" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: + │ │ │ │ @ ArgumentsNode (location: (7,14)-(7,15)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── arguments: (length: 1) + │ │ │ │ └── @ IntegerNode (location: (7,14)-(7,15)) + │ │ │ │ ├── flags: static_literal, decimal + │ │ │ │ └── value: 1 + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── locals: [] + │ │ ├── def_keyword_loc: (7,4)-(7,7) = "def" + │ │ ├── operator_loc: ∅ + │ │ ├── lparen_loc: ∅ + │ │ ├── rparen_loc: ∅ + │ │ ├── equal_loc: (7,10)-(7,11) = "=" + │ │ └── end_keyword_loc: ∅ + │ └── operator_loc: (7,2)-(7,3) = "=" + ├── @ DefNode (location: (9,0)-(9,17)) + │ ├── flags: newline + │ ├── name: :foo + │ ├── name_loc: (9,4)-(9,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: ∅ + │ ├── body: + │ │ @ StatementsNode (location: (9,10)-(9,17)) + │ │ ├── flags: ∅ + │ │ └── body: (length: 1) + │ │ └── @ CallNode (location: (9,10)-(9,17)) + │ │ ├── flags: ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :bar + │ │ ├── message_loc: (9,10)-(9,13) = "bar" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: + │ │ │ @ ArgumentsNode (location: (9,14)-(9,17)) + │ │ │ ├── flags: ∅ + │ │ │ └── arguments: (length: 1) + │ │ │ └── @ CallNode (location: (9,14)-(9,17)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :baz + │ │ │ ├── message_loc: (9,14)-(9,17) = "baz" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ ├── locals: [] + │ ├── def_keyword_loc: (9,0)-(9,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: ∅ + │ ├── rparen_loc: ∅ + │ ├── equal_loc: (9,8)-(9,9) = "=" + │ └── end_keyword_loc: ∅ + └── @ DefNode (location: (11,0)-(11,18)) ├── flags: newline - ├── name: :x - ├── depth: 0 - ├── name_loc: (7,0)-(7,1) = "x" - ├── value: - │ @ DefNode (location: (7,4)-(7,15)) + ├── name: :foo + ├── name_loc: (11,4)-(11,7) = "foo" + ├── receiver: ∅ + ├── parameters: ∅ + ├── body: + │ @ StatementsNode (location: (11,10)-(11,18)) │ ├── flags: ∅ - │ ├── name: :f - │ ├── name_loc: (7,8)-(7,9) = "f" - │ ├── receiver: ∅ - │ ├── parameters: ∅ - │ ├── body: - │ │ @ StatementsNode (location: (7,12)-(7,15)) - │ │ ├── flags: ∅ - │ │ └── body: (length: 1) - │ │ └── @ CallNode (location: (7,12)-(7,15)) - │ │ ├── flags: ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :p - │ │ ├── message_loc: (7,12)-(7,13) = "p" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: - │ │ │ @ ArgumentsNode (location: (7,14)-(7,15)) - │ │ │ ├── flags: ∅ - │ │ │ └── arguments: (length: 1) - │ │ │ └── @ IntegerNode (location: (7,14)-(7,15)) - │ │ │ ├── flags: static_literal, decimal - │ │ │ └── value: 1 - │ │ ├── closing_loc: ∅ - │ │ ├── equal_loc: ∅ - │ │ └── block: ∅ - │ ├── locals: [] - │ ├── def_keyword_loc: (7,4)-(7,7) = "def" - │ ├── operator_loc: ∅ - │ ├── lparen_loc: ∅ - │ ├── rparen_loc: ∅ - │ ├── equal_loc: (7,10)-(7,11) = "=" - │ └── end_keyword_loc: ∅ - └── operator_loc: (7,2)-(7,3) = "=" + │ └── body: (length: 1) + │ └── @ CallNode (location: (11,10)-(11,18)) + │ ├── flags: ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :bar + │ ├── message_loc: (11,10)-(11,13) = "bar" + │ ├── opening_loc: (11,13)-(11,14) = "(" + │ ├── arguments: + │ │ @ ArgumentsNode (location: (11,14)-(11,17)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ CallNode (location: (11,14)-(11,17)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :baz + │ │ ├── message_loc: (11,14)-(11,17) = "baz" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ ├── closing_loc: (11,17)-(11,18) = ")" + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── locals: [] + ├── def_keyword_loc: (11,0)-(11,3) = "def" + ├── operator_loc: ∅ + ├── lparen_loc: ∅ + ├── rparen_loc: ∅ + ├── equal_loc: (11,8)-(11,9) = "=" + └── end_keyword_loc: ∅ diff --git a/snapshots/heredoc_dedent_line_continuation.txt b/snapshots/heredoc_dedent_line_continuation.txt new file mode 100644 index 0000000000..d0c29ef2a2 --- /dev/null +++ b/snapshots/heredoc_dedent_line_continuation.txt @@ -0,0 +1,30 @@ +@ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ + └── body: (length: 1) + └── @ InterpolatedStringNode (location: (1,0)-(1,6)) + ├── flags: newline + ├── opening_loc: (1,0)-(1,6) = "<<~FOO" + ├── parts: (length: 3) + │ ├── @ StringNode (location: (2,0)-(3,0)) + │ │ ├── flags: static_literal, frozen + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (2,0)-(3,0) = " foo\\\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "foo" + │ ├── @ StringNode (location: (3,0)-(4,0)) + │ │ ├── flags: static_literal, frozen + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (3,0)-(4,0) = " \\\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "" + │ └── @ StringNode (location: (4,0)-(5,0)) + │ ├── flags: static_literal, frozen + │ ├── opening_loc: ∅ + │ ├── content_loc: (4,0)-(5,0) = " bar\n" + │ ├── closing_loc: ∅ + │ └── unescaped: "bar\n" + └── closing_loc: (5,0)-(6,0) = "FOO\n" diff --git a/snapshots/seattlerb/regexp_escape_extended.txt b/snapshots/seattlerb/regexp_escape_extended.txt index 732899a20d..a2e4d5eb96 100644 --- a/snapshots/seattlerb/regexp_escape_extended.txt +++ b/snapshots/seattlerb/regexp_escape_extended.txt @@ -6,7 +6,7 @@ ├── flags: ∅ └── body: (length: 1) └── @ RegularExpressionNode (location: (1,0)-(1,6)) - ├── flags: newline, static_literal + ├── flags: newline, static_literal, forced_us_ascii_encoding ├── opening_loc: (1,0)-(1,1) = "/" ├── content_loc: (1,1)-(1,5) = "\\“" ├── closing_loc: (1,5)-(1,6) = "/" diff --git a/snapshots/write_command_operator.txt b/snapshots/write_command_operator.txt new file mode 100644 index 0000000000..f1d92729ed --- /dev/null +++ b/snapshots/write_command_operator.txt @@ -0,0 +1,84 @@ +@ ProgramNode (location: (1,0)-(3,24)) +├── flags: ∅ +├── locals: [:foo] +└── statements: + @ StatementsNode (location: (1,0)-(3,24)) + ├── flags: ∅ + └── body: (length: 2) + ├── @ OrNode (location: (1,0)-(1,27)) + │ ├── flags: newline + │ ├── left: + │ │ @ LocalVariableWriteNode (location: (1,0)-(1,17)) + │ │ ├── flags: ∅ + │ │ ├── name: :foo + │ │ ├── depth: 0 + │ │ ├── name_loc: (1,0)-(1,3) = "foo" + │ │ ├── value: + │ │ │ @ CallNode (location: (1,6)-(1,17)) + │ │ │ ├── flags: ∅ + │ │ │ ├── receiver: + │ │ │ │ @ IntegerNode (location: (1,6)-(1,9)) + │ │ │ │ ├── flags: static_literal, decimal + │ │ │ │ └── value: 123 + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :| + │ │ │ ├── message_loc: (1,10)-(1,11) = "|" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: + │ │ │ │ @ ArgumentsNode (location: (1,12)-(1,17)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── arguments: (length: 1) + │ │ │ │ └── @ StringNode (location: (1,12)-(1,17)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: (1,12)-(1,13) = "'" + │ │ │ │ ├── content_loc: (1,13)-(1,16) = "456" + │ │ │ │ ├── closing_loc: (1,16)-(1,17) = "'" + │ │ │ │ └── unescaped: "456" + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ └── operator_loc: (1,4)-(1,5) = "=" + │ ├── right: + │ │ @ ReturnNode (location: (1,21)-(1,27)) + │ │ ├── flags: ∅ + │ │ ├── keyword_loc: (1,21)-(1,27) = "return" + │ │ └── arguments: ∅ + │ └── operator_loc: (1,18)-(1,20) = "or" + └── @ MatchPredicateNode (location: (3,0)-(3,24)) + ├── flags: newline + ├── value: + │ @ LocalVariableWriteNode (location: (3,0)-(3,17)) + │ ├── flags: ∅ + │ ├── name: :foo + │ ├── depth: 0 + │ ├── name_loc: (3,0)-(3,3) = "foo" + │ ├── value: + │ │ @ CallNode (location: (3,6)-(3,17)) + │ │ ├── flags: ∅ + │ │ ├── receiver: + │ │ │ @ IntegerNode (location: (3,6)-(3,9)) + │ │ │ ├── flags: static_literal, decimal + │ │ │ └── value: 123 + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :| + │ │ ├── message_loc: (3,10)-(3,11) = "|" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: + │ │ │ @ ArgumentsNode (location: (3,12)-(3,17)) + │ │ │ ├── flags: ∅ + │ │ │ └── arguments: (length: 1) + │ │ │ └── @ StringNode (location: (3,12)-(3,17)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: (3,12)-(3,13) = "'" + │ │ │ ├── content_loc: (3,13)-(3,16) = "456" + │ │ │ ├── closing_loc: (3,16)-(3,17) = "'" + │ │ │ └── unescaped: "456" + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ └── operator_loc: (3,4)-(3,5) = "=" + ├── pattern: + │ @ ConstantReadNode (location: (3,21)-(3,24)) + │ ├── flags: ∅ + │ └── name: :BAR + └── operator_loc: (3,18)-(3,20) = "in" diff --git a/src/options.c b/src/options.c index 09d2a65a6c..961d52330f 100644 --- a/src/options.c +++ b/src/options.c @@ -226,10 +226,10 @@ pm_options_free(pm_options_t *options) { pm_string_free(&scope->locals[local_index]); } - xfree(scope->locals); + xfree_sized(scope->locals, scope->locals_count * sizeof(pm_string_t)); } - xfree(options->scopes); + xfree_sized(options->scopes, options->scopes_count * sizeof(pm_options_scope_t)); } /** diff --git a/src/pack.c b/src/pack.c deleted file mode 100644 index 1388ca8a3b..0000000000 --- a/src/pack.c +++ /dev/null @@ -1,509 +0,0 @@ -#include "prism/pack.h" - -// We optionally support parsing String#pack templates. For systems that don't -// want or need this functionality, it can be turned off with the -// PRISM_EXCLUDE_PACK define. -#ifdef PRISM_EXCLUDE_PACK - -void pm_pack_parse(void) {} - -#else - -#include -#include - -static uintmax_t -strtoumaxc(const char **format) { - uintmax_t value = 0; - while (**format >= '0' && **format <= '9') { - if (value > UINTMAX_MAX / 10) { - errno = ERANGE; - } - value = value * 10 + ((uintmax_t) (**format - '0')); - (*format)++; - } - return value; -} - -PRISM_EXPORTED_FUNCTION pm_pack_result -pm_pack_parse( - pm_pack_variant variant, - const char **format, - const char *format_end, - pm_pack_type *type, - pm_pack_signed *signed_type, - pm_pack_endian *endian, - pm_pack_size *size, - pm_pack_length_type *length_type, - uint64_t *length, - pm_pack_encoding *encoding -) { - if (*encoding == PM_PACK_ENCODING_START) { - *encoding = PM_PACK_ENCODING_US_ASCII; - } - - if (*format == format_end) { - *type = PM_PACK_END; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - *length_type = PM_PACK_LENGTH_NA; - return PM_PACK_OK; - } - - *length_type = PM_PACK_LENGTH_FIXED; - *length = 1; - bool length_changed_allowed = true; - - char directive = **format; - (*format)++; - switch (directive) { - case ' ': - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - *type = PM_PACK_SPACE; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - *length_type = PM_PACK_LENGTH_NA; - *length = 0; - return PM_PACK_OK; - case '#': - while ((*format < format_end) && (**format != '\n')) { - (*format)++; - } - *type = PM_PACK_COMMENT; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - *length_type = PM_PACK_LENGTH_NA; - *length = 0; - return PM_PACK_OK; - case 'C': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_AGNOSTIC_ENDIAN; - *size = PM_PACK_SIZE_8; - break; - case 'S': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_16; - break; - case 'L': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_32; - break; - case 'Q': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_64; - break; - case 'J': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_P; - break; - case 'c': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_SIGNED; - *endian = PM_PACK_AGNOSTIC_ENDIAN; - *size = PM_PACK_SIZE_8; - break; - case 's': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_SIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_16; - break; - case 'l': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_SIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_32; - break; - case 'q': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_SIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_64; - break; - case 'j': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_SIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_P; - break; - case 'I': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_INT; - break; - case 'i': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_SIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_INT; - break; - case 'n': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_BIG_ENDIAN; - *size = PM_PACK_SIZE_16; - length_changed_allowed = false; - break; - case 'N': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_BIG_ENDIAN; - *size = PM_PACK_SIZE_32; - length_changed_allowed = false; - break; - case 'v': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_LITTLE_ENDIAN; - *size = PM_PACK_SIZE_16; - length_changed_allowed = false; - break; - case 'V': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_LITTLE_ENDIAN; - *size = PM_PACK_SIZE_32; - length_changed_allowed = false; - break; - case 'U': - *type = PM_PACK_UTF8; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'w': - *type = PM_PACK_BER; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'D': - case 'd': - *type = PM_PACK_FLOAT; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_64; - break; - case 'F': - case 'f': - *type = PM_PACK_FLOAT; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_32; - break; - case 'E': - *type = PM_PACK_FLOAT; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_LITTLE_ENDIAN; - *size = PM_PACK_SIZE_64; - break; - case 'e': - *type = PM_PACK_FLOAT; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_LITTLE_ENDIAN; - *size = PM_PACK_SIZE_32; - break; - case 'G': - *type = PM_PACK_FLOAT; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_BIG_ENDIAN; - *size = PM_PACK_SIZE_64; - break; - case 'g': - *type = PM_PACK_FLOAT; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_BIG_ENDIAN; - *size = PM_PACK_SIZE_32; - break; - case 'A': - *type = PM_PACK_STRING_SPACE_PADDED; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'a': - *type = PM_PACK_STRING_NULL_PADDED; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'Z': - *type = PM_PACK_STRING_NULL_TERMINATED; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'B': - *type = PM_PACK_STRING_MSB; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'b': - *type = PM_PACK_STRING_LSB; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'H': - *type = PM_PACK_STRING_HEX_HIGH; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'h': - *type = PM_PACK_STRING_HEX_LOW; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'u': - *type = PM_PACK_STRING_UU; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'M': - *type = PM_PACK_STRING_MIME; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'm': - *type = PM_PACK_STRING_BASE64; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'P': - *type = PM_PACK_STRING_FIXED; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'p': - *type = PM_PACK_STRING_POINTER; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case '@': - *type = PM_PACK_MOVE; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'X': - *type = PM_PACK_BACK; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'x': - *type = PM_PACK_NULL; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case '%': - return PM_PACK_ERROR_UNSUPPORTED_DIRECTIVE; - default: - return PM_PACK_ERROR_UNKNOWN_DIRECTIVE; - } - - bool explicit_endian = false; - - while (*format < format_end) { - switch (**format) { - case '_': - case '!': - (*format)++; - if (*type != PM_PACK_INTEGER || !length_changed_allowed) { - return PM_PACK_ERROR_BANG_NOT_ALLOWED; - } - switch (*size) { - case PM_PACK_SIZE_SHORT: - case PM_PACK_SIZE_INT: - case PM_PACK_SIZE_LONG: - case PM_PACK_SIZE_LONG_LONG: - break; - case PM_PACK_SIZE_16: - *size = PM_PACK_SIZE_SHORT; - break; - case PM_PACK_SIZE_32: - *size = PM_PACK_SIZE_LONG; - break; - case PM_PACK_SIZE_64: - *size = PM_PACK_SIZE_LONG_LONG; - break; - case PM_PACK_SIZE_P: - break; - default: - return PM_PACK_ERROR_BANG_NOT_ALLOWED; - } - break; - case '<': - (*format)++; - if (explicit_endian) { - return PM_PACK_ERROR_DOUBLE_ENDIAN; - } - *endian = PM_PACK_LITTLE_ENDIAN; - explicit_endian = true; - break; - case '>': - (*format)++; - if (explicit_endian) { - return PM_PACK_ERROR_DOUBLE_ENDIAN; - } - *endian = PM_PACK_BIG_ENDIAN; - explicit_endian = true; - break; - default: - goto exit_modifier_loop; - } - } - -exit_modifier_loop: - - if (variant == PM_PACK_VARIANT_UNPACK && *type == PM_PACK_MOVE) { - *length = 0; - } - - if (*format < format_end) { - if (**format == '*') { - switch (*type) { - case PM_PACK_NULL: - case PM_PACK_BACK: - switch (variant) { - case PM_PACK_VARIANT_PACK: - *length_type = PM_PACK_LENGTH_FIXED; - break; - case PM_PACK_VARIANT_UNPACK: - *length_type = PM_PACK_LENGTH_MAX; - break; - } - *length = 0; - break; - - case PM_PACK_MOVE: - switch (variant) { - case PM_PACK_VARIANT_PACK: - *length_type = PM_PACK_LENGTH_FIXED; - break; - case PM_PACK_VARIANT_UNPACK: - *length_type = PM_PACK_LENGTH_RELATIVE; - break; - } - *length = 0; - break; - - case PM_PACK_STRING_UU: - *length_type = PM_PACK_LENGTH_FIXED; - *length = 0; - break; - - case PM_PACK_STRING_FIXED: - switch (variant) { - case PM_PACK_VARIANT_PACK: - *length_type = PM_PACK_LENGTH_FIXED; - *length = 1; - break; - case PM_PACK_VARIANT_UNPACK: - *length_type = PM_PACK_LENGTH_MAX; - *length = 0; - break; - } - break; - - case PM_PACK_STRING_MIME: - case PM_PACK_STRING_BASE64: - *length_type = PM_PACK_LENGTH_FIXED; - *length = 1; - break; - - default: - *length_type = PM_PACK_LENGTH_MAX; - *length = 0; - break; - } - - (*format)++; - } else if (**format >= '0' && **format <= '9') { - errno = 0; - *length_type = PM_PACK_LENGTH_FIXED; - #if UINTMAX_MAX < UINT64_MAX - #error "prism's design assumes uintmax_t is at least as large as uint64_t" - #endif - uintmax_t length_max = strtoumaxc(format); - if (errno || length_max > UINT64_MAX) { - return PM_PACK_ERROR_LENGTH_TOO_BIG; - } - *length = (uint64_t) length_max; - } - } - - switch (*type) { - case PM_PACK_UTF8: - /* if encoding is US-ASCII, upgrade to UTF-8 */ - if (*encoding == PM_PACK_ENCODING_US_ASCII) { - *encoding = PM_PACK_ENCODING_UTF_8; - } - break; - case PM_PACK_STRING_MIME: - case PM_PACK_STRING_BASE64: - case PM_PACK_STRING_UU: - /* keep US-ASCII (do nothing) */ - break; - default: - /* fall back to BINARY */ - *encoding = PM_PACK_ENCODING_ASCII_8BIT; - break; - } - - return PM_PACK_OK; -} - -PRISM_EXPORTED_FUNCTION size_t -pm_size_to_native(pm_pack_size size) { - switch (size) { - case PM_PACK_SIZE_SHORT: - return sizeof(short); - case PM_PACK_SIZE_INT: - return sizeof(int); - case PM_PACK_SIZE_LONG: - return sizeof(long); - case PM_PACK_SIZE_LONG_LONG: - return sizeof(long long); - case PM_PACK_SIZE_8: - return 1; - case PM_PACK_SIZE_16: - return 2; - case PM_PACK_SIZE_32: - return 4; - case PM_PACK_SIZE_64: - return 8; - case PM_PACK_SIZE_P: - return sizeof(void *); - default: - return 0; - } -} - -#endif diff --git a/src/prism.c b/src/prism.c index 8f3617adce..9d58bdb43d 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1,4 +1,5 @@ #include "prism.h" +#include "prism/node_new.h" /** * The prism version and the serialization format. @@ -286,7 +287,7 @@ lex_mode_pop(pm_parser_t *parser) { } else { parser->lex_modes.index--; pm_lex_mode_t *prev = parser->lex_modes.current->prev; - xfree(parser->lex_modes.current); + xfree_sized(parser->lex_modes.current, sizeof(pm_lex_mode_t)); parser->lex_modes.current = prev; } } @@ -777,7 +778,7 @@ pm_parser_scope_shareable_constant_set(pm_parser_t *parser, pm_shareable_constan static void pm_locals_free(pm_locals_t *locals) { if (locals->capacity > 0) { - xfree(locals->locals); + xfree_sized(locals->locals, locals->capacity * sizeof(pm_local_t)); } } @@ -983,7 +984,7 @@ pm_locals_reads(pm_locals_t *locals, pm_constant_id_t name) { */ static void pm_locals_order(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, pm_locals_t *locals, pm_constant_id_list_t *list, bool toplevel) { - pm_constant_id_list_init_capacity(list, locals->size); + pm_constant_id_list_init_capacity(parser->arena, list, locals->size); // If we're still below the threshold for switching to a hash, then we only // need to loop over the locals until we hit the size because the locals are @@ -1000,7 +1001,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 && ((parser->start_line >= 0) || (pm_newline_list_line(&parser->newline_list, local->location.start, parser->start_line) >= 0))) { + if (warn_unused && local->reads == 0 && ((parser->start_line >= 0) || (pm_line_offset_list_line(&parser->line_offsets, 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 != '_') { @@ -2005,25 +2006,17 @@ static size_t pm_statements_node_body_length(pm_statements_node_t *node); /** - * This function is here to allow us a place to extend in the future when we - * implement our own arena allocation. + * Move an integer's values array into the arena. If the integer has heap- + * allocated values, copy them to the arena and free the original. */ -static inline void * -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); - abort(); +static inline void +pm_integer_arena_move(pm_arena_t *arena, pm_integer_t *integer) { + if (integer->values != NULL) { + size_t byte_size = integer->length * sizeof(uint32_t); + uint32_t *old_values = integer->values; + integer->values = (uint32_t *) pm_arena_memdup(arena, old_values, byte_size, PRISM_ALIGNOF(uint32_t)); + xfree(old_values); } - return memory; -} - -#define PM_NODE_ALLOC(parser_, type_) (type_ *) pm_node_alloc(parser_, sizeof(type_)) -#define PM_NODE_INIT(parser_, type_, flags_, location_) (pm_node_t) { \ - .type = (type_), \ - .flags = (flags_), \ - .node_id = ++(parser_)->node_id, \ - .location = location_ \ } /** @@ -2031,13 +2024,12 @@ pm_node_alloc(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, size_t size) { */ static pm_missing_node_t * pm_missing_node_create(pm_parser_t *parser, uint32_t start, uint32_t length) { - pm_missing_node_t *node = PM_NODE_ALLOC(parser, pm_missing_node_t); - - *node = (pm_missing_node_t) { - .base = PM_NODE_INIT(parser, PM_MISSING_NODE, 0, ((pm_location_t) { .start = start, .length = length })) - }; - - return node; + return pm_missing_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = length }) + ); } /** @@ -2046,16 +2038,16 @@ pm_missing_node_create(pm_parser_t *parser, uint32_t start, uint32_t length) { 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_NODE_ALLOC(parser, pm_alias_global_variable_node_t); - - *node = (pm_alias_global_variable_node_t) { - .base = PM_NODE_INIT(parser, PM_ALIAS_GLOBAL_VARIABLE_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, old_name)), - .new_name = new_name, - .old_name = old_name, - .keyword_loc = TOK2LOC(parser, keyword) - }; - return node; + return pm_alias_global_variable_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, old_name), + new_name, + old_name, + TOK2LOC(parser, keyword) + ); } /** @@ -2064,16 +2056,16 @@ 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_NODE_ALLOC(parser, pm_alias_method_node_t); - - *node = (pm_alias_method_node_t) { - .base = PM_NODE_INIT(parser, PM_ALIAS_METHOD_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, old_name)), - .new_name = new_name, - .old_name = old_name, - .keyword_loc = TOK2LOC(parser, keyword) - }; - return node; + return pm_alias_method_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, old_name), + new_name, + old_name, + TOK2LOC(parser, keyword) + ); } /** @@ -2081,16 +2073,15 @@ 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_NODE_ALLOC(parser, pm_alternation_pattern_node_t); - - *node = (pm_alternation_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_ALTERNATION_PATTERN_NODE, 0, PM_LOCATION_INIT_NODES(left, right)), - .left = left, - .right = right, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_alternation_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(left, right), + left, + right, + TOK2LOC(parser, operator) + ); } /** @@ -2100,16 +2091,15 @@ 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_NODE_ALLOC(parser, pm_and_node_t); - - *node = (pm_and_node_t) { - .base = PM_NODE_INIT(parser, PM_AND_NODE, 0, PM_LOCATION_INIT_NODES(left, right)), - .left = left, - .operator_loc = TOK2LOC(parser, operator), - .right = right - }; - - return node; + return pm_and_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(left, right), + left, + right, + TOK2LOC(parser, operator) + ); } /** @@ -2117,14 +2107,13 @@ 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_NODE_ALLOC(parser, pm_arguments_node_t); - - *node = (pm_arguments_node_t) { - .base = PM_NODE_INIT(parser, PM_ARGUMENTS_NODE, 0, PM_LOCATION_INIT_UNSET), - .arguments = { 0 } - }; - - return node; + return pm_arguments_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }) + ); } /** @@ -2139,7 +2128,7 @@ pm_arguments_node_size(pm_arguments_node_t *node) { * Append an argument to an arguments node. */ static void -pm_arguments_node_arguments_append(pm_arguments_node_t *node, pm_node_t *argument) { +pm_arguments_node_arguments_append(pm_arena_t *arena, pm_arguments_node_t *node, pm_node_t *argument) { if (pm_arguments_node_size(node) == 0) { PM_NODE_START_SET_NODE(node, argument); } @@ -2148,7 +2137,7 @@ pm_arguments_node_arguments_append(pm_arguments_node_t *node, pm_node_t *argumen PM_NODE_LENGTH_SET_NODE(node, argument); } - pm_node_list_append(&node->arguments, argument); + pm_node_list_append(arena, &node->arguments, argument); if (PM_NODE_TYPE_P(argument, PM_SPLAT_NODE)) { if (PM_NODE_FLAG_P(node, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT)) { @@ -2164,37 +2153,39 @@ 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_NODE_ALLOC(parser, pm_array_node_t); - if (opening == NULL) { - *node = (pm_array_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_UNSET), - .opening_loc = { 0 }, - .closing_loc = { 0 }, - .elements = { 0 } - }; + return pm_array_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); } else { - *node = (pm_array_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, opening)), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, opening), - .elements = { 0 } - }; + return pm_array_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, opening), + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, opening), + TOK2LOC(parser, opening) + ); } - - return node; } /** * Append an argument to an array node. */ static inline void -pm_array_node_elements_append(pm_array_node_t *node, pm_node_t *element) { +pm_array_node_elements_append(pm_arena_t *arena, pm_array_node_t *node, pm_node_t *element) { if (!node->elements.size && !node->opening_loc.length) { PM_NODE_START_SET_NODE(node, element); } - pm_node_list_append(&node->elements, element); + pm_node_list_append(arena, &node->elements, element); PM_NODE_LENGTH_SET_NODE(node, element); // If the element is not a static literal, then the array is not a static @@ -2224,17 +2215,18 @@ pm_array_node_close_set(const pm_parser_t *parser, pm_array_node_t *node, const */ 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_NODE_ALLOC(parser, pm_array_pattern_node_t); - - *node = (pm_array_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_PATTERN_NODE, 0, PM_LOCATION_INIT_NODES(nodes->nodes[0], nodes->nodes[nodes->size - 1])), - .constant = NULL, - .rest = NULL, - .requireds = { 0 }, - .posts = { 0 }, - .opening_loc = { 0 }, - .closing_loc = { 0 } - }; + pm_array_pattern_node_t *node = pm_array_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(nodes->nodes[0], nodes->nodes[nodes->size - 1]), + NULL, + ((pm_node_list_t) { 0 }), + NULL, + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); // For now we're going to just copy over each pointer manually. This could be // much more efficient, as we could instead resize the node list. @@ -2246,9 +2238,9 @@ pm_array_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *node node->rest = child; found_rest = true; } else if (found_rest) { - pm_node_list_append(&node->posts, child); + pm_node_list_append(parser->arena, &node->posts, child); } else { - pm_node_list_append(&node->requireds, child); + pm_node_list_append(parser->arena, &node->requireds, child); } } @@ -2260,19 +2252,18 @@ 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_NODE_ALLOC(parser, pm_array_pattern_node_t); - - *node = (pm_array_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_PATTERN_NODE, 0, PM_LOCATION_INIT_NODE(rest)), - .constant = NULL, - .rest = rest, - .requireds = { 0 }, - .posts = { 0 }, - .opening_loc = { 0 }, - .closing_loc = { 0 } - }; - - return node; + return pm_array_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODE(rest), + NULL, + ((pm_node_list_t) { 0 }), + rest, + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); } /** @@ -2281,19 +2272,18 @@ 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_NODE_ALLOC(parser, pm_array_pattern_node_t); - - *node = (pm_array_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_PATTERN_NODE, 0, PM_LOCATION_INIT_NODE_TOKEN(parser, constant, closing)), - .constant = constant, - .rest = NULL, - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing), - .requireds = { 0 }, - .posts = { 0 } - }; - - return node; + return pm_array_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODE_TOKEN(parser, constant, closing), + constant, + ((pm_node_list_t) { 0 }), + NULL, + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -2302,24 +2292,23 @@ 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_NODE_ALLOC(parser, pm_array_pattern_node_t); - - *node = (pm_array_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_PATTERN_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .constant = NULL, - .rest = NULL, - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing), - .requireds = { 0 }, - .posts = { 0 } - }; - - return node; + return pm_array_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + NULL, + ((pm_node_list_t) { 0 }), + NULL, + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } static inline void -pm_array_pattern_node_requireds_append(pm_array_pattern_node_t *node, pm_node_t *inner) { - pm_node_list_append(&node->requireds, inner); +pm_array_pattern_node_requireds_append(pm_arena_t *arena, pm_array_pattern_node_t *node, pm_node_t *inner) { + pm_node_list_append(arena, &node->requireds, inner); } /** @@ -2327,7 +2316,6 @@ 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_NODE_ALLOC(parser, pm_assoc_node_t); uint32_t end; if (value != NULL && PM_NODE_END(value) > PM_NODE_END(key)) { @@ -2355,14 +2343,15 @@ pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *oper flags = key->flags & value->flags & PM_NODE_FLAG_STATIC_LITERAL; } - *node = (pm_assoc_node_t) { - .base = PM_NODE_INIT(parser, PM_ASSOC_NODE, flags, ((pm_location_t) { .start = PM_NODE_START(key), .length = U32(end - PM_NODE_START(key)) })), - .key = key, - .operator_loc = NTOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_assoc_node_new( + parser->arena, + ++parser->node_id, + flags, + ((pm_location_t) { .start = PM_NODE_START(key), .length = U32(end - PM_NODE_START(key)) }), + key, + value, + NTOK2LOC(parser, operator) + ); } /** @@ -2371,15 +2360,15 @@ 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_NODE_ALLOC(parser, pm_assoc_splat_node_t); - - *node = (pm_assoc_splat_node_t) { - .base = PM_NODE_INIT(parser, PM_ASSOC_SPLAT_NODE, 0, (value == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, value)), - .value = value, - .operator_loc = TOK2LOC(parser, operator) - }; - return node; + return pm_assoc_splat_node_new( + parser->arena, + ++parser->node_id, + 0, + (value == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, value), + value, + TOK2LOC(parser, operator) + ); } /** @@ -2388,14 +2377,14 @@ 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_NODE_ALLOC(parser, pm_back_reference_read_node_t); - - *node = (pm_back_reference_read_node_t) { - .base = PM_NODE_INIT(parser, PM_BACK_REFERENCE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = pm_parser_constant_id_token(parser, name) - }; - return node; + return pm_back_reference_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -2403,19 +2392,21 @@ 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_NODE_ALLOC(parser, pm_begin_node_t); - uint32_t start = begin_keyword == NULL ? 0 : PM_TOKEN_START(parser, begin_keyword); uint32_t end = statements == NULL ? (begin_keyword == NULL ? 0 : PM_TOKEN_END(parser, begin_keyword)) : PM_NODE_END(statements); - *node = (pm_begin_node_t) { - .base = PM_NODE_INIT(parser, PM_BEGIN_NODE, 0, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .begin_keyword_loc = NTOK2LOC(parser, begin_keyword), - .statements = statements, - .end_keyword_loc = { 0 } - }; - - return node; + return pm_begin_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NTOK2LOC(parser, begin_keyword), + statements, + NULL, + NULL, + NULL, + ((pm_location_t) { 0 }) + ); } /** @@ -2470,15 +2461,15 @@ pm_begin_node_end_keyword_set(const pm_parser_t *parser, pm_begin_node_t *node, static pm_block_argument_node_t * pm_block_argument_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *expression) { assert(operator->type == PM_TOKEN_UAMPERSAND); - pm_block_argument_node_t *node = PM_NODE_ALLOC(parser, pm_block_argument_node_t); - *node = (pm_block_argument_node_t) { - .base = PM_NODE_INIT(parser, PM_BLOCK_ARGUMENT_NODE, 0, (expression == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, expression)), - .expression = expression, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_block_argument_node_new( + parser->arena, + ++parser->node_id, + 0, + (expression == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, expression), + expression, + TOK2LOC(parser, operator) + ); } /** @@ -2486,18 +2477,17 @@ 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_NODE_ALLOC(parser, pm_block_node_t); - - *node = (pm_block_node_t) { - .base = PM_NODE_INIT(parser, PM_BLOCK_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .locals = *locals, - .parameters = parameters, - .body = body, - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing) - }; - - return node; + return pm_block_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + *locals, + parameters, + body, + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -2506,16 +2496,16 @@ 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_UAMPERSAND || operator->type == PM_TOKEN_AMPERSAND); - pm_block_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_block_parameter_node_t); - *node = (pm_block_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_BLOCK_PARAMETER_NODE, 0, (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name)), - .name = name == NULL ? 0 : pm_parser_constant_id_token(parser, name), - .name_loc = NTOK2LOC(parser, name), - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_block_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name), + name == NULL ? 0 : pm_parser_constant_id_token(parser, name), + NTOK2LOC(parser, name), + TOK2LOC(parser, operator) + ); } /** @@ -2523,8 +2513,6 @@ 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_NODE_ALLOC(parser, pm_block_parameters_node_t); - uint32_t start; if (opening != NULL) { start = PM_TOKEN_START(parser, opening); @@ -2543,15 +2531,16 @@ pm_block_parameters_node_create(pm_parser_t *parser, pm_parameters_node_t *param end = 0; } - *node = (pm_block_parameters_node_t) { - .base = PM_NODE_INIT(parser, PM_BLOCK_PARAMETERS_NODE, 0, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .parameters = parameters, - .opening_loc = NTOK2LOC(parser, opening), - .closing_loc = { 0 }, - .locals = { 0 } - }; - - return node; + return pm_block_parameters_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + parameters, + ((pm_node_list_t) { 0 }), + NTOK2LOC(parser, opening), + ((pm_location_t) { 0 }) + ); } /** @@ -2569,22 +2558,21 @@ pm_block_parameters_node_closing_set(const pm_parser_t *parser, pm_block_paramet */ 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_NODE_ALLOC(parser, pm_block_local_variable_node_t); - - *node = (pm_block_local_variable_node_t) { - .base = PM_NODE_INIT(parser, PM_BLOCK_LOCAL_VARIABLE_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = pm_parser_constant_id_token(parser, name) - }; - - return node; + return pm_block_local_variable_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_parser_constant_id_token(parser, name) + ); } /** * Append a new block-local variable to a BlockParametersNode node. */ static void -pm_block_parameters_node_append_local(pm_block_parameters_node_t *node, const pm_block_local_variable_node_t *local) { - pm_node_list_append(&node->locals, UP(local)); +pm_block_parameters_node_append_local(pm_arena_t *arena, pm_block_parameters_node_t *node, const pm_block_local_variable_node_t *local) { + pm_node_list_append(arena, &node->locals, UP(local)); if (PM_NODE_LENGTH(node) == 0) { PM_NODE_START_SET_NODE(node, local); @@ -2599,15 +2587,15 @@ 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_NODE_ALLOC(parser, pm_break_node_t); - - *node = (pm_break_node_t) { - .base = PM_NODE_INIT(parser, PM_BREAK_NODE, 0, (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments)), - .arguments = arguments, - .keyword_loc = TOK2LOC(parser, keyword) - }; - return node; + return pm_break_node_new( + parser->arena, + ++parser->node_id, + 0, + (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments), + arguments, + TOK2LOC(parser, keyword) + ); } // There are certain flags that we want to use internally but don't want to @@ -2626,22 +2614,21 @@ static const pm_node_flags_t PM_CALL_NODE_FLAGS_INDEX = ((PM_CALL_NODE_FLAGS_LAS */ static pm_call_node_t * pm_call_node_create(pm_parser_t *parser, pm_node_flags_t flags) { - pm_call_node_t *node = PM_NODE_ALLOC(parser, pm_call_node_t); - - *node = (pm_call_node_t) { - .base = PM_NODE_INIT(parser, PM_CALL_NODE, flags, PM_LOCATION_INIT_UNSET), - .receiver = NULL, - .call_operator_loc = { 0 }, - .message_loc = { 0 }, - .opening_loc = { 0 }, - .arguments = NULL, - .closing_loc = { 0 }, - .equal_loc = { 0 }, - .block = NULL, - .name = 0 - }; - - return node; + return pm_call_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_UNSET, + NULL, + ((pm_location_t) { 0 }), + 0, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + NULL, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + NULL + ); } /** @@ -2704,7 +2691,7 @@ pm_call_node_binary_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t node->message_loc = TOK2LOC(parser, operator); pm_arguments_node_t *arguments = pm_arguments_node_create(parser); - pm_arguments_node_arguments_append(arguments, argument); + pm_arguments_node_arguments_append(parser->arena, arguments, argument); node->arguments = arguments; node->name = pm_parser_constant_id_token(parser, operator); @@ -2938,25 +2925,25 @@ 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_NODE_ALLOC(parser, pm_call_and_write_node_t); - - *node = (pm_call_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CALL_AND_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .message_loc = target->message_loc, - .read_name = 0, - .write_name = target->name, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; + + pm_call_and_write_node_t *node = pm_call_and_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->message_loc, + 0, + target->name, + TOK2LOC(parser, operator), + value + ); pm_call_write_read_name_init(parser, &node->read_name, &node->write_name); - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree(target); + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -2990,27 +2977,28 @@ 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_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) { - .base = PM_NODE_INIT(parser, PM_INDEX_AND_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .opening_loc = target->opening_loc, - .arguments = target->arguments, - .closing_loc = target->closing_loc, - .block = (pm_block_argument_node_t *) target->block, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree(target); + pm_index_and_write_node_t *node = pm_index_and_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->opening_loc, + target->arguments, + target->closing_loc, + (pm_block_argument_node_t *) target->block, + TOK2LOC(parser, operator), + value + ); + + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -3021,26 +3009,26 @@ 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_NODE_ALLOC(parser, pm_call_operator_write_node_t); - - *node = (pm_call_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CALL_OPERATOR_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .message_loc = target->message_loc, - .read_name = 0, - .write_name = target->name, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value - }; + + pm_call_operator_write_node_t *node = pm_call_operator_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->message_loc, + 0, + target->name, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), + TOK2LOC(parser, operator), + value + ); pm_call_write_read_name_init(parser, &node->read_name, &node->write_name); - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree(target); + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -3050,28 +3038,28 @@ 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_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) { - .base = PM_NODE_INIT(parser, PM_INDEX_OPERATOR_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .opening_loc = target->opening_loc, - .arguments = target->arguments, - .closing_loc = target->closing_loc, - .block = (pm_block_argument_node_t *) target->block, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value - }; - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree(target); + pm_index_operator_write_node_t *node = pm_index_operator_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->opening_loc, + target->arguments, + target->closing_loc, + (pm_block_argument_node_t *) target->block, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), + TOK2LOC(parser, operator), + value + ); + + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -3083,25 +3071,25 @@ 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_NODE_ALLOC(parser, pm_call_or_write_node_t); - - *node = (pm_call_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CALL_OR_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .message_loc = target->message_loc, - .read_name = 0, - .write_name = target->name, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; + + pm_call_or_write_node_t *node = pm_call_or_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->message_loc, + 0, + target->name, + TOK2LOC(parser, operator), + value + ); pm_call_write_read_name_init(parser, &node->read_name, &node->write_name); - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree(target); + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -3112,27 +3100,28 @@ 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_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) { - .base = PM_NODE_INIT(parser, PM_INDEX_OR_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .opening_loc = target->opening_loc, - .arguments = target->arguments, - .closing_loc = target->closing_loc, - .block = (pm_block_argument_node_t *) target->block, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree(target); + pm_index_or_write_node_t *node = pm_index_or_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->opening_loc, + target->arguments, + target->closing_loc, + (pm_block_argument_node_t *) target->block, + TOK2LOC(parser, operator), + value + ); + + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -3143,15 +3132,16 @@ 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_NODE_ALLOC(parser, pm_call_target_node_t); - - *node = (pm_call_target_node_t) { - .base = PM_NODE_INIT(parser, PM_CALL_TARGET_NODE, FL(target), PM_LOCATION_INIT_NODE(target)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .name = target->name, - .message_loc = target->message_loc - }; + pm_call_target_node_t *node = pm_call_target_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODE(target), + target->receiver, + target->call_operator_loc, + target->name, + target->message_loc + ); /* It is possible to get here where we have parsed an invalid syntax tree * where the call operator was not present. In that case we will have a @@ -3161,10 +3151,8 @@ pm_call_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { node->call_operator_loc = target->base.location; } - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree(target); + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -3175,24 +3163,23 @@ 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_NODE_ALLOC(parser, pm_index_target_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_target_node_t) { - .base = PM_NODE_INIT(parser, PM_INDEX_TARGET_NODE, FL(target) | PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE, PM_LOCATION_INIT_NODE(target)), - .receiver = target->receiver, - .opening_loc = target->opening_loc, - .arguments = target->arguments, - .closing_loc = target->closing_loc, - .block = (pm_block_argument_node_t *) target->block, - }; + pm_index_target_node_t *node = pm_index_target_node_new( + parser->arena, + ++parser->node_id, + FL(target) | PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE, + PM_LOCATION_INIT_NODE(target), + target->receiver, + target->opening_loc, + target->arguments, + target->closing_loc, + (pm_block_argument_node_t *) target->block + ); - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree(target); + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -3202,16 +3189,15 @@ pm_index_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { */ static 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) { - .base = PM_NODE_INIT(parser, PM_CAPTURE_PATTERN_NODE, 0, PM_LOCATION_INIT_NODES(value, target)), - .value = value, - .target = target, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_capture_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(value, target), + value, + target, + TOK2LOC(parser, operator) + ); } /** @@ -3219,28 +3205,27 @@ pm_capture_pattern_node_create(pm_parser_t *parser, pm_node_t *value, pm_local_v */ 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_NODE_ALLOC(parser, pm_case_node_t); - - *node = (pm_case_node_t) { - .base = PM_NODE_INIT(parser, PM_CASE_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, case_keyword, end_keyword == NULL ? case_keyword : end_keyword)), - .predicate = predicate, - .else_clause = NULL, - .case_keyword_loc = TOK2LOC(parser, case_keyword), - .end_keyword_loc = NTOK2LOC(parser, end_keyword), - .conditions = { 0 } - }; - - return node; + return pm_case_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, case_keyword, end_keyword == NULL ? case_keyword : end_keyword), + predicate, + ((pm_node_list_t) { 0 }), + NULL, + TOK2LOC(parser, case_keyword), + NTOK2LOC(parser, end_keyword) + ); } /** * Append a new condition to a CaseNode node. */ static void -pm_case_node_condition_append(pm_case_node_t *node, pm_node_t *condition) { +pm_case_node_condition_append(pm_arena_t *arena, pm_case_node_t *node, pm_node_t *condition) { assert(PM_NODE_TYPE_P(condition, PM_WHEN_NODE)); - pm_node_list_append(&node->conditions, condition); + pm_node_list_append(arena, &node->conditions, condition); PM_NODE_LENGTH_SET_NODE(node, condition); } @@ -3267,28 +3252,27 @@ pm_case_node_end_keyword_loc_set(const pm_parser_t *parser, pm_case_node_t *node */ 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) { - pm_case_match_node_t *node = PM_NODE_ALLOC(parser, pm_case_match_node_t); - - *node = (pm_case_match_node_t) { - .base = PM_NODE_INIT(parser, PM_CASE_MATCH_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, case_keyword)), - .predicate = predicate, - .else_clause = NULL, - .case_keyword_loc = TOK2LOC(parser, case_keyword), - .end_keyword_loc = { 0 }, - .conditions = { 0 } - }; - - return node; + return pm_case_match_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, case_keyword), + predicate, + ((pm_node_list_t) { 0 }), + NULL, + TOK2LOC(parser, case_keyword), + ((pm_location_t) { 0 }) + ); } /** * Append a new condition to a CaseMatchNode node. */ static void -pm_case_match_node_condition_append(pm_case_match_node_t *node, pm_node_t *condition) { +pm_case_match_node_condition_append(pm_arena_t *arena, pm_case_match_node_t *node, pm_node_t *condition) { assert(PM_NODE_TYPE_P(condition, PM_IN_NODE)); - pm_node_list_append(&node->conditions, condition); + pm_node_list_append(arena, &node->conditions, condition); PM_NODE_LENGTH_SET_NODE(node, condition); } @@ -3315,21 +3299,20 @@ pm_case_match_node_end_keyword_loc_set(const pm_parser_t *parser, pm_case_match_ */ 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_NODE_ALLOC(parser, pm_class_node_t); - - *node = (pm_class_node_t) { - .base = PM_NODE_INIT(parser, PM_CLASS_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, class_keyword, end_keyword)), - .locals = *locals, - .class_keyword_loc = TOK2LOC(parser, class_keyword), - .constant_path = constant_path, - .inheritance_operator_loc = NTOK2LOC(parser, inheritance_operator), - .superclass = superclass, - .body = body, - .end_keyword_loc = TOK2LOC(parser, end_keyword), - .name = pm_parser_constant_id_token(parser, name) - }; - - return node; + return pm_class_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, class_keyword, end_keyword), + *locals, + TOK2LOC(parser, class_keyword), + constant_path, + NTOK2LOC(parser, inheritance_operator), + superclass, + body, + TOK2LOC(parser, end_keyword), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -3338,17 +3321,17 @@ 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_NODE_ALLOC(parser, pm_class_variable_and_write_node_t); - - *node = (pm_class_variable_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CLASS_VARIABLE_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_class_variable_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -3356,18 +3339,17 @@ 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_NODE_ALLOC(parser, pm_class_variable_operator_write_node_t); - - *node = (pm_class_variable_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) - }; - - return node; + return pm_class_variable_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) + ); } /** @@ -3376,17 +3358,17 @@ 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_NODE_ALLOC(parser, pm_class_variable_or_write_node_t); - - *node = (pm_class_variable_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CLASS_VARIABLE_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_class_variable_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -3395,14 +3377,14 @@ 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_NODE_ALLOC(parser, pm_class_variable_read_node_t); - - *node = (pm_class_variable_read_node_t) { - .base = PM_NODE_INIT(parser, PM_CLASS_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)), - .name = pm_parser_constant_id_token(parser, token) - }; - return node; + return pm_class_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token), + pm_parser_constant_id_token(parser, token) + ); } /** @@ -3424,18 +3406,16 @@ pm_implicit_array_write_flags(const pm_node_t *node, pm_node_flags_t flags) { */ 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_NODE_ALLOC(parser, pm_class_variable_write_node_t); - pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY); - - *node = (pm_class_variable_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CLASS_VARIABLE_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(read_node, value)), - .name = read_node->name, - .name_loc = read_node->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_class_variable_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(read_node, value), + read_node->name, + read_node->base.location, + value, + TOK2LOC(parser, operator) + ); } /** @@ -3444,16 +3424,16 @@ 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_NODE_ALLOC(parser, pm_constant_path_and_write_node_t); - - *node = (pm_constant_path_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_PATH_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .target = target, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_constant_path_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target, + TOK2LOC(parser, operator), + value + ); } /** @@ -3461,17 +3441,16 @@ 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_NODE_ALLOC(parser, pm_constant_path_operator_write_node_t); - - *node = (pm_constant_path_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_PATH_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .target = target, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) - }; - - return node; + return pm_constant_path_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target, + TOK2LOC(parser, operator), + value, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) + ); } /** @@ -3480,16 +3459,16 @@ 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_NODE_ALLOC(parser, pm_constant_path_or_write_node_t); - - *node = (pm_constant_path_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_PATH_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .target = target, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_constant_path_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target, + TOK2LOC(parser, operator), + value + ); } /** @@ -3498,22 +3477,22 @@ 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_NODE_ALLOC(parser, pm_constant_path_node_t); pm_constant_id_t name = PM_CONSTANT_ID_UNSET; if (name_token->type == PM_TOKEN_CONSTANT) { name = pm_parser_constant_id_token(parser, name_token); } - *node = (pm_constant_path_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_PATH_NODE, 0, (parent == NULL) ? PM_LOCATION_INIT_TOKENS(parser, delimiter, name_token) : PM_LOCATION_INIT_NODE_TOKEN(parser, parent, name_token)), - .parent = parent, - .name = name, - .delimiter_loc = TOK2LOC(parser, delimiter), - .name_loc = TOK2LOC(parser, name_token) - }; - - return node; + return pm_constant_path_node_new( + parser->arena, + ++parser->node_id, + 0, + (parent == NULL) ? PM_LOCATION_INIT_TOKENS(parser, delimiter, name_token) : PM_LOCATION_INIT_NODE_TOKEN(parser, parent, name_token), + parent, + name, + TOK2LOC(parser, delimiter), + TOK2LOC(parser, name_token) + ); } /** @@ -3521,17 +3500,15 @@ 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_NODE_ALLOC(parser, pm_constant_path_write_node_t); - pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY); - - *node = (pm_constant_path_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_PATH_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(target, value)), - .target = target, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_constant_path_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(target, value), + target, + TOK2LOC(parser, operator), + value + ); } /** @@ -3540,17 +3517,17 @@ 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_NODE_ALLOC(parser, pm_constant_and_write_node_t); - - *node = (pm_constant_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_constant_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -3558,18 +3535,17 @@ 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_NODE_ALLOC(parser, pm_constant_operator_write_node_t); - - *node = (pm_constant_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) - }; - - return node; + return pm_constant_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) + ); } /** @@ -3578,17 +3554,17 @@ 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_NODE_ALLOC(parser, pm_constant_or_write_node_t); - - *node = (pm_constant_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_constant_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -3597,14 +3573,14 @@ 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 == 0); - pm_constant_read_node_t *node = PM_NODE_ALLOC(parser, pm_constant_read_node_t); - - *node = (pm_constant_read_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = pm_parser_constant_id_token(parser, name) - }; - return node; + return pm_constant_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -3612,18 +3588,16 @@ 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_NODE_ALLOC(parser, pm_constant_write_node_t); - pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY); - - *node = (pm_constant_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_constant_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + value, + TOK2LOC(parser, operator) + ); } /** @@ -3689,29 +3663,28 @@ pm_def_node_create( const pm_token_t *equal, const pm_token_t *end_keyword ) { - pm_def_node_t *node = PM_NODE_ALLOC(parser, pm_def_node_t); - if (receiver != NULL) { pm_def_node_receiver_check(parser, receiver); } - *node = (pm_def_node_t) { - .base = PM_NODE_INIT(parser, PM_DEF_NODE, 0, (end_keyword == NULL) ? PM_LOCATION_INIT_TOKEN_NODE(parser, def_keyword, body) : PM_LOCATION_INIT_TOKENS(parser, def_keyword, end_keyword)), - .name = name, - .name_loc = TOK2LOC(parser, name_loc), - .receiver = receiver, - .parameters = parameters, - .body = body, - .locals = *locals, - .def_keyword_loc = TOK2LOC(parser, def_keyword), - .operator_loc = NTOK2LOC(parser, operator), - .lparen_loc = NTOK2LOC(parser, lparen), - .rparen_loc = NTOK2LOC(parser, rparen), - .equal_loc = NTOK2LOC(parser, equal), - .end_keyword_loc = NTOK2LOC(parser, end_keyword) - }; - - return node; + return pm_def_node_new( + parser->arena, + ++parser->node_id, + 0, + (end_keyword == NULL) ? PM_LOCATION_INIT_TOKEN_NODE(parser, def_keyword, body) : PM_LOCATION_INIT_TOKENS(parser, def_keyword, end_keyword), + name, + TOK2LOC(parser, name_loc), + receiver, + parameters, + body, + *locals, + TOK2LOC(parser, def_keyword), + NTOK2LOC(parser, operator), + NTOK2LOC(parser, lparen), + NTOK2LOC(parser, rparen), + NTOK2LOC(parser, equal), + NTOK2LOC(parser, end_keyword) + ); } /** @@ -3719,17 +3692,16 @@ 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_token_t *keyword) { - pm_defined_node_t *node = PM_NODE_ALLOC(parser, pm_defined_node_t); - - *node = (pm_defined_node_t) { - .base = PM_NODE_INIT(parser, PM_DEFINED_NODE, 0, (rparen == NULL) ? PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, value) : PM_LOCATION_INIT_TOKENS(parser, keyword, rparen)), - .lparen_loc = NTOK2LOC(parser, lparen), - .value = value, - .rparen_loc = NTOK2LOC(parser, rparen), - .keyword_loc = TOK2LOC(parser, keyword) - }; - - return node; + return pm_defined_node_new( + parser->arena, + ++parser->node_id, + 0, + (rparen == NULL) ? PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, value) : PM_LOCATION_INIT_TOKENS(parser, keyword, rparen), + NTOK2LOC(parser, lparen), + value, + NTOK2LOC(parser, rparen), + TOK2LOC(parser, keyword) + ); } /** @@ -3737,16 +3709,15 @@ 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_NODE_ALLOC(parser, pm_else_node_t); - - *node = (pm_else_node_t) { - .base = PM_NODE_INIT(parser, PM_ELSE_NODE, 0, ((end_keyword == NULL) && (statements != NULL)) ? PM_LOCATION_INIT_TOKEN_NODE(parser, else_keyword, statements) : PM_LOCATION_INIT_TOKENS(parser, else_keyword, end_keyword)), - .else_keyword_loc = TOK2LOC(parser, else_keyword), - .statements = statements, - .end_keyword_loc = NTOK2LOC(parser, end_keyword) - }; - - return node; + return pm_else_node_new( + parser->arena, + ++parser->node_id, + 0, + ((end_keyword == NULL) && (statements != NULL)) ? PM_LOCATION_INIT_TOKEN_NODE(parser, else_keyword, statements) : PM_LOCATION_INIT_TOKENS(parser, else_keyword, end_keyword), + TOK2LOC(parser, else_keyword), + statements, + NTOK2LOC(parser, end_keyword) + ); } /** @@ -3754,16 +3725,15 @@ 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_NODE_ALLOC(parser, pm_embedded_statements_node_t); - - *node = (pm_embedded_statements_node_t) { - .base = PM_NODE_INIT(parser, PM_EMBEDDED_STATEMENTS_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .opening_loc = TOK2LOC(parser, opening), - .statements = statements, - .closing_loc = TOK2LOC(parser, closing) - }; - - return node; + return pm_embedded_statements_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + TOK2LOC(parser, opening), + statements, + TOK2LOC(parser, closing) + ); } /** @@ -3771,15 +3741,14 @@ 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_NODE_ALLOC(parser, pm_embedded_variable_node_t); - - *node = (pm_embedded_variable_node_t) { - .base = PM_NODE_INIT(parser, PM_EMBEDDED_VARIABLE_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, operator, variable)), - .operator_loc = TOK2LOC(parser, operator), - .variable = variable - }; - - return node; + return pm_embedded_variable_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, operator, variable), + TOK2LOC(parser, operator), + variable + ); } /** @@ -3787,16 +3756,15 @@ 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_NODE_ALLOC(parser, pm_ensure_node_t); - - *node = (pm_ensure_node_t) { - .base = PM_NODE_INIT(parser, PM_ENSURE_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, ensure_keyword, end_keyword)), - .ensure_keyword_loc = TOK2LOC(parser, ensure_keyword), - .statements = statements, - .end_keyword_loc = TOK2LOC(parser, end_keyword) - }; - - return node; + return pm_ensure_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, ensure_keyword, end_keyword), + TOK2LOC(parser, ensure_keyword), + statements, + TOK2LOC(parser, end_keyword) + ); } /** @@ -3805,13 +3773,13 @@ 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_NODE_ALLOC(parser, pm_false_node_t); - *node = (pm_false_node_t) { - .base = PM_NODE_INIT(parser, PM_FALSE_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - - return node; + return pm_false_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -3820,8 +3788,6 @@ 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_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; @@ -3842,21 +3808,25 @@ pm_find_pattern_node_create(pm_parser_t *parser, pm_node_list_t *nodes) { #else pm_node_t *right_splat_node = right; #endif - *node = (pm_find_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_FIND_PATTERN_NODE, 0, PM_LOCATION_INIT_NODES(left, right)), - .constant = NULL, - .left = left_splat_node, - .right = right_splat_node, - .requireds = { 0 }, - .opening_loc = { 0 }, - .closing_loc = { 0 } - }; + + pm_find_pattern_node_t *node = pm_find_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(left, right), + NULL, + left_splat_node, + ((pm_node_list_t) { 0 }), + right_splat_node, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); // For now we're going to just copy over each pointer manually. This could be // much more efficient, as we could instead resize the node list to only point // to 1...-1. for (size_t index = 1; index < nodes->size - 1; index++) { - pm_node_list_append(&node->requireds, nodes->nodes[index]); + pm_node_list_append(parser->arena, &node->requireds, nodes->nodes[index]); } return node; @@ -3873,7 +3843,8 @@ pm_double_parse(pm_parser_t *parser, const pm_token_t *token) { // First, get a buffer of the content. size_t length = (size_t) diff; - char *buffer = xmalloc(sizeof(char) * (length + 1)); + const size_t buffer_size = sizeof(char) * (length + 1); + char *buffer = xmalloc(buffer_size); memcpy((void *) buffer, token->start, length); // Next, determine if we need to replace the decimal point because of @@ -3908,7 +3879,7 @@ pm_double_parse(pm_parser_t *parser, const pm_token_t *token) { // is in a valid format. However it's good to be safe. if ((eptr != buffer + length) || (errno != 0 && errno != ERANGE)) { PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, token, PM_ERR_FLOAT_PARSE); - xfree((void *) buffer); + xfree_sized(buffer, buffer_size); return 0.0; } @@ -3931,7 +3902,7 @@ pm_double_parse(pm_parser_t *parser, const pm_token_t *token) { } // Finally we can free the buffer and return the value. - xfree((void *) buffer); + xfree_sized(buffer, buffer_size); return value; } @@ -3941,14 +3912,14 @@ 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_NODE_ALLOC(parser, pm_float_node_t); - *node = (pm_float_node_t) { - .base = PM_NODE_INIT(parser, PM_FLOAT_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .value = pm_double_parse(parser, token) - }; - - return node; + return pm_float_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + pm_double_parse(parser, token) + ); } /** @@ -3958,17 +3929,17 @@ 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_NODE_ALLOC(parser, pm_imaginary_node_t); - *node = (pm_imaginary_node_t) { - .base = PM_NODE_INIT(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numeric = UP(pm_float_node_create(parser, &((pm_token_t) { + return pm_imaginary_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + UP(pm_float_node_create(parser, &((pm_token_t) { .type = PM_TOKEN_FLOAT, .start = token->start, .end = token->end - 1 }))) - }; - - return node; + ); } /** @@ -3978,12 +3949,14 @@ 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_NODE_ALLOC(parser, pm_rational_node_t); - *node = (pm_rational_node_t) { - .base = PM_NODE_INIT(parser, PM_RATIONAL_NODE, PM_INTEGER_BASE_FLAGS_DECIMAL | PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numerator = { 0 }, - .denominator = { 0 } - }; + pm_rational_node_t *node = pm_rational_node_new( + parser->arena, + ++parser->node_id, + PM_INTEGER_BASE_FLAGS_DECIMAL | PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + ((pm_integer_t) { 0 }), + ((pm_integer_t) { 0 }) + ); const uint8_t *start = token->start; const uint8_t *end = token->end - 1; // r @@ -4017,9 +3990,11 @@ pm_float_node_rational_create(pm_parser_t *parser, const pm_token_t *token) { digits[0] = '1'; if (fract_length > 1) memset(digits + 1, '0', fract_length - 1); pm_integer_parse(&node->denominator, PM_INTEGER_BASE_DEFAULT, digits, digits + fract_length); - xfree(digits); + xfree_sized(digits, length); pm_integers_reduce(&node->numerator, &node->denominator); + pm_integer_arena_move(parser->arena, &node->numerator); + pm_integer_arena_move(parser->arena, &node->denominator); return node; } @@ -4031,17 +4006,17 @@ 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_NODE_ALLOC(parser, pm_imaginary_node_t); - *node = (pm_imaginary_node_t) { - .base = PM_NODE_INIT(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numeric = UP(pm_float_node_rational_create(parser, &((pm_token_t) { + return pm_imaginary_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + UP(pm_float_node_rational_create(parser, &((pm_token_t) { .type = PM_TOKEN_FLOAT_RATIONAL, .start = token->start, .end = token->end - 1 }))) - }; - - return node; + ); } /** @@ -4058,20 +4033,19 @@ pm_for_node_create( const pm_token_t *do_keyword, const pm_token_t *end_keyword ) { - pm_for_node_t *node = PM_NODE_ALLOC(parser, pm_for_node_t); - - *node = (pm_for_node_t) { - .base = PM_NODE_INIT(parser, PM_FOR_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, for_keyword, end_keyword)), - .index = index, - .collection = collection, - .statements = statements, - .for_keyword_loc = TOK2LOC(parser, for_keyword), - .in_keyword_loc = TOK2LOC(parser, in_keyword), - .do_keyword_loc = NTOK2LOC(parser, do_keyword), - .end_keyword_loc = TOK2LOC(parser, end_keyword) - }; - - return node; + return pm_for_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, for_keyword, end_keyword), + index, + collection, + statements, + TOK2LOC(parser, for_keyword), + TOK2LOC(parser, in_keyword), + NTOK2LOC(parser, do_keyword), + TOK2LOC(parser, end_keyword) + ); } /** @@ -4080,13 +4054,13 @@ 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_NODE_ALLOC(parser, pm_forwarding_arguments_node_t); - - *node = (pm_forwarding_arguments_node_t) { - .base = PM_NODE_INIT(parser, PM_FORWARDING_ARGUMENTS_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_forwarding_arguments_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -4095,13 +4069,13 @@ 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_NODE_ALLOC(parser, pm_forwarding_parameter_node_t); - - *node = (pm_forwarding_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_FORWARDING_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_forwarding_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -4111,19 +4085,19 @@ 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_NODE_ALLOC(parser, pm_forwarding_super_node_t); pm_block_node_t *block = NULL; if (arguments->block != NULL) { block = (pm_block_node_t *) arguments->block; } - *node = (pm_forwarding_super_node_t) { - .base = PM_NODE_INIT(parser, PM_FORWARDING_SUPER_NODE, 0, (block == NULL) ? PM_LOCATION_INIT_TOKEN(parser, token) : PM_LOCATION_INIT_TOKEN_NODE(parser, token, block)), - .block = block - }; - - return node; + return pm_forwarding_super_node_new( + parser->arena, + ++parser->node_id, + 0, + (block == NULL) ? PM_LOCATION_INIT_TOKEN(parser, token) : PM_LOCATION_INIT_TOKEN_NODE(parser, token, block), + block + ); } /** @@ -4132,18 +4106,17 @@ 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_NODE_ALLOC(parser, pm_hash_pattern_node_t); - - *node = (pm_hash_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_HASH_PATTERN_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .constant = NULL, - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing), - .elements = { 0 }, - .rest = NULL - }; - - return node; + return pm_hash_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + NULL, + ((pm_node_list_t) { 0 }), + NULL, + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -4151,8 +4124,6 @@ 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_NODE_ALLOC(parser, pm_hash_pattern_node_t); - uint32_t start; uint32_t end; @@ -4170,16 +4141,19 @@ pm_hash_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *eleme end = PM_NODE_END(rest); } - *node = (pm_hash_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_HASH_PATTERN_NODE, 0, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .constant = NULL, - .elements = { 0 }, - .rest = rest, - .opening_loc = { 0 }, - .closing_loc = { 0 } - }; + pm_hash_pattern_node_t *node = pm_hash_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NULL, + ((pm_node_list_t) { 0 }), + rest, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); - pm_node_list_concat(&node->elements, elements); + pm_node_list_concat(parser->arena, &node->elements, elements); return node; } @@ -4209,17 +4183,17 @@ 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_NODE_ALLOC(parser, pm_global_variable_and_write_node_t); - - *node = (pm_global_variable_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = pm_global_variable_write_name(parser, target), - .name_loc = target->location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_global_variable_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + pm_global_variable_write_name(parser, target), + target->location, + TOK2LOC(parser, operator), + value + ); } /** @@ -4227,18 +4201,17 @@ 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_NODE_ALLOC(parser, pm_global_variable_operator_write_node_t); - - *node = (pm_global_variable_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = pm_global_variable_write_name(parser, target), - .name_loc = target->location, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) - }; - - return node; + return pm_global_variable_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + pm_global_variable_write_name(parser, target), + target->location, + TOK2LOC(parser, operator), + value, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) + ); } /** @@ -4247,17 +4220,17 @@ 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_NODE_ALLOC(parser, pm_global_variable_or_write_node_t); - - *node = (pm_global_variable_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = pm_global_variable_write_name(parser, target), - .name_loc = target->location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_global_variable_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + pm_global_variable_write_name(parser, target), + target->location, + TOK2LOC(parser, operator), + value + ); } /** @@ -4265,14 +4238,13 @@ 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_NODE_ALLOC(parser, pm_global_variable_read_node_t); - - *node = (pm_global_variable_read_node_t) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = pm_parser_constant_id_token(parser, name) - }; - - return node; + return pm_global_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -4280,14 +4252,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_NODE_ALLOC(parser, pm_global_variable_read_node_t); - - *node = (pm_global_variable_read_node_t) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_UNSET), - .name = name - }; - - return node; + return pm_global_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + name + ); } /** @@ -4295,18 +4266,16 @@ 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_NODE_ALLOC(parser, pm_global_variable_write_node_t); - pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY); - - *node = (pm_global_variable_write_node_t) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(target, value)), - .name = pm_global_variable_write_name(parser, target), - .name_loc = target->location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_global_variable_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(target, value), + pm_global_variable_write_name(parser, target), + target->location, + value, + TOK2LOC(parser, operator) + ); } /** @@ -4314,17 +4283,16 @@ 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_NODE_ALLOC(parser, pm_global_variable_write_node_t); - - *node = (pm_global_variable_write_node_t) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_WRITE_NODE, 0, PM_LOCATION_INIT_UNSET), - .name = name, - .name_loc = { 0 }, - .operator_loc = { 0 }, - .value = value - }; - - return node; + return pm_global_variable_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + name, + ((pm_location_t) { 0 }), + value, + ((pm_location_t) { 0 }) + ); } /** @@ -4333,24 +4301,24 @@ 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_NODE_ALLOC(parser, pm_hash_node_t); - *node = (pm_hash_node_t) { - .base = PM_NODE_INIT(parser, PM_HASH_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, opening)), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = { 0 }, - .elements = { 0 } - }; - - return node; + return pm_hash_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, opening), + TOK2LOC(parser, opening), + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }) + ); } /** * Append a new element to a hash node. */ static inline void -pm_hash_node_elements_append(pm_hash_node_t *hash, pm_node_t *element) { - pm_node_list_append(&hash->elements, element); +pm_hash_node_elements_append(pm_arena_t *arena, pm_hash_node_t *hash, pm_node_t *element) { + pm_node_list_append(arena, &hash->elements, element); bool static_literal = PM_NODE_TYPE_P(element, PM_ASSOC_NODE); if (static_literal) { @@ -4384,7 +4352,6 @@ pm_if_node_create(pm_parser_t *parser, const pm_token_t *end_keyword ) { pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - pm_if_node_t *node = PM_NODE_ALLOC(parser, pm_if_node_t); uint32_t start = PM_TOKEN_START(parser, if_keyword); uint32_t end; @@ -4399,17 +4366,18 @@ pm_if_node_create(pm_parser_t *parser, end = PM_NODE_END(predicate); } - *node = (pm_if_node_t) { - .base = PM_NODE_INIT(parser, PM_IF_NODE, PM_NODE_FLAG_NEWLINE, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .if_keyword_loc = TOK2LOC(parser, if_keyword), - .predicate = predicate, - .then_keyword_loc = NTOK2LOC(parser, then_keyword), - .statements = statements, - .subsequent = subsequent, - .end_keyword_loc = NTOK2LOC(parser, end_keyword) - }; - - return node; + return pm_if_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_NEWLINE, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + TOK2LOC(parser, if_keyword), + predicate, + NTOK2LOC(parser, then_keyword), + statements, + subsequent, + NTOK2LOC(parser, end_keyword) + ); } /** @@ -4418,22 +4386,22 @@ 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_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, true); - *node = (pm_if_node_t) { - .base = PM_NODE_INIT(parser, PM_IF_NODE, PM_NODE_FLAG_NEWLINE, PM_LOCATION_INIT_NODES(statement, predicate)), - .if_keyword_loc = TOK2LOC(parser, if_keyword), - .predicate = predicate, - .then_keyword_loc = { 0 }, - .statements = statements, - .subsequent = NULL, - .end_keyword_loc = { 0 } - }; - - return node; + return pm_if_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_NEWLINE, + PM_LOCATION_INIT_NODES(statement, predicate), + TOK2LOC(parser, if_keyword), + predicate, + ((pm_location_t) { 0 }), + statements, + NULL, + ((pm_location_t) { 0 }) + ); } /** @@ -4451,20 +4419,18 @@ pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, const pm_to pm_statements_node_body_append(parser, else_statements, false_expression, true); pm_else_node_t *else_node = pm_else_node_create(parser, colon, else_statements, NULL); - pm_if_node_t *node = PM_NODE_ALLOC(parser, pm_if_node_t); - - *node = (pm_if_node_t) { - .base = PM_NODE_INIT(parser, PM_IF_NODE, PM_NODE_FLAG_NEWLINE, PM_LOCATION_INIT_NODES(predicate, false_expression)), - .if_keyword_loc = { 0 }, - .predicate = predicate, - .then_keyword_loc = TOK2LOC(parser, qmark), - .statements = if_statements, - .subsequent = UP(else_node), - .end_keyword_loc = { 0 } - }; - - return node; - + return pm_if_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_NEWLINE, + PM_LOCATION_INIT_NODES(predicate, false_expression), + ((pm_location_t) { 0 }), + predicate, + TOK2LOC(parser, qmark), + if_statements, + UP(else_node), + ((pm_location_t) { 0 }) + ); } static inline void @@ -4484,14 +4450,13 @@ pm_else_node_end_keyword_loc_set(const pm_parser_t *parser, pm_else_node_t *node */ static pm_implicit_node_t * pm_implicit_node_create(pm_parser_t *parser, pm_node_t *value) { - pm_implicit_node_t *node = PM_NODE_ALLOC(parser, pm_implicit_node_t); - - *node = (pm_implicit_node_t) { - .base = PM_NODE_INIT(parser, PM_IMPLICIT_NODE, 0, PM_LOCATION_INIT_NODE(value)), - .value = value - }; - - return node; + return pm_implicit_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODE(value), + value + ); } /** @@ -4501,13 +4466,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_NODE_ALLOC(parser, pm_implicit_rest_node_t); - - *node = (pm_implicit_rest_node_t) { - .base = PM_NODE_INIT(parser, PM_IMPLICIT_REST_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - - return node; + return pm_implicit_rest_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -4516,12 +4480,14 @@ 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_NODE_ALLOC(parser, pm_integer_node_t); - *node = (pm_integer_node_t) { - .base = PM_NODE_INIT(parser, PM_INTEGER_NODE, base | PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .value = { 0 } - }; + pm_integer_node_t *node = pm_integer_node_new( + parser->arena, + ++parser->node_id, + base | PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + ((pm_integer_t) { 0 }) + ); pm_integer_base_t integer_base = PM_INTEGER_BASE_DECIMAL; switch (base) { @@ -4533,6 +4499,7 @@ pm_integer_node_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token } pm_integer_parse(&node->value, integer_base, token->start, token->end); + pm_integer_arena_move(parser->arena, &node->value); return node; } @@ -4544,17 +4511,17 @@ 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_NODE_ALLOC(parser, pm_imaginary_node_t); - *node = (pm_imaginary_node_t) { - .base = PM_NODE_INIT(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numeric = UP(pm_integer_node_create(parser, base, &((pm_token_t) { + return pm_imaginary_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + UP(pm_integer_node_create(parser, base, &((pm_token_t) { .type = PM_TOKEN_INTEGER, .start = token->start, .end = token->end - 1 }))) - }; - - return node; + ); } /** @@ -4565,12 +4532,14 @@ 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_NODE_ALLOC(parser, pm_rational_node_t); - *node = (pm_rational_node_t) { - .base = PM_NODE_INIT(parser, PM_RATIONAL_NODE, base | PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numerator = { 0 }, - .denominator = { .value = 1, 0 } - }; + pm_rational_node_t *node = pm_rational_node_new( + parser->arena, + ++parser->node_id, + base | PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + ((pm_integer_t) { 0 }), + ((pm_integer_t) { .value = 1 }) + ); pm_integer_base_t integer_base = PM_INTEGER_BASE_DECIMAL; switch (base) { @@ -4582,6 +4551,7 @@ pm_integer_node_rational_create(pm_parser_t *parser, pm_node_flags_t base, const } pm_integer_parse(&node->numerator, integer_base, token->start, token->end - 1); + pm_integer_arena_move(parser->arena, &node->numerator); return node; } @@ -4594,17 +4564,17 @@ 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_NODE_ALLOC(parser, pm_imaginary_node_t); - *node = (pm_imaginary_node_t) { - .base = PM_NODE_INIT(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numeric = UP(pm_integer_node_rational_create(parser, base, &((pm_token_t) { + return pm_imaginary_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + UP(pm_integer_node_rational_create(parser, base, &((pm_token_t) { .type = PM_TOKEN_INTEGER_RATIONAL, .start = token->start, .end = token->end - 1 }))) - }; - - return node; + ); } /** @@ -4612,8 +4582,6 @@ 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_NODE_ALLOC(parser, pm_in_node_t); - uint32_t start = PM_TOKEN_START(parser, in_keyword); uint32_t end; @@ -4625,15 +4593,16 @@ pm_in_node_create(pm_parser_t *parser, pm_node_t *pattern, pm_statements_node_t end = PM_NODE_END(pattern); } - *node = (pm_in_node_t) { - .base = PM_NODE_INIT(parser, PM_IN_NODE, 0, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .pattern = pattern, - .statements = statements, - .in_loc = TOK2LOC(parser, in_keyword), - .then_loc = NTOK2LOC(parser, then_keyword) - }; - - return node; + return pm_in_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + pattern, + statements, + TOK2LOC(parser, in_keyword), + NTOK2LOC(parser, then_keyword) + ); } /** @@ -4642,17 +4611,17 @@ 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_NODE_ALLOC(parser, pm_instance_variable_and_write_node_t); - - *node = (pm_instance_variable_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_INSTANCE_VARIABLE_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_instance_variable_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -4660,18 +4629,17 @@ 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_NODE_ALLOC(parser, pm_instance_variable_operator_write_node_t); - - *node = (pm_instance_variable_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) - }; - - return node; + return pm_instance_variable_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) + ); } /** @@ -4680,17 +4648,17 @@ 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_NODE_ALLOC(parser, pm_instance_variable_or_write_node_t); - - *node = (pm_instance_variable_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_INSTANCE_VARIABLE_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_instance_variable_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -4699,14 +4667,14 @@ 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_NODE_ALLOC(parser, pm_instance_variable_read_node_t); - *node = (pm_instance_variable_read_node_t) { - .base = PM_NODE_INIT(parser, PM_INSTANCE_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)), - .name = pm_parser_constant_id_token(parser, token) - }; - - return node; + return pm_instance_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token), + pm_parser_constant_id_token(parser, token) + ); } /** @@ -4715,18 +4683,16 @@ 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_NODE_ALLOC(parser, pm_instance_variable_write_node_t); - pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY); - - *node = (pm_instance_variable_write_node_t) { - .base = PM_NODE_INIT(parser, PM_INSTANCE_VARIABLE_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(read_node, value)), - .name = read_node->name, - .name_loc = read_node->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_instance_variable_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(read_node, value), + read_node->name, + read_node->base.location, + value, + TOK2LOC(parser, operator) + ); } /** @@ -4735,7 +4701,7 @@ pm_instance_variable_write_node_create(pm_parser_t *parser, pm_instance_variable * literals. */ static void -pm_interpolated_node_append(pm_node_t *node, pm_node_list_t *parts, pm_node_t *part) { +pm_interpolated_node_append(pm_arena_t *arena, pm_node_t *node, pm_node_list_t *parts, pm_node_t *part) { switch (PM_NODE_TYPE(part)) { case PM_STRING_NODE: pm_node_flag_set(part, PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN); @@ -4770,7 +4736,7 @@ pm_interpolated_node_append(pm_node_t *node, pm_node_list_t *parts, pm_node_t *p break; } - pm_node_list_append(parts, part); + pm_node_list_append(arena, parts, part); } /** @@ -4778,20 +4744,19 @@ 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_NODE_ALLOC(parser, pm_interpolated_regular_expression_node_t); - - *node = (pm_interpolated_regular_expression_node_t) { - .base = PM_NODE_INIT(parser, PM_INTERPOLATED_REGULAR_EXPRESSION_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, opening)), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, opening), - .parts = { 0 } - }; - - return node; + return pm_interpolated_regular_expression_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, opening), + TOK2LOC(parser, opening), + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, opening) + ); } static inline void -pm_interpolated_regular_expression_node_append(pm_interpolated_regular_expression_node_t *node, pm_node_t *part) { +pm_interpolated_regular_expression_node_append(pm_arena_t *arena, pm_interpolated_regular_expression_node_t *node, pm_node_t *part) { if (PM_NODE_START(node) > PM_NODE_START(part)) { PM_NODE_START_SET_NODE(node, part); } @@ -4799,7 +4764,7 @@ pm_interpolated_regular_expression_node_append(pm_interpolated_regular_expressio PM_NODE_LENGTH_SET_NODE(node, part); } - pm_interpolated_node_append(UP(node), &node->parts, part); + pm_interpolated_node_append(arena, UP(node), &node->parts, part); } static inline void @@ -4833,7 +4798,7 @@ pm_interpolated_regular_expression_node_closing_set(pm_parser_t *parser, pm_inte * which could potentially use a chilled string otherwise. */ static inline void -pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_t *part) { +pm_interpolated_string_node_append(pm_arena_t *arena, pm_interpolated_string_node_t *node, pm_node_t *part) { #define CLEAR_FLAGS(node) \ node->base.flags = (pm_node_flags_t) (FL(node) & ~(PM_NODE_FLAG_STATIC_LITERAL | PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN | PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE)) @@ -4918,7 +4883,7 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_ break; } - pm_node_list_append(&node->parts, part); + pm_node_list_append(arena, &node->parts, part); #undef CLEAR_FLAGS #undef MUTABLE_FLAGS @@ -4929,7 +4894,6 @@ 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_NODE_ALLOC(parser, pm_interpolated_string_node_t); pm_node_flags_t flags = PM_NODE_FLAG_STATIC_LITERAL; switch (parser->frozen_string_literal) { @@ -4944,17 +4908,20 @@ pm_interpolated_string_node_create(pm_parser_t *parser, const pm_token_t *openin uint32_t start = opening == NULL ? 0 : PM_TOKEN_START(parser, opening); uint32_t end = closing == NULL ? 0 : PM_TOKEN_END(parser, closing); - *node = (pm_interpolated_string_node_t) { - .base = PM_NODE_INIT(parser, PM_INTERPOLATED_STRING_NODE, flags, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .opening_loc = NTOK2LOC(parser, opening), - .closing_loc = NTOK2LOC(parser, closing), - .parts = { 0 } - }; + pm_interpolated_string_node_t *node = pm_interpolated_string_node_new( + parser->arena, + ++parser->node_id, + flags, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NTOK2LOC(parser, opening), + ((pm_node_list_t) { 0 }), + NTOK2LOC(parser, closing) + ); if (parts != NULL) { pm_node_t *part; PM_NODE_LIST_FOREACH(parts, index, part) { - pm_interpolated_string_node_append(node, part); + pm_interpolated_string_node_append(parser->arena, node, part); } } @@ -4971,12 +4938,12 @@ pm_interpolated_string_node_closing_set(const pm_parser_t *parser, pm_interpolat } static void -pm_interpolated_symbol_node_append(pm_interpolated_symbol_node_t *node, pm_node_t *part) { +pm_interpolated_symbol_node_append(pm_arena_t *arena, pm_interpolated_symbol_node_t *node, pm_node_t *part) { if (node->parts.size == 0 && node->opening_loc.length == 0) { PM_NODE_START_SET_NODE(node, part); } - pm_interpolated_node_append(UP(node), &node->parts, part); + pm_interpolated_node_append(arena, UP(node), &node->parts, part); if (PM_NODE_END(part) > PM_NODE_END(node)) { PM_NODE_LENGTH_SET_NODE(node, part); @@ -4994,22 +4961,23 @@ pm_interpolated_symbol_node_closing_loc_set(const pm_parser_t *parser, pm_interp */ 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_NODE_ALLOC(parser, pm_interpolated_symbol_node_t); - uint32_t start = opening == NULL ? 0 : PM_TOKEN_START(parser, opening); uint32_t end = closing == NULL ? 0 : PM_TOKEN_END(parser, closing); - *node = (pm_interpolated_symbol_node_t) { - .base = PM_NODE_INIT(parser, PM_INTERPOLATED_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .opening_loc = NTOK2LOC(parser, opening), - .closing_loc = NTOK2LOC(parser, closing), - .parts = { 0 } - }; + pm_interpolated_symbol_node_t *node = pm_interpolated_symbol_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NTOK2LOC(parser, opening), + ((pm_node_list_t) { 0 }), + NTOK2LOC(parser, closing) + ); if (parts != NULL) { pm_node_t *part; PM_NODE_LIST_FOREACH(parts, index, part) { - pm_interpolated_symbol_node_append(node, part); + pm_interpolated_symbol_node_append(parser->arena, node, part); } } @@ -5021,21 +4989,20 @@ 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_NODE_ALLOC(parser, pm_interpolated_x_string_node_t); - - *node = (pm_interpolated_x_string_node_t) { - .base = PM_NODE_INIT(parser, PM_INTERPOLATED_X_STRING_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing), - .parts = { 0 } - }; - - return node; + return pm_interpolated_x_string_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + TOK2LOC(parser, opening), + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, closing) + ); } static inline void -pm_interpolated_xstring_node_append(pm_interpolated_x_string_node_t *node, pm_node_t *part) { - pm_interpolated_node_append(UP(node), &node->parts, part); +pm_interpolated_xstring_node_append(pm_arena_t *arena, pm_interpolated_x_string_node_t *node, pm_node_t *part) { + pm_interpolated_node_append(arena, UP(node), &node->parts, part); PM_NODE_LENGTH_SET_NODE(node, part); } @@ -5050,13 +5017,12 @@ pm_interpolated_xstring_node_closing_set(const pm_parser_t *parser, pm_interpola */ 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) { - .base = PM_NODE_INIT(parser, PM_IT_LOCAL_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - }; - - return node; + return pm_it_local_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name) + ); } /** @@ -5064,13 +5030,12 @@ pm_it_local_variable_read_node_create(pm_parser_t *parser, const pm_token_t *nam */ 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_NODE_ALLOC(parser, pm_it_parameters_node_t); - - *node = (pm_it_parameters_node_t) { - .base = PM_NODE_INIT(parser, PM_IT_PARAMETERS_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - }; - - return node; + return pm_it_parameters_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing) + ); } /** @@ -5078,28 +5043,27 @@ 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_NODE_ALLOC(parser, pm_keyword_hash_node_t); - - *node = (pm_keyword_hash_node_t) { - .base = PM_NODE_INIT(parser, PM_KEYWORD_HASH_NODE, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS, PM_LOCATION_INIT_UNSET), - .elements = { 0 } - }; - - return node; + return pm_keyword_hash_node_new( + parser->arena, + ++parser->node_id, + PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }) + ); } /** * Append an element to a KeywordHashNode node. */ static void -pm_keyword_hash_node_elements_append(pm_keyword_hash_node_t *hash, pm_node_t *element) { +pm_keyword_hash_node_elements_append(pm_arena_t *arena, pm_keyword_hash_node_t *hash, pm_node_t *element) { // If the element being added is not an AssocNode or does not have a symbol // key, then we want to turn the SYMBOL_KEYS flag off. if (!PM_NODE_TYPE_P(element, PM_ASSOC_NODE) || !PM_NODE_TYPE_P(((pm_assoc_node_t *) element)->key, PM_SYMBOL_NODE)) { pm_node_flag_unset(UP(hash), PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS); } - pm_node_list_append(&hash->elements, element); + pm_node_list_append(arena, &hash->elements, element); if (PM_NODE_LENGTH(hash) == 0) { PM_NODE_START_SET_NODE(hash, element); } @@ -5111,15 +5075,14 @@ 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_NODE_ALLOC(parser, pm_required_keyword_parameter_node_t); - - *node = (pm_required_keyword_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_REQUIRED_KEYWORD_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = pm_parser_constant_id_raw(parser, name->start, name->end - 1), - .name_loc = TOK2LOC(parser, name), - }; - - return node; + return pm_required_keyword_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_parser_constant_id_raw(parser, name->start, name->end - 1), + TOK2LOC(parser, name) + ); } /** @@ -5127,16 +5090,15 @@ 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_NODE_ALLOC(parser, pm_optional_keyword_parameter_node_t); - - *node = (pm_optional_keyword_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_OPTIONAL_KEYWORD_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, name, value)), - .name = pm_parser_constant_id_raw(parser, name->start, name->end - 1), - .name_loc = TOK2LOC(parser, name), - .value = value - }; - - return node; + return pm_optional_keyword_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, name, value), + pm_parser_constant_id_raw(parser, name->start, name->end - 1), + TOK2LOC(parser, name), + value + ); } /** @@ -5144,16 +5106,15 @@ 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_NODE_ALLOC(parser, pm_keyword_rest_parameter_node_t); - - *node = (pm_keyword_rest_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_KEYWORD_REST_PARAMETER_NODE, 0, (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name)), - .name = name == NULL ? 0 : pm_parser_constant_id_token(parser, name), - .name_loc = NTOK2LOC(parser, name), - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_keyword_rest_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name), + name == NULL ? 0 : pm_parser_constant_id_token(parser, name), + NTOK2LOC(parser, name), + TOK2LOC(parser, operator) + ); } /** @@ -5169,19 +5130,18 @@ pm_lambda_node_create( pm_node_t *parameters, pm_node_t *body ) { - pm_lambda_node_t *node = PM_NODE_ALLOC(parser, pm_lambda_node_t); - - *node = (pm_lambda_node_t) { - .base = PM_NODE_INIT(parser, PM_LAMBDA_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, operator, closing)), - .locals = *locals, - .operator_loc = TOK2LOC(parser, operator), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing), - .parameters = parameters, - .body = body - }; - - return node; + return pm_lambda_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, operator, closing), + *locals, + TOK2LOC(parser, operator), + TOK2LOC(parser, opening), + TOK2LOC(parser, closing), + parameters, + body + ); } /** @@ -5191,18 +5151,18 @@ 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_IT_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_NODE_ALLOC(parser, pm_local_variable_and_write_node_t); - - *node = (pm_local_variable_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name_loc = target->location, - .operator_loc = TOK2LOC(parser, operator), - .value = value, - .name = name, - .depth = depth - }; - return node; + return pm_local_variable_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->location, + TOK2LOC(parser, operator), + value, + name, + depth + ); } /** @@ -5210,19 +5170,18 @@ 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_NODE_ALLOC(parser, pm_local_variable_operator_write_node_t); - - *node = (pm_local_variable_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name_loc = target->location, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .name = name, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), - .depth = depth - }; - - return node; + return pm_local_variable_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->location, + TOK2LOC(parser, operator), + value, + name, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), + depth + ); } /** @@ -5232,18 +5191,18 @@ 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_IT_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_NODE_ALLOC(parser, pm_local_variable_or_write_node_t); - - *node = (pm_local_variable_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name_loc = target->location, - .operator_loc = TOK2LOC(parser, operator), - .value = value, - .name = name, - .depth = depth - }; - return node; + return pm_local_variable_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->location, + TOK2LOC(parser, operator), + value, + name, + depth + ); } /** @@ -5253,15 +5212,14 @@ 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_NODE_ALLOC(parser, pm_local_variable_read_node_t); - - *node = (pm_local_variable_read_node_t) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = name_id, - .depth = depth - }; - - return node; + return pm_local_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + name_id, + depth + ); } /** @@ -5288,19 +5246,17 @@ 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_NODE_ALLOC(parser, pm_local_variable_write_node_t); - pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY); - - *node = (pm_local_variable_write_node_t) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_WRITE_NODE, flags, ((pm_location_t) { .start = name_loc->start, .length = PM_NODE_END(value) - name_loc->start })), - .name = name, - .depth = depth, - .value = value, - .name_loc = *name_loc, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_local_variable_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + ((pm_location_t) { .start = name_loc->start, .length = PM_NODE_END(value) - name_loc->start }), + name, + depth, + *name_loc, + value, + TOK2LOC(parser, operator) + ); } /** @@ -5343,15 +5299,15 @@ pm_refute_numbered_parameter(pm_parser_t *parser, uint32_t start, uint32_t lengt 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->length); - pm_local_variable_target_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_target_node_t); - *node = (pm_local_variable_target_node_t) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_TARGET_NODE, 0, ((pm_location_t) { .start = location->start, .length = location->length })), - .name = name, - .depth = depth - }; - - return node; + return pm_local_variable_target_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = location->start, .length = location->length }), + name, + depth + ); } /** @@ -5361,16 +5317,15 @@ 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_NODE_ALLOC(parser, pm_match_predicate_node_t); - - *node = (pm_match_predicate_node_t) { - .base = PM_NODE_INIT(parser, PM_MATCH_PREDICATE_NODE, 0, PM_LOCATION_INIT_NODES(value, pattern)), - .value = value, - .pattern = pattern, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_match_predicate_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(value, pattern), + value, + pattern, + TOK2LOC(parser, operator) + ); } /** @@ -5380,16 +5335,15 @@ 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_NODE_ALLOC(parser, pm_match_required_node_t); - - *node = (pm_match_required_node_t) { - .base = PM_NODE_INIT(parser, PM_MATCH_REQUIRED_NODE, 0, PM_LOCATION_INIT_NODES(value, pattern)), - .value = value, - .pattern = pattern, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_match_required_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(value, pattern), + value, + pattern, + TOK2LOC(parser, operator) + ); } /** @@ -5397,15 +5351,14 @@ 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_NODE_ALLOC(parser, pm_match_write_node_t); - - *node = (pm_match_write_node_t) { - .base = PM_NODE_INIT(parser, PM_MATCH_WRITE_NODE, 0, PM_LOCATION_INIT_NODE(call)), - .call = call, - .targets = { 0 } - }; - - return node; + return pm_match_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODE(call), + call, + ((pm_node_list_t) { 0 }) + ); } /** @@ -5413,19 +5366,18 @@ 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_NODE_ALLOC(parser, pm_module_node_t); - - *node = (pm_module_node_t) { - .base = PM_NODE_INIT(parser, PM_MODULE_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, module_keyword, end_keyword)), - .locals = (locals == NULL ? ((pm_constant_id_list_t) { .ids = NULL, .size = 0, .capacity = 0 }) : *locals), - .module_keyword_loc = TOK2LOC(parser, module_keyword), - .constant_path = constant_path, - .body = body, - .end_keyword_loc = TOK2LOC(parser, end_keyword), - .name = pm_parser_constant_id_token(parser, name) - }; - - return node; + return pm_module_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, module_keyword, end_keyword), + (locals == NULL ? ((pm_constant_id_list_t) { .ids = NULL, .size = 0, .capacity = 0 }) : *locals), + TOK2LOC(parser, module_keyword), + constant_path, + body, + TOK2LOC(parser, end_keyword), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -5433,18 +5385,17 @@ 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_NODE_ALLOC(parser, pm_multi_target_node_t); - - *node = (pm_multi_target_node_t) { - .base = PM_NODE_INIT(parser, PM_MULTI_TARGET_NODE, 0, PM_LOCATION_INIT_UNSET), - .lefts = { 0 }, - .rest = NULL, - .rights = { 0 }, - .lparen_loc = { 0 }, - .rparen_loc = { 0 } - }; - - return node; + return pm_multi_target_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }), + NULL, + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); } /** @@ -5457,19 +5408,19 @@ pm_multi_target_node_targets_append(pm_parser_t *parser, pm_multi_target_node_t node->rest = target; } else { pm_parser_err_node(parser, target, PM_ERR_MULTI_ASSIGN_MULTI_SPLATS); - pm_node_list_append(&node->rights, target); + pm_node_list_append(parser->arena, &node->rights, target); } } else if (PM_NODE_TYPE_P(target, PM_IMPLICIT_REST_NODE)) { if (node->rest == NULL) { node->rest = target; } else { PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, &parser->current, PM_ERR_MULTI_ASSIGN_UNEXPECTED_REST); - pm_node_list_append(&node->rights, target); + pm_node_list_append(parser->arena, &node->rights, target); } } else if (node->rest == NULL) { - pm_node_list_append(&node->lefts, target); + pm_node_list_append(parser->arena, &node->lefts, target); } else { - pm_node_list_append(&node->rights, target); + pm_node_list_append(parser->arena, &node->rights, target); } if (PM_NODE_LENGTH(node) == 0 || (PM_NODE_START(node) > PM_NODE_START(target))) { @@ -5505,25 +5456,21 @@ pm_multi_target_node_closing_set(const pm_parser_t *parser, pm_multi_target_node */ 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_NODE_ALLOC(parser, pm_multi_write_node_t); - pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY); - - *node = (pm_multi_write_node_t) { - .base = PM_NODE_INIT(parser, PM_MULTI_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(target, value)), - .lefts = target->lefts, - .rest = target->rest, - .rights = target->rights, - .lparen_loc = target->lparen_loc, - .rparen_loc = target->rparen_loc, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - // Explicitly do not call pm_node_destroy here because we want to keep - // around all of the information within the MultiWriteNode node. - xfree(target); - - return node; + /* The target is no longer necessary because we have reused its children. It + * is arena-allocated so no explicit free is needed. */ + return pm_multi_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(target, value), + target->lefts, + target->rest, + target->rights, + target->lparen_loc, + target->rparen_loc, + TOK2LOC(parser, operator), + value + ); } /** @@ -5532,15 +5479,15 @@ 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_NODE_ALLOC(parser, pm_next_node_t); - - *node = (pm_next_node_t) { - .base = PM_NODE_INIT(parser, PM_NEXT_NODE, 0, (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments)), - .keyword_loc = TOK2LOC(parser, keyword), - .arguments = arguments - }; - return node; + return pm_next_node_new( + parser->arena, + ++parser->node_id, + 0, + (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments), + arguments, + TOK2LOC(parser, keyword) + ); } /** @@ -5549,13 +5496,31 @@ 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_NODE_ALLOC(parser, pm_nil_node_t); - *node = (pm_nil_node_t) { - .base = PM_NODE_INIT(parser, PM_NIL_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)) - }; + return pm_nil_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token) + ); +} - return node; +/** + * Allocate and initialize a new NoKeywordsParameterNode node. + */ +static pm_no_block_parameter_node_t * +pm_no_block_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *keyword) { + assert(operator->type == PM_TOKEN_AMPERSAND || operator->type == PM_TOKEN_UAMPERSAND); + assert(keyword->type == PM_TOKEN_KEYWORD_NIL); + + return pm_no_block_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, operator, keyword), + TOK2LOC(parser, operator), + TOK2LOC(parser, keyword) + ); } /** @@ -5565,15 +5530,15 @@ 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_NODE_ALLOC(parser, pm_no_keywords_parameter_node_t); - *node = (pm_no_keywords_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_NO_KEYWORDS_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, operator, keyword)), - .operator_loc = TOK2LOC(parser, operator), - .keyword_loc = TOK2LOC(parser, keyword) - }; - - return node; + return pm_no_keywords_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, operator, keyword), + TOK2LOC(parser, operator), + TOK2LOC(parser, keyword) + ); } /** @@ -5581,14 +5546,13 @@ 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_token_t *opening, const pm_token_t *closing, uint8_t maximum) { - pm_numbered_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_numbered_parameters_node_t); - - *node = (pm_numbered_parameters_node_t) { - .base = PM_NODE_INIT(parser, PM_NUMBERED_PARAMETERS_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .maximum = maximum - }; - - return node; + return pm_numbered_parameters_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + maximum + ); } /** @@ -5628,7 +5592,7 @@ pm_numbered_reference_read_node_number(pm_parser_t *parser, const pm_token_t *to value = 0; } - xfree(digits); + xfree_sized(digits, sizeof(char) * (length + 1)); if ((errno == ERANGE) || (value > NTH_REF_MAX)) { PM_PARSER_WARN_FORMAT(parser, U32(start - parser->start), U32(length), PM_WARN_INVALID_NUMBERED_REFERENCE, (int) (length + 1), (const char *) token->start); @@ -5646,14 +5610,14 @@ 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_NODE_ALLOC(parser, pm_numbered_reference_read_node_t); - *node = (pm_numbered_reference_read_node_t) { - .base = PM_NODE_INIT(parser, PM_NUMBERED_REFERENCE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .number = pm_numbered_reference_read_node_number(parser, name) - }; - - return node; + return pm_numbered_reference_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_numbered_reference_read_node_number(parser, name) + ); } /** @@ -5661,17 +5625,16 @@ 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_NODE_ALLOC(parser, pm_optional_parameter_node_t); - - *node = (pm_optional_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_OPTIONAL_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, name, value)), - .name = pm_parser_constant_id_token(parser, name), - .name_loc = TOK2LOC(parser, name), - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_optional_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, name, value), + pm_parser_constant_id_token(parser, name), + TOK2LOC(parser, name), + TOK2LOC(parser, operator), + value + ); } /** @@ -5681,16 +5644,15 @@ 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_NODE_ALLOC(parser, pm_or_node_t); - - *node = (pm_or_node_t) { - .base = PM_NODE_INIT(parser, PM_OR_NODE, 0, PM_LOCATION_INIT_NODES(left, right)), - .left = left, - .right = right, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_or_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(left, right), + left, + right, + TOK2LOC(parser, operator) + ); } /** @@ -5698,20 +5660,19 @@ 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_NODE_ALLOC(parser, pm_parameters_node_t); - - *node = (pm_parameters_node_t) { - .base = PM_NODE_INIT(parser, PM_PARAMETERS_NODE, 0, PM_LOCATION_INIT_UNSET), - .rest = NULL, - .keyword_rest = NULL, - .block = NULL, - .requireds = { 0 }, - .optionals = { 0 }, - .posts = { 0 }, - .keywords = { 0 } - }; - - return node; + return pm_parameters_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }), + ((pm_node_list_t) { 0 }), + NULL, + ((pm_node_list_t) { 0 }), + ((pm_node_list_t) { 0 }), + NULL, + NULL + ); } /** @@ -5732,27 +5693,27 @@ pm_parameters_node_location_set(pm_parameters_node_t *params, pm_node_t *param) * Append a required parameter to a ParametersNode node. */ static void -pm_parameters_node_requireds_append(pm_parameters_node_t *params, pm_node_t *param) { +pm_parameters_node_requireds_append(pm_arena_t *arena, pm_parameters_node_t *params, pm_node_t *param) { pm_parameters_node_location_set(params, param); - pm_node_list_append(¶ms->requireds, param); + pm_node_list_append(arena, ¶ms->requireds, param); } /** * Append an optional parameter to a ParametersNode node. */ static void -pm_parameters_node_optionals_append(pm_parameters_node_t *params, pm_optional_parameter_node_t *param) { +pm_parameters_node_optionals_append(pm_arena_t *arena, pm_parameters_node_t *params, pm_optional_parameter_node_t *param) { pm_parameters_node_location_set(params, UP(param)); - pm_node_list_append(¶ms->optionals, UP(param)); + pm_node_list_append(arena, ¶ms->optionals, UP(param)); } /** * Append a post optional arguments parameter to a ParametersNode node. */ static void -pm_parameters_node_posts_append(pm_parameters_node_t *params, pm_node_t *param) { +pm_parameters_node_posts_append(pm_arena_t *arena, pm_parameters_node_t *params, pm_node_t *param) { pm_parameters_node_location_set(params, param); - pm_node_list_append(¶ms->posts, param); + pm_node_list_append(arena, ¶ms->posts, param); } /** @@ -5768,9 +5729,9 @@ pm_parameters_node_rest_set(pm_parameters_node_t *params, pm_node_t *param) { * Append a keyword parameter to a ParametersNode node. */ static void -pm_parameters_node_keywords_append(pm_parameters_node_t *params, pm_node_t *param) { +pm_parameters_node_keywords_append(pm_arena_t *arena, pm_parameters_node_t *params, pm_node_t *param) { pm_parameters_node_location_set(params, param); - pm_node_list_append(¶ms->keywords, param); + pm_node_list_append(arena, ¶ms->keywords, param); } /** @@ -5787,9 +5748,9 @@ pm_parameters_node_keyword_rest_set(pm_parameters_node_t *params, pm_node_t *par * Set the block parameter on a ParametersNode node. */ static void -pm_parameters_node_block_set(pm_parameters_node_t *params, pm_block_parameter_node_t *param) { +pm_parameters_node_block_set(pm_parameters_node_t *params, pm_node_t *param) { assert(params->block == NULL); - pm_parameters_node_location_set(params, UP(param)); + pm_parameters_node_location_set(params, param); params->block = param; } @@ -5798,15 +5759,14 @@ 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_NODE_ALLOC(parser, pm_program_node_t); - - *node = (pm_program_node_t) { - .base = PM_NODE_INIT(parser, PM_PROGRAM_NODE, 0, PM_LOCATION_INIT_NODE(statements)), - .locals = *locals, - .statements = statements - }; - - return node; + return pm_program_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODE(statements), + *locals, + statements + ); } /** @@ -5814,16 +5774,15 @@ 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_node_flags_t flags) { - pm_parentheses_node_t *node = PM_NODE_ALLOC(parser, pm_parentheses_node_t); - - *node = (pm_parentheses_node_t) { - .base = PM_NODE_INIT(parser, PM_PARENTHESES_NODE, flags, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .body = body, - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing) - }; - - return node; + return pm_parentheses_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + body, + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -5831,17 +5790,16 @@ 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_NODE_ALLOC(parser, pm_pinned_expression_node_t); - - *node = (pm_pinned_expression_node_t) { - .base = PM_NODE_INIT(parser, PM_PINNED_EXPRESSION_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, operator, rparen)), - .expression = expression, - .operator_loc = TOK2LOC(parser, operator), - .lparen_loc = TOK2LOC(parser, lparen), - .rparen_loc = TOK2LOC(parser, rparen) - }; - - return node; + return pm_pinned_expression_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, operator, rparen), + expression, + TOK2LOC(parser, operator), + TOK2LOC(parser, lparen), + TOK2LOC(parser, rparen) + ); } /** @@ -5849,15 +5807,14 @@ 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_NODE_ALLOC(parser, pm_pinned_variable_node_t); - - *node = (pm_pinned_variable_node_t) { - .base = PM_NODE_INIT(parser, PM_PINNED_VARIABLE_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, operator, variable)), - .variable = variable, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_pinned_variable_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, operator, variable), + variable, + TOK2LOC(parser, operator) + ); } /** @@ -5865,17 +5822,16 @@ 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_NODE_ALLOC(parser, pm_post_execution_node_t); - - *node = (pm_post_execution_node_t) { - .base = PM_NODE_INIT(parser, PM_POST_EXECUTION_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, keyword, closing)), - .statements = statements, - .keyword_loc = TOK2LOC(parser, keyword), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing) - }; - - return node; + return pm_post_execution_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, keyword, closing), + statements, + TOK2LOC(parser, keyword), + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -5883,17 +5839,16 @@ 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_NODE_ALLOC(parser, pm_pre_execution_node_t); - - *node = (pm_pre_execution_node_t) { - .base = PM_NODE_INIT(parser, PM_PRE_EXECUTION_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, keyword, closing)), - .statements = statements, - .keyword_loc = TOK2LOC(parser, keyword), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing) - }; - - return node; + return pm_pre_execution_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, keyword, closing), + statements, + TOK2LOC(parser, keyword), + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -5903,8 +5858,6 @@ static pm_range_node_t * pm_range_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_assert_value_expression(parser, right); - - 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 `...`. @@ -5925,14 +5878,15 @@ pm_range_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *ope uint32_t start = left == NULL ? PM_TOKEN_START(parser, operator) : PM_NODE_START(left); uint32_t end = right == NULL ? PM_TOKEN_END(parser, operator) : PM_NODE_END(right); - *node = (pm_range_node_t) { - .base = PM_NODE_INIT(parser, PM_RANGE_NODE, flags, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .left = left, - .right = right, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_range_node_new( + parser->arena, + ++parser->node_id, + flags, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + left, + right, + TOK2LOC(parser, operator) + ); } /** @@ -5941,33 +5895,31 @@ 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_NODE_ALLOC(parser, pm_redo_node_t); - *node = (pm_redo_node_t) { - .base = PM_NODE_INIT(parser, PM_REDO_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - - return node; + return pm_redo_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** * Allocate a new initialize a new RegularExpressionNode node with the given * unescaped string. */ -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_NODE_ALLOC(parser, pm_regular_expression_node_t); - pm_node_flags_t flags = pm_regular_expression_flags_create(parser, closing) | PM_NODE_FLAG_STATIC_LITERAL; - - *node = (pm_regular_expression_node_t) { - .base = PM_NODE_INIT(parser, PM_REGULAR_EXPRESSION_NODE, flags, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .opening_loc = TOK2LOC(parser, opening), - .content_loc = TOK2LOC(parser, content), - .closing_loc = TOK2LOC(parser, closing), - .unescaped = *unescaped - }; - - return node; +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) { + return pm_regular_expression_node_new( + parser->arena, + ++parser->node_id, + pm_regular_expression_flags_create(parser, closing) | PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + TOK2LOC(parser, opening), + TOK2LOC(parser, content), + TOK2LOC(parser, closing), + *unescaped + ); } /** @@ -5983,14 +5935,13 @@ 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_NODE_ALLOC(parser, pm_required_parameter_node_t); - - *node = (pm_required_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_REQUIRED_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)), - .name = pm_parser_constant_id_token(parser, token) - }; - - return node; + return pm_required_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token), + pm_parser_constant_id_token(parser, token) + ); } /** @@ -5998,16 +5949,15 @@ 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_NODE_ALLOC(parser, pm_rescue_modifier_node_t); - - *node = (pm_rescue_modifier_node_t) { - .base = PM_NODE_INIT(parser, PM_RESCUE_MODIFIER_NODE, 0, PM_LOCATION_INIT_NODES(expression, rescue_expression)), - .expression = expression, - .keyword_loc = TOK2LOC(parser, keyword), - .rescue_expression = rescue_expression - }; - - return node; + return pm_rescue_modifier_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(expression, rescue_expression), + expression, + TOK2LOC(parser, keyword), + rescue_expression + ); } /** @@ -6015,20 +5965,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_NODE_ALLOC(parser, pm_rescue_node_t); - - *node = (pm_rescue_node_t) { - .base = PM_NODE_INIT(parser, PM_RESCUE_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, keyword)), - .keyword_loc = TOK2LOC(parser, keyword), - .operator_loc = { 0 }, - .then_keyword_loc = { 0 }, - .reference = NULL, - .statements = NULL, - .subsequent = NULL, - .exceptions = { 0 } - }; - - return node; + return pm_rescue_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, keyword), + TOK2LOC(parser, keyword), + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + NULL, + ((pm_location_t) { 0 }), + NULL, + NULL + ); } static inline void @@ -6069,8 +6018,8 @@ pm_rescue_node_subsequent_set(pm_rescue_node_t *node, pm_rescue_node_t *subseque * Append an exception node to a rescue node, and update the location. */ static void -pm_rescue_node_exceptions_append(pm_rescue_node_t *node, pm_node_t *exception) { - pm_node_list_append(&node->exceptions, exception); +pm_rescue_node_exceptions_append(pm_arena_t *arena, pm_rescue_node_t *node, pm_node_t *exception) { + pm_node_list_append(arena, &node->exceptions, exception); PM_NODE_LENGTH_SET_NODE(node, exception); } @@ -6079,16 +6028,15 @@ 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_NODE_ALLOC(parser, pm_rest_parameter_node_t); - - *node = (pm_rest_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_REST_PARAMETER_NODE, 0, (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name)), - .name = name == NULL ? 0 : pm_parser_constant_id_token(parser, name), - .name_loc = NTOK2LOC(parser, name), - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_rest_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name), + name == NULL ? 0 : pm_parser_constant_id_token(parser, name), + NTOK2LOC(parser, name), + TOK2LOC(parser, operator) + ); } /** @@ -6097,13 +6045,13 @@ 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_NODE_ALLOC(parser, pm_retry_node_t); - - *node = (pm_retry_node_t) { - .base = PM_NODE_INIT(parser, PM_RETRY_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_retry_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -6111,15 +6059,14 @@ 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_NODE_ALLOC(parser, pm_return_node_t); - - *node = (pm_return_node_t) { - .base = PM_NODE_INIT(parser, PM_RETURN_NODE, 0, (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments)), - .keyword_loc = TOK2LOC(parser, keyword), - .arguments = arguments - }; - - return node; + return pm_return_node_new( + parser->arena, + ++parser->node_id, + 0, + (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments), + TOK2LOC(parser, keyword), + arguments + ); } /** @@ -6128,13 +6075,13 @@ 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_NODE_ALLOC(parser, pm_self_node_t); - - *node = (pm_self_node_t) { - .base = PM_NODE_INIT(parser, PM_SELF_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_self_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -6142,14 +6089,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_NODE_ALLOC(parser, pm_shareable_constant_node_t); - - *node = (pm_shareable_constant_node_t) { - .base = PM_NODE_INIT(parser, PM_SHAREABLE_CONSTANT_NODE, (pm_node_flags_t) value, PM_LOCATION_INIT_NODE(write)), - .write = write - }; - - return node; + return pm_shareable_constant_node_new( + parser->arena, + ++parser->node_id, + (pm_node_flags_t) value, + PM_LOCATION_INIT_NODE(write), + write + ); } /** @@ -6157,19 +6103,18 @@ 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_NODE_ALLOC(parser, pm_singleton_class_node_t); - - *node = (pm_singleton_class_node_t) { - .base = PM_NODE_INIT(parser, PM_SINGLETON_CLASS_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, class_keyword, end_keyword)), - .locals = *locals, - .class_keyword_loc = TOK2LOC(parser, class_keyword), - .operator_loc = TOK2LOC(parser, operator), - .expression = expression, - .body = body, - .end_keyword_loc = TOK2LOC(parser, end_keyword) - }; - - return node; + return pm_singleton_class_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, class_keyword, end_keyword), + *locals, + TOK2LOC(parser, class_keyword), + TOK2LOC(parser, operator), + expression, + body, + TOK2LOC(parser, end_keyword) + ); } /** @@ -6178,13 +6123,13 @@ 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_NODE_ALLOC(parser, pm_source_encoding_node_t); - *node = (pm_source_encoding_node_t) { - .base = PM_NODE_INIT(parser, PM_SOURCE_ENCODING_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - - return node; + return pm_source_encoding_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -6192,7 +6137,6 @@ 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_NODE_ALLOC(parser, pm_source_file_node_t); assert(file_keyword->type == PM_TOKEN_KEYWORD___FILE__); pm_node_flags_t flags = 0; @@ -6206,12 +6150,13 @@ pm_source_file_node_create(pm_parser_t *parser, const pm_token_t *file_keyword) break; } - *node = (pm_source_file_node_t) { - .base = PM_NODE_INIT(parser, PM_SOURCE_FILE_NODE, flags, PM_LOCATION_INIT_TOKEN(parser, file_keyword)), - .filepath = parser->filepath - }; - - return node; + return pm_source_file_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_TOKEN(parser, file_keyword), + parser->filepath + ); } /** @@ -6220,13 +6165,13 @@ 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_NODE_ALLOC(parser, pm_source_line_node_t); - *node = (pm_source_line_node_t) { - .base = PM_NODE_INIT(parser, PM_SOURCE_LINE_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - - return node; + return pm_source_line_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -6234,15 +6179,14 @@ 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_NODE_ALLOC(parser, pm_splat_node_t); - - *node = (pm_splat_node_t) { - .base = PM_NODE_INIT(parser, PM_SPLAT_NODE, 0, (expression == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, expression)), - .operator_loc = TOK2LOC(parser, operator), - .expression = expression - }; - - return node; + return pm_splat_node_new( + parser->arena, + ++parser->node_id, + 0, + (expression == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, expression), + TOK2LOC(parser, operator), + expression + ); } /** @@ -6250,14 +6194,13 @@ 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_NODE_ALLOC(parser, pm_statements_node_t); - - *node = (pm_statements_node_t) { - .base = PM_NODE_INIT(parser, PM_STATEMENTS_NODE, 0, PM_LOCATION_INIT_UNSET), - .body = { 0 } - }; - - return node; + return pm_statements_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }) + ); } /** @@ -6306,7 +6249,7 @@ pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node, } } - pm_node_list_append(&node->body, statement); + pm_node_list_append(parser->arena, &node->body, statement); if (newline) pm_node_flag_set(statement, PM_NODE_FLAG_NEWLINE); } @@ -6314,9 +6257,9 @@ pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node, * Prepend a new node to the given StatementsNode node's body. */ static void -pm_statements_node_body_prepend(pm_statements_node_t *node, pm_node_t *statement) { +pm_statements_node_body_prepend(pm_arena_t *arena, pm_statements_node_t *node, pm_node_t *statement) { pm_statements_node_body_update(node, statement); - pm_node_list_prepend(&node->body, statement); + pm_node_list_prepend(arena, &node->body, statement); pm_node_flag_set(statement, PM_NODE_FLAG_NEWLINE); } @@ -6325,7 +6268,6 @@ 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_NODE_ALLOC(parser, pm_string_node_t); pm_node_flags_t flags = 0; switch (parser->frozen_string_literal) { @@ -6340,15 +6282,16 @@ pm_string_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, uint32_t start = PM_TOKEN_START(parser, opening == NULL ? content : opening); uint32_t end = PM_TOKEN_END(parser, closing == NULL ? content : closing); - *node = (pm_string_node_t) { - .base = PM_NODE_INIT(parser, PM_STRING_NODE, flags, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .opening_loc = NTOK2LOC(parser, opening), - .content_loc = TOK2LOC(parser, content), - .closing_loc = NTOK2LOC(parser, closing), - .unescaped = *string - }; - - return node; + return pm_string_node_new( + parser->arena, + ++parser->node_id, + flags, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NTOK2LOC(parser, opening), + TOK2LOC(parser, content), + NTOK2LOC(parser, closing), + *string + ); } /** @@ -6376,21 +6319,21 @@ 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_NODE_ALLOC(parser, pm_super_node_t); const pm_location_t *end = pm_arguments_end(arguments); assert(end != NULL && "unreachable"); - *node = (pm_super_node_t) { - .base = PM_NODE_INIT(parser, PM_SUPER_NODE, 0, ((pm_location_t) { .start = PM_TOKEN_START(parser, keyword), .length = PM_LOCATION_END(end) - PM_TOKEN_START(parser, keyword) })), - .keyword_loc = TOK2LOC(parser, keyword), - .lparen_loc = arguments->opening_loc, - .arguments = arguments->arguments, - .rparen_loc = arguments->closing_loc, - .block = arguments->block - }; - - return node; + return pm_super_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = PM_TOKEN_START(parser, keyword), .length = PM_LOCATION_END(end) - PM_TOKEN_START(parser, keyword) }), + TOK2LOC(parser, keyword), + arguments->opening_loc, + arguments->arguments, + arguments->closing_loc, + arguments->block + ); } /** @@ -6480,149 +6423,25 @@ parse_symbol_encoding(pm_parser_t *parser, const pm_token_t *location, const pm_ return 0; } -static pm_node_flags_t -parse_and_validate_regular_expression_encoding_modifier(pm_parser_t *parser, const pm_string_t *source, bool ascii_only, pm_node_flags_t flags, char modifier, const pm_encoding_t *modifier_encoding) { - assert ((modifier == 'n' && modifier_encoding == PM_ENCODING_ASCII_8BIT_ENTRY) || - (modifier == 'u' && modifier_encoding == PM_ENCODING_UTF_8_ENTRY) || - (modifier == 'e' && modifier_encoding == PM_ENCODING_EUC_JP_ENTRY) || - (modifier == 's' && modifier_encoding == PM_ENCODING_WINDOWS_31J_ENTRY)); - - // There's special validation logic used if a string does not contain any character escape sequences. - if (parser->explicit_encoding == NULL) { - // If an ASCII-only string without character escapes is used with an encoding modifier, then resulting Regexp - // has the modifier encoding, unless the ASCII-8BIT modifier is used, in which case the Regexp "downgrades" to - // the US-ASCII encoding. - if (ascii_only) { - return modifier == 'n' ? PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING : flags; - } - - if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) { - if (!ascii_only) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_INVALID_MULTIBYTE_CHAR, parser->encoding->name); - } - } else if (parser->encoding != modifier_encoding) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_REGEXP_ENCODING_OPTION_MISMATCH, modifier, parser->encoding->name); - - if (modifier == 'n' && !ascii_only) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_REGEXP_NON_ESCAPED_MBC, (int) pm_string_length(source), (const char *) pm_string_source(source)); - } - } - - return flags; - } - - // TODO (nirvdrum 21-Feb-2024): To validate regexp sources with character escape sequences we need to know whether hex or Unicode escape sequences were used and Prism doesn't currently provide that data. We handle a subset of unambiguous cases in the meanwhile. - bool mixed_encoding = false; - - if (mixed_encoding) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_INVALID_MULTIBYTE_ESCAPE, (int) pm_string_length(source), (const char *) pm_string_source(source)); - } else if (modifier != 'n' && parser->explicit_encoding == PM_ENCODING_ASCII_8BIT_ENTRY) { - // TODO (nirvdrum 21-Feb-2024): Validate the content is valid in the modifier encoding. Do this on-demand so we don't pay the cost of computation unnecessarily. - bool valid_string_in_modifier_encoding = true; - - if (!valid_string_in_modifier_encoding) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_INVALID_MULTIBYTE_ESCAPE, (int) pm_string_length(source), (const char *) pm_string_source(source)); - } - } else if (modifier != 'u' && parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { - // TODO (nirvdrum 21-Feb-2024): There's currently no way to tell if the source used hex or Unicode character escapes from `explicit_encoding` alone. If the source encoding was already UTF-8, both character escape types would set `explicit_encoding` to UTF-8, but need to be processed differently. Skip for now. - if (parser->encoding != PM_ENCODING_UTF_8_ENTRY) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_REGEXP_INCOMPAT_CHAR_ENCODING, (int) pm_string_length(source), (const char *) pm_string_source(source)); - } - } - - // We've determined the encoding would naturally be EUC-JP and there is no need to force the encoding to anything else. - return flags; -} - -/** - * Ruby "downgrades" the encoding of Regexps to US-ASCII if the associated encoding is ASCII-compatible and - * the unescaped representation of a Regexp source consists only of US-ASCII code points. This is true even - * when the Regexp is explicitly given an ASCII-8BIT encoding via the (/n) modifier. Otherwise, the encoding - * may be explicitly set with an escape sequence. - */ -static pm_node_flags_t -parse_and_validate_regular_expression_encoding(pm_parser_t *parser, const pm_string_t *source, bool ascii_only, pm_node_flags_t flags) { - // TODO (nirvdrum 22-Feb-2024): CRuby reports a special Regexp-specific error for invalid Unicode ranges. We either need to scan again or modify the "invalid Unicode escape sequence" message we already report. - bool valid_unicode_range = true; - if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY && !valid_unicode_range) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_REGEXP_INVALID_UNICODE_RANGE, (int) pm_string_length(source), (const char *) pm_string_source(source)); - return flags; - } - - // US-ASCII strings do not admit multi-byte character literals. However, character escape sequences corresponding - // to multi-byte characters are allowed. - if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY && parser->explicit_encoding == NULL && !ascii_only) { - // CRuby will continue processing even though a SyntaxError has already been detected. It may result in the - // following error message appearing twice. We do the same for compatibility. - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_INVALID_MULTIBYTE_CHAR, parser->encoding->name); - } - - /** - * Start checking modifier flags. We need to process these before considering any explicit encodings that may have - * been set by character literals. The order in which the encoding modifiers is checked does not matter. In the - * event that both an encoding modifier and an explicit encoding would result in the same encoding we do not set - * the corresponding "forced_" flag. Instead, the caller should check the encoding modifier flag and - * determine the encoding that way. - */ - - if (flags & PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT) { - return parse_and_validate_regular_expression_encoding_modifier(parser, source, ascii_only, flags, 'n', PM_ENCODING_ASCII_8BIT_ENTRY); - } - - if (flags & PM_REGULAR_EXPRESSION_FLAGS_UTF_8) { - return parse_and_validate_regular_expression_encoding_modifier(parser, source, ascii_only, flags, 'u', PM_ENCODING_UTF_8_ENTRY); - } - - if (flags & PM_REGULAR_EXPRESSION_FLAGS_EUC_JP) { - return parse_and_validate_regular_expression_encoding_modifier(parser, source, ascii_only, flags, 'e', PM_ENCODING_EUC_JP_ENTRY); - } - - if (flags & PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J) { - return parse_and_validate_regular_expression_encoding_modifier(parser, source, ascii_only, flags, 's', PM_ENCODING_WINDOWS_31J_ENTRY); - } - - // At this point no encoding modifiers will be present on the regular expression as they would have already - // been processed. Ruby stipulates that all source files must use an ASCII-compatible encoding. Thus, all - // regular expressions without an encoding modifier appearing in source are eligible for "downgrading" to US-ASCII. - if (ascii_only) { - return PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING; - } - - // A Regexp may optionally have its encoding explicitly set via a character escape sequence in the source string - // or by specifying a modifier. - // - // NB: an explicitly set encoding is ignored by Ruby if the Regexp consists of only US ASCII code points. - if (parser->explicit_encoding != NULL) { - if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { - return PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING; - } else if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) { - return PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING; - } - } - - return 0; -} - /** * Allocate and initialize a new SymbolNode node with the given unescaped * string. */ 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_NODE_ALLOC(parser, pm_symbol_node_t); - uint32_t start = opening == NULL ? PM_TOKEN_START(parser, value) : PM_TOKEN_START(parser, opening); uint32_t end = closing == NULL ? PM_TOKEN_END(parser, value) : PM_TOKEN_END(parser, closing); - *node = (pm_symbol_node_t) { - .base = PM_NODE_INIT(parser, PM_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL | flags, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .opening_loc = NTOK2LOC(parser, opening), - .value_loc = NTOK2LOC(parser, value), - .closing_loc = NTOK2LOC(parser, closing), - .unescaped = *unescaped - }; - - return node; + return pm_symbol_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL | flags, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NTOK2LOC(parser, opening), + NTOK2LOC(parser, value), + NTOK2LOC(parser, closing), + *unescaped + ); } /** @@ -6666,13 +6485,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_NODE_ALLOC(parser, pm_symbol_node_t); - - *node = (pm_symbol_node_t) { - .base = PM_NODE_INIT(parser, PM_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL | PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING, PM_LOCATION_INIT_UNSET), - .value_loc = { 0 }, - .unescaped = { 0 } - }; + pm_symbol_node_t *node = pm_symbol_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL | PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING, + PM_LOCATION_INIT_UNSET, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_string_t) { 0 }) + ); pm_string_constant_init(&node->unescaped, content, strlen(content)); return node; @@ -6712,15 +6534,16 @@ pm_symbol_node_label_p(const pm_parser_t *parser, const 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_NODE_ALLOC(parser, pm_symbol_node_t); - - *new_node = (pm_symbol_node_t) { - .base = PM_NODE_INIT(parser, PM_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .opening_loc = TOK2LOC(parser, opening), - .value_loc = node->content_loc, - .closing_loc = TOK2LOC(parser, closing), - .unescaped = node->unescaped - }; + pm_symbol_node_t *new_node = pm_symbol_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + TOK2LOC(parser, opening), + node->content_loc, + TOK2LOC(parser, closing), + node->unescaped + ); pm_token_t content = { .type = PM_TOKEN_IDENTIFIER, @@ -6730,11 +6553,7 @@ pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const pm_node_flag_set(UP(new_node), parse_symbol_encoding(parser, &content, &node->unescaped, true)); - // We are explicitly _not_ using pm_node_destroy here because we don't want - // to trash the unescaped string. We could instead copy the string if we - // know that it is owned, but we're taking the fast path for now. - xfree(node); - + /* The old node is arena-allocated so no explicit free is needed. */ return new_node; } @@ -6743,7 +6562,6 @@ 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_NODE_ALLOC(parser, pm_string_node_t); pm_node_flags_t flags = 0; switch (parser->frozen_string_literal) { @@ -6755,19 +6573,18 @@ pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) { break; } - *new_node = (pm_string_node_t) { - .base = PM_NODE_INIT(parser, PM_STRING_NODE, flags, PM_LOCATION_INIT_NODE(node)), - .opening_loc = node->opening_loc, - .content_loc = node->value_loc, - .closing_loc = node->closing_loc, - .unescaped = node->unescaped - }; - - // We are explicitly _not_ using pm_node_destroy here because we don't want - // to trash the unescaped string. We could instead copy the string if we - // know that it is owned, but we're taking the fast path for now. - xfree(node); + pm_string_node_t *new_node = pm_string_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_NODE(node), + node->opening_loc, + node->value_loc, + node->closing_loc, + node->unescaped + ); + /* The old node is arena-allocated so no explicit free is needed. */ return new_node; } @@ -6777,13 +6594,13 @@ 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_NODE_ALLOC(parser, pm_true_node_t); - - *node = (pm_true_node_t) { - .base = PM_NODE_INIT(parser, PM_TRUE_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_true_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -6791,13 +6608,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_NODE_ALLOC(parser, pm_true_node_t); - - *node = (pm_true_node_t) { - .base = PM_NODE_INIT(parser, PM_TRUE_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_UNSET) - }; - - return node; + return pm_true_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_UNSET + ); } /** @@ -6806,24 +6622,24 @@ 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_NODE_ALLOC(parser, pm_undef_node_t); - *node = (pm_undef_node_t) { - .base = PM_NODE_INIT(parser, PM_UNDEF_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)), - .keyword_loc = TOK2LOC(parser, token), - .names = { 0 } - }; - - return node; + return pm_undef_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token), + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, token) + ); } /** * Append a name to an undef node. */ static void -pm_undef_node_append(pm_undef_node_t *node, pm_node_t *name) { +pm_undef_node_append(pm_arena_t *arena, pm_undef_node_t *node, pm_node_t *name) { PM_NODE_LENGTH_SET_NODE(node, name); - pm_node_list_append(&node->names, name); + pm_node_list_append(arena, &node->names, name); } /** @@ -6832,21 +6648,20 @@ 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_NODE_ALLOC(parser, pm_unless_node_t); pm_node_t *end = statements == NULL ? predicate : UP(statements); - *node = (pm_unless_node_t) { - .base = PM_NODE_INIT(parser, PM_UNLESS_NODE, PM_NODE_FLAG_NEWLINE, PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, end)), - .keyword_loc = TOK2LOC(parser, keyword), - .predicate = predicate, - .then_keyword_loc = NTOK2LOC(parser, then_keyword), - .statements = statements, - .else_clause = NULL, - .end_keyword_loc = { 0 } - }; - - return node; + return pm_unless_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_NEWLINE, + PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, end), + TOK2LOC(parser, keyword), + predicate, + NTOK2LOC(parser, then_keyword), + statements, + NULL, + ((pm_location_t) { 0 }) + ); } /** @@ -6855,22 +6670,22 @@ 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_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, true); - *node = (pm_unless_node_t) { - .base = PM_NODE_INIT(parser, PM_UNLESS_NODE, PM_NODE_FLAG_NEWLINE, PM_LOCATION_INIT_NODES(statement, predicate)), - .keyword_loc = TOK2LOC(parser, unless_keyword), - .predicate = predicate, - .then_keyword_loc = { 0 }, - .statements = statements, - .else_clause = NULL, - .end_keyword_loc = { 0 } - }; - - return node; + return pm_unless_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_NEWLINE, + PM_LOCATION_INIT_NODES(statement, predicate), + TOK2LOC(parser, unless_keyword), + predicate, + ((pm_location_t) { 0 }), + statements, + NULL, + ((pm_location_t) { 0 }) + ); } static inline void @@ -6907,19 +6722,19 @@ pm_loop_modifier_block_exits(pm_parser_t *parser, pm_statements_node_t *statemen */ static pm_until_node_t * pm_until_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *do_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_NODE_ALLOC(parser, pm_until_node_t); pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - *node = (pm_until_node_t) { - .base = PM_NODE_INIT(parser, PM_UNTIL_NODE, flags, PM_LOCATION_INIT_TOKENS(parser, keyword, closing)), - .keyword_loc = TOK2LOC(parser, keyword), - .do_keyword_loc = NTOK2LOC(parser, do_keyword), - .closing_loc = TOK2LOC(parser, closing), - .predicate = predicate, - .statements = statements - }; - - return node; + return pm_until_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_TOKENS(parser, keyword, closing), + TOK2LOC(parser, keyword), + NTOK2LOC(parser, do_keyword), + TOK2LOC(parser, closing), + predicate, + statements + ); } /** @@ -6927,20 +6742,20 @@ 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_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) { - .base = PM_NODE_INIT(parser, PM_UNTIL_NODE, flags, PM_LOCATION_INIT_NODES(statements, predicate)), - .keyword_loc = TOK2LOC(parser, keyword), - .do_keyword_loc = { 0 }, - .closing_loc = { 0 }, - .predicate = predicate, - .statements = statements - }; - - return node; + return pm_until_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_NODES(statements, predicate), + TOK2LOC(parser, keyword), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + predicate, + statements + ); } /** @@ -6948,26 +6763,25 @@ 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_NODE_ALLOC(parser, pm_when_node_t); - - *node = (pm_when_node_t) { - .base = PM_NODE_INIT(parser, PM_WHEN_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, keyword)), - .keyword_loc = TOK2LOC(parser, keyword), - .statements = NULL, - .then_keyword_loc = { 0 }, - .conditions = { 0 } - }; - - return node; + return pm_when_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, keyword), + TOK2LOC(parser, keyword), + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + NULL + ); } /** * Append a new condition to a when node. */ static void -pm_when_node_conditions_append(pm_when_node_t *node, pm_node_t *condition) { +pm_when_node_conditions_append(pm_arena_t *arena, pm_when_node_t *node, pm_node_t *condition) { PM_NODE_LENGTH_SET_NODE(node, condition); - pm_node_list_append(&node->conditions, condition); + pm_node_list_append(arena, &node->conditions, condition); } /** @@ -6996,19 +6810,19 @@ 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 *do_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_NODE_ALLOC(parser, pm_while_node_t); pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - *node = (pm_while_node_t) { - .base = PM_NODE_INIT(parser, PM_WHILE_NODE, flags, PM_LOCATION_INIT_TOKENS(parser, keyword, closing)), - .keyword_loc = TOK2LOC(parser, keyword), - .do_keyword_loc = NTOK2LOC(parser, do_keyword), - .closing_loc = TOK2LOC(parser, closing), - .predicate = predicate, - .statements = statements - }; - - return node; + return pm_while_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_TOKENS(parser, keyword, closing), + TOK2LOC(parser, keyword), + NTOK2LOC(parser, do_keyword), + TOK2LOC(parser, closing), + predicate, + statements + ); } /** @@ -7016,20 +6830,20 @@ 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_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) { - .base = PM_NODE_INIT(parser, PM_WHILE_NODE, flags, PM_LOCATION_INIT_NODES(statements, predicate)), - .keyword_loc = TOK2LOC(parser, keyword), - .do_keyword_loc = { 0 }, - .closing_loc = { 0 }, - .predicate = predicate, - .statements = statements - }; - - return node; + return pm_while_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_NODES(statements, predicate), + TOK2LOC(parser, keyword), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + predicate, + statements + ); } /** @@ -7037,18 +6851,17 @@ 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_NODE_ALLOC(parser, pm_while_node_t); - - *node = (pm_while_node_t) { - .base = PM_NODE_INIT(parser, PM_WHILE_NODE, 0, PM_LOCATION_INIT_UNSET), - .keyword_loc = { 0 }, - .do_keyword_loc = { 0 }, - .closing_loc = { 0 }, - .predicate = predicate, - .statements = statements - }; - - return node; + return pm_while_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + predicate, + statements + ); } /** @@ -7057,17 +6870,16 @@ 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_NODE_ALLOC(parser, pm_x_string_node_t); - - *node = (pm_x_string_node_t) { - .base = PM_NODE_INIT(parser, PM_X_STRING_NODE, PM_STRING_FLAGS_FROZEN, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .opening_loc = TOK2LOC(parser, opening), - .content_loc = TOK2LOC(parser, content), - .closing_loc = TOK2LOC(parser, closing), - .unescaped = *unescaped - }; - - return node; + return pm_x_string_node_new( + parser->arena, + ++parser->node_id, + PM_STRING_FLAGS_FROZEN, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + TOK2LOC(parser, opening), + TOK2LOC(parser, content), + TOK2LOC(parser, closing), + *unescaped + ); } /** @@ -7083,8 +6895,6 @@ 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_NODE_ALLOC(parser, pm_yield_node_t); - uint32_t start = PM_TOKEN_START(parser, keyword); uint32_t end; @@ -7098,15 +6908,16 @@ pm_yield_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_lo end = PM_TOKEN_END(parser, keyword); } - *node = (pm_yield_node_t) { - .base = PM_NODE_INIT(parser, PM_YIELD_NODE, 0, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .keyword_loc = TOK2LOC(parser, keyword), - .lparen_loc = *lparen_loc, - .arguments = arguments, - .rparen_loc = *rparen_loc - }; - - return node; + return pm_yield_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + TOK2LOC(parser, keyword), + *lparen_loc, + arguments, + *rparen_loc + ); } /** @@ -7228,8 +7039,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); + xfree_sized(scope, sizeof(pm_scope_t)); } /******************************************************************************/ @@ -7829,7 +7639,7 @@ context_push(pm_parser_t *parser, pm_context_t context) { static void context_pop(pm_parser_t *parser) { pm_context_node_t *prev = parser->current_context->prev; - xfree(parser->current_context); + xfree_sized(parser->current_context, sizeof(pm_context_node_t)); parser->current_context = prev; } @@ -8397,9 +8207,15 @@ lex_identifier(pm_parser_t *parser, bool previous_command_start) { switch (width) { case 2: if (lex_keyword(parser, current_start, "do", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_DO, PM_TOKEN_EOF) != PM_TOKEN_EOF) { + if (parser->enclosure_nesting == parser->lambda_enclosure_nesting) { + return PM_TOKEN_KEYWORD_DO; + } if (pm_do_loop_stack_p(parser)) { return PM_TOKEN_KEYWORD_DO_LOOP; } + if (!pm_accepts_block_stack_p(parser)) { + return PM_TOKEN_KEYWORD_DO_BLOCK; + } return PM_TOKEN_KEYWORD_DO; } @@ -8650,7 +8466,7 @@ escape_hexadecimal_digit(const uint8_t value) { * validated. */ static inline uint32_t -escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length, const pm_location_t *error_location) { +escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length, const pm_location_t *error_location, const uint8_t flags) { uint32_t value = 0; for (size_t index = 0; index < length; index++) { if (index != 0) value <<= 4; @@ -8660,7 +8476,10 @@ escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length, const // 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) { - if (error_location != NULL) { + if (flags & PM_ESCAPE_FLAG_REGEXP) { + // In regexp context, defer the error to regexp encoding + // validation where we can produce a regexp-specific message. + } else if (error_location != NULL) { pm_parser_err(parser, error_location->start, error_location->length, PM_ERR_ESCAPE_INVALID_UNICODE); } else { pm_parser_err(parser, U32(string - parser->start), U32(length), PM_ERR_ESCAPE_INVALID_UNICODE); @@ -8691,14 +8510,25 @@ escape_write_unicode(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_t fla // literal. if (value >= 0x80 || flags & PM_ESCAPE_FLAG_SINGLE) { if (parser->explicit_encoding != NULL && parser->explicit_encoding != PM_ENCODING_UTF_8_ENTRY) { - PM_PARSER_ERR_FORMAT(parser, U32(start - parser->start), U32(end - start), PM_ERR_MIXED_ENCODING, parser->explicit_encoding->name); + if (flags & PM_ESCAPE_FLAG_REGEXP) { + // In regexp context, suppress this error — the regexp encoding + // validation will produce a more specific error message. + } else { + PM_PARSER_ERR_FORMAT(parser, U32(start - parser->start), U32(end - start), PM_ERR_MIXED_ENCODING, parser->explicit_encoding->name); + } } parser->explicit_encoding = PM_ENCODING_UTF_8_ENTRY; } if (!pm_buffer_append_unicode_codepoint(buffer, value)) { - pm_parser_err(parser, U32(start - parser->start), U32(end - start), PM_ERR_ESCAPE_INVALID_UNICODE); + if (flags & PM_ESCAPE_FLAG_REGEXP) { + // In regexp context, defer the error to the regexp encoding + // validation which produces a regexp-specific message. + } else { + pm_parser_err(parser, U32(start - parser->start), U32(end - start), PM_ERR_ESCAPE_INVALID_UNICODE); + } + pm_buffer_append_byte(buffer, 0xEF); pm_buffer_append_byte(buffer, 0xBF); pm_buffer_append_byte(buffer, 0xBD); @@ -8710,10 +8540,15 @@ escape_write_unicode(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_t fla * (i.e., the top bit is set) then it locks in the encoding. */ static inline void -escape_write_byte_encoded(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t byte) { +escape_write_byte_encoded(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_t flags, uint8_t byte) { if (byte >= 0x80) { if (parser->explicit_encoding != NULL && parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY && parser->encoding != PM_ENCODING_UTF_8_ENTRY) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_MIXED_ENCODING, parser->encoding->name); + if (flags & PM_ESCAPE_FLAG_REGEXP) { + // In regexp context, suppress this error — the regexp encoding + // validation will produce a more specific error message. + } else { + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_MIXED_ENCODING, parser->encoding->name); + } } parser->explicit_encoding = parser->encoding; @@ -8743,7 +8578,7 @@ escape_write_byte(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular pm_buffer_append_format(regular_expression_buffer, "\\x%02X", byte); } - escape_write_byte_encoded(parser, buffer, byte); + escape_write_byte_encoded(parser, buffer, flags, byte); } /** @@ -8759,6 +8594,7 @@ escape_write_escape_encoded(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_ } if (width == 1) { + if (*parser->current.end == '\n') pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(*parser->current.end++, flags)); } else if (width > 1) { // Valid multibyte character. Just ignore escape. @@ -8899,7 +8735,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_encoded(parser, buffer, flags, value); } else { pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_HEXADECIMAL); } @@ -8948,7 +8784,8 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre 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. + // error instead of us because we don't know at this + // point if we're inside a comment in /x mode. pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end - start)); } else { pm_parser_err(parser, PM_TOKEN_END(parser, &parser->current), 0, PM_ERR_ESCAPE_INVALID_UNICODE); @@ -8964,7 +8801,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre extra_codepoints_start = unicode_start; } - uint32_t value = escape_unicode(parser, unicode_start, hexadecimal_length, NULL); + uint32_t value = escape_unicode(parser, unicode_start, hexadecimal_length, NULL, flags); escape_write_unicode(parser, buffer, flags, unicode_start, parser->current.end, value); parser->current.end += pm_strspn_inline_whitespace(parser->current.end, parser->end - parser->current.end); @@ -8984,7 +8821,8 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre 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. + // instead of us because we don't know at this point if + // we're inside a comment in /x mode. pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end - start)); } else { pm_parser_err(parser, U32(unicode_codepoints_start - parser->start), U32(parser->current.end - unicode_codepoints_start), PM_ERR_ESCAPE_INVALID_UNICODE_TERM); @@ -9005,7 +8843,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre PM_PARSER_ERR_FORMAT(parser, U32(start - parser->start), U32(parser->current.end - start), PM_ERR_ESCAPE_INVALID_UNICODE_SHORT, 2, start); } } else if (length == 4) { - uint32_t value = escape_unicode(parser, parser->current.end, 4, NULL); + uint32_t value = escape_unicode(parser, parser->current.end, 4, NULL, flags); if (flags & PM_ESCAPE_FLAG_REGEXP) { pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end + 4 - start)); @@ -9073,6 +8911,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; } + if (peeked == '\n') pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); parser->current.end++; escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_CONTROL)); return; @@ -9131,6 +8970,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; } + if (peeked == '\n') pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); parser->current.end++; escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_CONTROL)); return; @@ -9184,6 +9024,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; } + if (peeked == '\n') pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); parser->current.end++; escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_META)); return; @@ -9191,8 +9032,9 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre } case '\r': { if (peek_offset(parser, 1) == '\n') { + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 2); parser->current.end += 2; - escape_write_byte_encoded(parser, buffer, escape_byte('\n', flags)); + escape_write_byte_encoded(parser, buffer, flags, escape_byte('\n', flags)); return; } PRISM_FALLTHROUGH @@ -9265,7 +9107,11 @@ lex_question_mark(pm_parser_t *parser) { pm_buffer_init_capacity(&buffer, 3); escape_read(parser, &buffer, NULL, PM_ESCAPE_FLAG_SINGLE); - pm_string_owned_init(&parser->current_string, (uint8_t *) buffer.value, buffer.length); + + // Copy buffer data into the arena and free the heap buffer. + void *arena_data = pm_arena_memdup(parser->arena, buffer.value, buffer.length, PRISM_ALIGNOF(uint8_t)); + pm_string_constant_init(&parser->current_string, (const char *) arena_data, buffer.length); + pm_buffer_free(&buffer); return PM_TOKEN_CHARACTER_LITERAL; } else { @@ -9367,7 +9213,7 @@ lex_embdoc(pm_parser_t *parser) { if (newline == NULL) { parser->current.end = parser->end; } else { - pm_newline_list_append(&parser->newline_list, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(newline - parser->start + 1)); parser->current.end = newline + 1; } @@ -9401,7 +9247,7 @@ lex_embdoc(pm_parser_t *parser) { if (newline == NULL) { parser->current.end = parser->end; } else { - pm_newline_list_append(&parser->newline_list, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(newline - parser->start + 1)); parser->current.end = newline + 1; } @@ -9421,7 +9267,7 @@ lex_embdoc(pm_parser_t *parser) { if (newline == NULL) { parser->current.end = parser->end; } else { - pm_newline_list_append(&parser->newline_list, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(newline - parser->start + 1)); parser->current.end = newline + 1; } @@ -9573,20 +9419,12 @@ pm_token_buffer_push_escaped(pm_token_buffer_t *token_buffer, pm_parser_t *parse static void pm_regexp_token_buffer_push_escaped(pm_regexp_token_buffer_t *token_buffer, pm_parser_t *parser) { size_t width = parser_char_width(parser); - pm_buffer_append_bytes(&token_buffer->base.buffer, parser->current.end, width); - pm_buffer_append_bytes(&token_buffer->regexp_buffer, parser->current.end, width); + const uint8_t *start = parser->current.end; + pm_buffer_append_bytes(&token_buffer->base.buffer, start, width); + pm_buffer_append_bytes(&token_buffer->regexp_buffer, start, width); parser->current.end += width; } -static bool -pm_slice_ascii_only_p(const uint8_t *value, size_t length) { - for (size_t index = 0; index < length; index++) { - if (value[index] & 0x80) return false; - } - - return true; -} - /** * When we're about to return from lexing the current token and we know for sure * that we have found an escape sequence, this function is called to copy the @@ -9595,13 +9433,16 @@ pm_slice_ascii_only_p(const uint8_t *value, size_t length) { */ static inline void pm_token_buffer_copy(pm_parser_t *parser, pm_token_buffer_t *token_buffer) { - pm_string_owned_init(&parser->current_string, (uint8_t *) pm_buffer_value(&token_buffer->buffer), pm_buffer_length(&token_buffer->buffer)); + // Copy buffer data into the arena and free the heap buffer. + size_t len = pm_buffer_length(&token_buffer->buffer); + void *arena_data = pm_arena_memdup(parser->arena, pm_buffer_value(&token_buffer->buffer), len, PRISM_ALIGNOF(uint8_t)); + pm_string_constant_init(&parser->current_string, (const char *) arena_data, len); + pm_buffer_free(&token_buffer->buffer); } static inline void pm_regexp_token_buffer_copy(pm_parser_t *parser, pm_regexp_token_buffer_t *token_buffer) { - pm_string_owned_init(&parser->current_string, (uint8_t *) pm_buffer_value(&token_buffer->base.buffer), pm_buffer_length(&token_buffer->base.buffer)); - parser->current_regular_expression_ascii_only = pm_slice_ascii_only_p((const uint8_t *) pm_buffer_value(&token_buffer->regexp_buffer), pm_buffer_length(&token_buffer->regexp_buffer)); + pm_token_buffer_copy(parser, &token_buffer->base); pm_buffer_free(&token_buffer->regexp_buffer); } @@ -9628,10 +9469,11 @@ static void pm_regexp_token_buffer_flush(pm_parser_t *parser, pm_regexp_token_buffer_t *token_buffer) { if (token_buffer->base.cursor == NULL) { pm_string_shared_init(&parser->current_string, parser->current.start, parser->current.end); - parser->current_regular_expression_ascii_only = pm_slice_ascii_only_p(parser->current.start, (size_t) (parser->current.end - parser->current.start)); } else { - pm_buffer_append_bytes(&token_buffer->base.buffer, token_buffer->base.cursor, (size_t) (parser->current.end - token_buffer->base.cursor)); - pm_buffer_append_bytes(&token_buffer->regexp_buffer, token_buffer->base.cursor, (size_t) (parser->current.end - token_buffer->base.cursor)); + const uint8_t *cursor = token_buffer->base.cursor; + size_t length = (size_t) (parser->current.end - cursor); + pm_buffer_append_bytes(&token_buffer->base.buffer, cursor, length); + pm_buffer_append_bytes(&token_buffer->regexp_buffer, cursor, length); pm_regexp_token_buffer_copy(parser, token_buffer); } } @@ -9735,7 +9577,7 @@ pm_lex_percent_delimiter(pm_parser_t *parser) { parser_flush_heredoc_end(parser); } else { // Otherwise, we'll add the newline to the list of newlines. - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + U32(eol_length)); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + U32(eol_length)); } uint8_t delimiter = *parser->current.end; @@ -9783,6 +9625,12 @@ parser_lex(pm_parser_t *parser) { unsigned int semantic_token_seen = parser->semantic_token_seen; parser->semantic_token_seen = true; + // We'll jump to this label when we are about to encounter an EOF. + // If we still have lex_modes on the stack, we pop them so that cleanup + // can happen. For example, we should still continue parsing after a heredoc + // identifier, even if the heredoc body was syntax invalid. + switch_lex_modes: + switch (parser->lex_modes.current->mode) { case PM_LEX_DEFAULT: case PM_LEX_EMBEXPR: @@ -9833,7 +9681,7 @@ parser_lex(pm_parser_t *parser) { parser->heredoc_end = NULL; } else { parser->current.end += eol_length + 1; - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); space_seen = true; } } else if (pm_char_is_inline_whitespace(*parser->current.end)) { @@ -9856,6 +9704,14 @@ parser_lex(pm_parser_t *parser) { // We'll check if we're at the end of the file. If we are, then we // need to return the EOF token. if (parser->current.end >= parser->end) { + // We may be missing closing tokens. We should pop modes one by one + // to do the appropriate cleanup like moving next_start for heredocs. + // Only when no mode is remaining will we actually emit the EOF token. + if (parser->lex_modes.current->mode != PM_LEX_DEFAULT) { + lex_mode_pop(parser); + goto switch_lex_modes; + } + // If we hit EOF, but the EOF came immediately after a newline, // set the start of the token to the newline. This way any EOF // errors will be reported as happening on that line rather than @@ -9927,7 +9783,7 @@ parser_lex(pm_parser_t *parser) { } if (parser->heredoc_end == NULL) { - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); } } @@ -10013,8 +9869,21 @@ parser_lex(pm_parser_t *parser) { following && ( (peek_at(parser, following) == '&' && peek_at(parser, following + 1) == '&') || (peek_at(parser, following) == '|' && peek_at(parser, following + 1) == '|') || - (peek_at(parser, following) == 'a' && peek_at(parser, following + 1) == 'n' && peek_at(parser, following + 2) == 'd' && !char_is_identifier(parser, following + 3, parser->end - (following + 3))) || - (peek_at(parser, following) == 'o' && peek_at(parser, following + 1) == 'r' && !char_is_identifier(parser, following + 2, parser->end - (following + 2))) + ( + peek_at(parser, following) == 'a' && + peek_at(parser, following + 1) == 'n' && + peek_at(parser, following + 2) == 'd' && + peek_at(parser, next_content + 3) != '!' && + peek_at(parser, next_content + 3) != '?' && + !char_is_identifier(parser, following + 3, parser->end - (following + 3)) + ) || + ( + peek_at(parser, following) == 'o' && + peek_at(parser, following + 1) == 'r' && + peek_at(parser, next_content + 2) != '!' && + peek_at(parser, next_content + 2) != '?' && + !char_is_identifier(parser, following + 2, parser->end - (following + 2)) + ) ) ) { if (!lexed_comment) parser_lex_ignored_newline(parser); @@ -10085,6 +9954,8 @@ parser_lex(pm_parser_t *parser) { peek_at(parser, next_content) == 'a' && peek_at(parser, next_content + 1) == 'n' && peek_at(parser, next_content + 2) == 'd' && + peek_at(parser, next_content + 3) != '!' && + peek_at(parser, next_content + 3) != '?' && !char_is_identifier(parser, next_content + 3, parser->end - (next_content + 3)) ) { if (!lexed_comment) parser_lex_ignored_newline(parser); @@ -10101,6 +9972,8 @@ parser_lex(pm_parser_t *parser) { if ( peek_at(parser, next_content) == 'o' && peek_at(parser, next_content + 1) == 'r' && + peek_at(parser, next_content + 2) != '!' && + peek_at(parser, next_content + 2) != '?' && !char_is_identifier(parser, next_content + 2, parser->end - (next_content + 2)) ) { if (!lexed_comment) parser_lex_ignored_newline(parser); @@ -10436,7 +10309,7 @@ parser_lex(pm_parser_t *parser) { } else { // Otherwise, we want to indicate that the body of the // heredoc starts on the character after the next newline. - pm_newline_list_append(&parser->newline_list, U32(body_start - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(body_start - parser->start + 1)); body_start++; } @@ -11077,7 +10950,7 @@ parser_lex(pm_parser_t *parser) { // correct column information for it. const uint8_t *cursor = parser->current.end; while ((cursor = next_newline(cursor, parser->end - cursor)) != NULL) { - pm_newline_list_append(&parser->newline_list, U32(++cursor - parser->start)); + pm_line_offset_list_append(&parser->line_offsets, U32(++cursor - parser->start)); } parser->current.end = parser->end; @@ -11138,7 +11011,7 @@ parser_lex(pm_parser_t *parser) { whitespace += 1; } } else { - whitespace = pm_strspn_whitespace_newlines(parser->current.end, parser->end - parser->current.end, &parser->newline_list, PM_TOKEN_END(parser, &parser->current)); + whitespace = pm_strspn_whitespace_newlines(parser->current.end, parser->end - parser->current.end, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); } if (whitespace > 0) { @@ -11253,7 +11126,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } else { // ... else track the newline. - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + 1); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); } parser->current.end++; @@ -11391,7 +11264,7 @@ parser_lex(pm_parser_t *parser) { // would have already have added the newline to the // list. if (parser->heredoc_end == NULL) { - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); } } else { parser->current.end = breakpoint + 1; @@ -11438,7 +11311,7 @@ parser_lex(pm_parser_t *parser) { // If we've hit a newline, then we need to track that in // the list of newlines. if (parser->heredoc_end == NULL) { - pm_newline_list_append(&parser->newline_list, U32(breakpoint - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(breakpoint - parser->start + 1)); parser->current.end = breakpoint + 1; breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, false); break; @@ -11486,7 +11359,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } else { // ... else track the newline. - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + 1); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); } parser->current.end++; @@ -11651,7 +11524,7 @@ parser_lex(pm_parser_t *parser) { // would have already have added the newline to the // list. if (parser->heredoc_end == NULL) { - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); } } else { parser->current.end = breakpoint + 1; @@ -11703,7 +11576,7 @@ parser_lex(pm_parser_t *parser) { // for the terminator in case the terminator is a // newline character. if (parser->heredoc_end == NULL) { - pm_newline_list_append(&parser->newline_list, U32(breakpoint - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(breakpoint - parser->start + 1)); parser->current.end = breakpoint + 1; breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true); break; @@ -11757,7 +11630,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } else { // ... else track the newline. - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + 1); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); } parser->current.end++; @@ -11886,7 +11759,7 @@ parser_lex(pm_parser_t *parser) { (memcmp(terminator_start, ident_start, ident_length) == 0) ) { if (newline != NULL) { - pm_newline_list_append(&parser->newline_list, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(newline - parser->start + 1)); } parser->current.end = terminator_end; @@ -11958,7 +11831,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } - pm_newline_list_append(&parser->newline_list, U32(breakpoint - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(breakpoint - parser->start + 1)); // If we have a - or ~ heredoc, then we can match after // some leading whitespace. @@ -12078,7 +11951,7 @@ parser_lex(pm_parser_t *parser) { const uint8_t *end = parser->current.end; if (parser->heredoc_end == NULL) { - pm_newline_list_append(&parser->newline_list, U32(end - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(end - parser->start + 1)); } // Here we want the buffer to only @@ -12477,16 +12350,22 @@ expect1_opening(pm_parser_t *parser, pm_token_type_t type, pm_diagnostic_id_t di parser->previous.type = 0; } +/** Flags for controlling expression parsing behavior. */ +#define PM_PARSE_ACCEPTS_COMMAND_CALL ((uint8_t) 0x1) +#define PM_PARSE_ACCEPTS_LABEL ((uint8_t) 0x2) +#define PM_PARSE_ACCEPTS_DO_BLOCK ((uint8_t) 0x4) +#define PM_PARSE_IN_ENDLESS_DEF ((uint8_t) 0x8) + static pm_node_t * -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); +parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t flags, 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, 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); +parse_value_expression(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth) { + pm_node_t *node = parse_expression(parser, binding_power, flags, diag_id, depth); pm_assert_value_expression(parser, node); return node; } @@ -12525,6 +12404,7 @@ token_begins_expression_p(pm_token_type_t type) { case PM_TOKEN_EOF: case PM_TOKEN_LAMBDA_BEGIN: case PM_TOKEN_KEYWORD_DO: + case PM_TOKEN_KEYWORD_DO_BLOCK: case PM_TOKEN_KEYWORD_DO_LOOP: case PM_TOKEN_KEYWORD_END: case PM_TOKEN_KEYWORD_ELSE: @@ -12570,14 +12450,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, uint16_t depth) { +parse_starred_expression(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t flags, 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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); + pm_node_t *expression = parse_value_expression(parser, binding_power, (uint8_t) (flags & PM_PARSE_ACCEPTS_DO_BLOCK), PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); return UP(pm_splat_node_create(parser, &operator, expression)); } - return parse_value_expression(parser, binding_power, accepts_command_call, false, diag_id, depth); + return parse_value_expression(parser, binding_power, flags, diag_id, depth); } static bool @@ -12701,7 +12581,6 @@ parse_unwriteable_target(pm_parser_t *parser, pm_node_t *target) { pm_constant_id_t name = pm_parser_constant_id_raw(parser, parser->start + PM_NODE_START(target), parser->start + PM_NODE_END(target)); pm_local_variable_target_node_t *result = pm_local_variable_target_node_create(parser, &target->location, name, 0); - pm_node_destroy(parser, target); return UP(result); } @@ -12780,7 +12659,6 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple, bool splat_p pm_node_t *node = UP(pm_local_variable_target_node_create(parser, &target->location, name, 0)); pm_node_unreference(parser, target); - pm_node_destroy(parser, target); return node; } @@ -12831,7 +12709,6 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple, bool splat_p // =, so we know it's a local variable write. pm_location_t message_loc = call->message_loc; pm_constant_id_t name = pm_parser_local_add_location(parser, &message_loc, 0); - pm_node_destroy(parser, target); return UP(pm_local_variable_target_node_create(parser, &message_loc, name, 0)); } @@ -12906,11 +12783,9 @@ static pm_node_t * parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_node_t *value) { switch (PM_NODE_TYPE(target)) { case PM_MISSING_NODE: - pm_node_destroy(parser, value); return target; case PM_CLASS_VARIABLE_READ_NODE: { pm_class_variable_write_node_t *node = pm_class_variable_write_node_create(parser, (pm_class_variable_read_node_t *) target, operator, value); - pm_node_destroy(parser, target); return UP(node); } case PM_CONSTANT_PATH_NODE: { @@ -12929,7 +12804,6 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_IN_METHOD); } - pm_node_destroy(parser, target); return parse_shareable_constant_write(parser, node); } case PM_BACK_REFERENCE_READ_NODE: @@ -12938,7 +12812,6 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod PRISM_FALLTHROUGH case PM_GLOBAL_VARIABLE_READ_NODE: { pm_global_variable_write_node_t *node = pm_global_variable_write_node_create(parser, target, operator, value); - pm_node_destroy(parser, target); return UP(node); } case PM_LOCAL_VARIABLE_READ_NODE: { @@ -12956,7 +12829,6 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod } pm_locals_unread(&scope->locals, name); - pm_node_destroy(parser, target); return UP(pm_local_variable_write_node_create(parser, name, depth, value, &location, operator)); } @@ -12965,13 +12837,11 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod pm_node_t *node = UP(pm_local_variable_write_node_create(parser, name, 0, value, &target->location, operator)); pm_node_unreference(parser, target); - pm_node_destroy(parser, target); return node; } case PM_INSTANCE_VARIABLE_READ_NODE: { pm_node_t *write_node = UP(pm_instance_variable_write_node_create(parser, (pm_instance_variable_read_node_t *) target, operator, value)); - pm_node_destroy(parser, target); return write_node; } case PM_MULTI_TARGET_NODE: @@ -13016,7 +12886,6 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod pm_refute_numbered_parameter(parser, message_loc.start, message_loc.length); pm_parser_local_add_location(parser, &message_loc, 0); - pm_node_destroy(parser, target); pm_constant_id_t constant_id = pm_parser_constant_id_raw(parser, parser->start + PM_LOCATION_START(&message_loc), parser->start + PM_LOCATION_END(&message_loc)); target = UP(pm_local_variable_write_node_create(parser, constant_id, 0, value, &message_loc, operator)); @@ -13038,7 +12907,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod pm_arguments_node_t *arguments = pm_arguments_node_create(parser); call->arguments = arguments; - pm_arguments_node_arguments_append(arguments, value); + pm_arguments_node_arguments_append(parser->arena, arguments, value); PM_NODE_LENGTH_SET_NODE(call, arguments); call->equal_loc = TOK2LOC(parser, operator); @@ -13057,7 +12926,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod call->arguments = pm_arguments_node_create(parser); } - pm_arguments_node_arguments_append(call->arguments, value); + pm_arguments_node_arguments_append(parser->arena, call->arguments, value); PM_NODE_LENGTH_SET_NODE(target, value); // Replace the name with "[]=". @@ -13082,7 +12951,6 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod // any implicit parameters from the list of implicit parameters for // the current scope. pm_node_unreference(parser, value); - pm_node_destroy(parser, value); } PRISM_FALLTHROUGH default: @@ -13116,7 +12984,6 @@ parse_unwriteable_write(pm_parser_t *parser, pm_node_t *target, const pm_token_t pm_constant_id_t name = pm_parser_local_add_location(parser, &target->location, 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); return UP(result); } @@ -13150,7 +13017,7 @@ 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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); + name = parse_expression(parser, binding_power, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); name = parse_target(parser, name, true, true); } @@ -13159,13 +13026,13 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b 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)); + pm_node_t *target = parse_expression(parser, binding_power, PM_PARSE_ACCEPTS_DO_BLOCK, 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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1)); + pm_node_t *target = parse_expression(parser, binding_power, PM_PARSE_ACCEPTS_DO_BLOCK, 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); @@ -13217,7 +13084,7 @@ parse_statements(pm_parser_t *parser, pm_context_t context, uint16_t depth) { context_push(parser, context); while (true) { - pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, false, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1)); + pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, PM_PARSE_ACCEPTS_COMMAND_CALL | PM_PARSE_ACCEPTS_DO_BLOCK, 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 @@ -13282,6 +13149,7 @@ parse_statements(pm_parser_t *parser, pm_context_t context, uint16_t depth) { } context_pop(parser); + bool last_value = true; switch (context) { case PM_CONTEXT_BEGIN_ENSURE: @@ -13302,11 +13170,11 @@ parse_statements(pm_parser_t *parser, pm_context_t context, uint16_t depth) { */ 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, parser->start_line, literals, node, true); + const pm_node_t *duplicated = pm_static_literals_add(&parser->line_offsets, parser->start, parser->start_line, literals, node, true); if (duplicated != NULL) { pm_buffer_t buffer = { 0 }; - pm_static_literal_inspect(&buffer, &parser->newline_list, parser->start, parser->start_line, parser->encoding->name, duplicated); + pm_static_literal_inspect(&buffer, &parser->line_offsets, parser->start, parser->start_line, parser->encoding->name, duplicated); pm_diagnostic_list_append_format( &parser->warning_list, @@ -13315,7 +13183,7 @@ pm_hash_key_static_literals_add(pm_parser_t *parser, pm_static_literals_t *liter PM_WARN_DUPLICATED_HASH_KEY, (int) pm_buffer_length(&buffer), pm_buffer_value(&buffer), - pm_newline_list_line_column(&parser->newline_list, PM_NODE_START(node), parser->start_line).line + pm_line_offset_list_line_column(&parser->line_offsets, PM_NODE_START(node), parser->start_line).line ); pm_buffer_free(&buffer); @@ -13330,14 +13198,14 @@ static void pm_when_clause_static_literals_add(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) { pm_node_t *previous; - if ((previous = pm_static_literals_add(&parser->newline_list, parser->start, parser->start_line, literals, node, false)) != NULL) { + if ((previous = pm_static_literals_add(&parser->line_offsets, parser->start, parser->start_line, literals, node, false)) != NULL) { pm_diagnostic_list_append_format( &parser->warning_list, PM_NODE_START(node), PM_NODE_LENGTH(node), PM_WARN_DUPLICATED_WHEN_CLAUSE, - pm_newline_list_line_column(&parser->newline_list, PM_NODE_START(node), parser->start_line).line, - pm_newline_list_line_column(&parser->newline_list, PM_NODE_START(previous), parser->start_line).line + pm_line_offset_list_line_column(&parser->line_offsets, PM_NODE_START(node), parser->start_line).line, + pm_line_offset_list_line_column(&parser->line_offsets, PM_NODE_START(previous), parser->start_line).line ); } } @@ -13365,9 +13233,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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH, (uint16_t) (depth + 1)); + value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_PARSE_ACCEPTS_DO_BLOCK, 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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH, (uint16_t) (depth + 1)); + value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH, (uint16_t) (depth + 1)); } else { pm_parser_scope_forwarding_keywords_check(parser, &operator); } @@ -13386,7 +13254,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, false, PM_ERR_HASH_EXPRESSION_AFTER_LABEL, (uint16_t) (depth + 1)); + value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_PARSE_ACCEPTS_DO_BLOCK, 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 }; @@ -13416,7 +13284,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, true, PM_ERR_HASH_KEY, (uint16_t) (depth + 1)); + pm_node_t *key = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_PARSE_ACCEPTS_DO_BLOCK | PM_PARSE_ACCEPTS_LABEL, PM_ERR_HASH_KEY, (uint16_t) (depth + 1)); // Hash keys that are strings are automatically frozen. We will // mark that here. @@ -13432,16 +13300,16 @@ 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, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); + pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); element = UP(pm_assoc_node_create(parser, key, NTOK2PTR(operator), value)); break; } } if (PM_NODE_TYPE_P(node, PM_HASH_NODE)) { - pm_hash_node_elements_append((pm_hash_node_t *) node, element); + pm_hash_node_elements_append(parser->arena, (pm_hash_node_t *) node, element); } else { - pm_keyword_hash_node_elements_append((pm_keyword_hash_node_t *) node, element); + pm_keyword_hash_node_elements_append(parser->arena, (pm_keyword_hash_node_t *) node, element); } // If there's no comma after the element, then we're done. @@ -13495,14 +13363,14 @@ parse_arguments_append(pm_parser_t *parser, pm_arguments_t *arguments, pm_node_t arguments->arguments = pm_arguments_node_create(parser); } - pm_arguments_node_arguments_append(arguments->arguments, argument); + pm_arguments_node_arguments_append(parser->arena, arguments->arguments, argument); } /** * 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, uint16_t depth) { +parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_forwarding, pm_token_type_t terminator, uint8_t flags, 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 @@ -13542,9 +13410,9 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for parse_arguments_append(parser, arguments, argument); - pm_node_flags_t flags = PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS; - if (contains_keyword_splat) flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT; - pm_node_flag_set(UP(arguments->arguments), flags); + pm_node_flags_t node_flags = PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS; + if (contains_keyword_splat) node_flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT; + pm_node_flag_set(UP(arguments->arguments), node_flags); pm_static_literals_free(&hash_keys); parsed_bare_hash = true; @@ -13557,7 +13425,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, false, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1)); + expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1)); } else { pm_parser_scope_forwarding_block_check(parser, &operator); } @@ -13587,7 +13455,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for pm_parser_err_previous(parser, PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT); } } else { - pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT, (uint16_t) (depth + 1)); + pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT, (uint16_t) (depth + 1)); if (parsed_bare_hash) { pm_parser_err(parser, PM_TOKEN_START(parser, &operator), PM_NODE_END(expression) - PM_TOKEN_START(parser, &operator), PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT); @@ -13608,7 +13476,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for // 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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_RANGE, flags & PM_PARSE_ACCEPTS_DO_BLOCK, 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 @@ -13637,7 +13505,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for PRISM_FALLTHROUGH default: { if (argument == NULL) { - argument = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, !parsed_first_argument, true, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1)); + argument = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (!parsed_first_argument ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0u) | PM_PARSE_ACCEPTS_LABEL, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1)); } bool contains_keywords = false; @@ -13661,10 +13529,10 @@ 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, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); + pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); argument = UP(pm_assoc_node_create(parser, argument, NTOK2PTR(operator), value)); - pm_keyword_hash_node_elements_append(bare_hash, argument); + pm_keyword_hash_node_elements_append(parser->arena, bare_hash, argument); argument = UP(bare_hash); // Then parse more if we have a comma @@ -13681,10 +13549,10 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for parse_arguments_append(parser, arguments, argument); - pm_node_flags_t flags = 0; - if (contains_keywords) flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS; - if (contains_keyword_splat) flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT; - pm_node_flag_set(UP(arguments->arguments), flags); + pm_node_flags_t node_flags = 0; + if (contains_keywords) node_flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS; + if (contains_keyword_splat) node_flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT; + pm_node_flag_set(UP(arguments->arguments), node_flags); break; } @@ -13875,6 +13743,43 @@ update_parameter_state(pm_parser_t *parser, pm_token_t *token, pm_parameters_ord return true; } +static inline void +parse_parameters_handle_trailing_comma( + pm_parser_t *parser, + pm_parameters_node_t *params, + pm_parameters_order_t order, + bool in_block, + bool allows_trailing_comma +) { + if (!allows_trailing_comma) { + pm_parser_err_previous(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA); + return; + } + + if (in_block) { + if (order >= PM_PARAMETERS_ORDER_NAMED) { + // foo do |bar,|; end + pm_node_t *param = UP(pm_implicit_rest_node_create(parser, &parser->previous)); + + if (params->rest == NULL) { + pm_parameters_node_rest_set(params, param); + } else { + pm_parser_err_node(parser, UP(param), PM_ERR_PARAMETER_SPLAT_MULTI); + pm_parameters_node_posts_append(parser->arena, params, UP(param)); + } + } else { + // foo do |*bar,|; end + pm_parser_err_previous(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA); + } + } else { + // https://bugs.ruby-lang.org/issues/19107 + // Allow `def foo(bar,); end`, `def foo(*bar,); end`, etc. but not `def foo(...,); end` + if (parser->version < PM_OPTIONS_VERSION_CRUBY_4_1 || order == PM_PARAMETERS_ORDER_NOTHING_AFTER) { + pm_parser_err_previous(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA); + } + } +} + /** * Parse a list of parameters on a method definition. */ @@ -13887,6 +13792,7 @@ parse_parameters( bool allows_forwarding_parameters, bool accepts_blocks_in_defaults, bool in_block, + pm_diagnostic_id_t diag_id_forwarding, uint16_t depth ) { pm_do_loop_stack_push(parser, false); @@ -13903,9 +13809,9 @@ parse_parameters( pm_node_t *param = UP(parse_required_destructured_parameter(parser)); if (order > PM_PARAMETERS_ORDER_AFTER_OPTIONAL) { - pm_parameters_node_requireds_append(params, param); + pm_parameters_node_requireds_append(parser->arena, params, param); } else { - pm_parameters_node_posts_append(params, param); + pm_parameters_node_posts_append(parser->arena, params, param); } break; } @@ -13915,33 +13821,40 @@ parse_parameters( parser_lex(parser); pm_token_t operator = parser->previous; - pm_token_t name = { 0 }; + pm_node_t *param; - bool repeated = false; - if (accept1(parser, PM_TOKEN_IDENTIFIER)) { - name = parser->previous; - repeated = pm_parser_parameter_name_check(parser, &name); - pm_parser_local_add_token(parser, &name, 1); + if (parser->version >= PM_OPTIONS_VERSION_CRUBY_4_1 && accept1(parser, PM_TOKEN_KEYWORD_NIL)) { + param = (pm_node_t *) pm_no_block_parameter_node_create(parser, &operator, &parser->previous); } else { - parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_BLOCK; + pm_token_t name = {0}; + + bool repeated = false; + if (accept1(parser, PM_TOKEN_IDENTIFIER)) { + name = parser->previous; + repeated = pm_parser_parameter_name_check(parser, &name); + pm_parser_local_add_token(parser, &name, 1); + } else { + parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_BLOCK; + } + + param = (pm_node_t *) pm_block_parameter_node_create(parser, NTOK2PTR(name), &operator); + if (repeated) { + pm_node_flag_set_repeated_parameter(param); + } } - pm_block_parameter_node_t *param = pm_block_parameter_node_create(parser, NTOK2PTR(name), &operator); - if (repeated) { - pm_node_flag_set_repeated_parameter(UP(param)); - } if (params->block == NULL) { pm_parameters_node_block_set(params, param); } else { - pm_parser_err_node(parser, UP(param), PM_ERR_PARAMETER_BLOCK_MULTI); - pm_parameters_node_posts_append(params, UP(param)); + pm_parser_err_node(parser, param, PM_ERR_PARAMETER_BLOCK_MULTI); + pm_parameters_node_posts_append(parser->arena, params, param); } break; } case PM_TOKEN_UDOT_DOT_DOT: { if (!allows_forwarding_parameters) { - pm_parser_err_current(parser, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES); + pm_parser_err_current(parser, diag_id_forwarding); } bool succeeded = update_parameter_state(parser, &parser->current, &order); @@ -13954,7 +13867,7 @@ parse_parameters( // 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_parameters_node_posts_append(parser->arena, params, keyword_rest); if (succeeded) pm_parser_err_previous(parser, PM_ERR_PARAMETER_UNEXPECTED_FWD); params->keyword_rest = NULL; } @@ -14007,7 +13920,7 @@ parse_parameters( 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)); + pm_node_t *value = parse_value_expression(parser, binding_power, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_PARAMETER_NO_DEFAULT, (uint16_t) (depth + 1)); if (accepts_blocks_in_defaults) pm_accepts_block_stack_pop(parser); pm_optional_parameter_node_t *param = pm_optional_parameter_node_create(parser, &name, &operator, value); @@ -14015,7 +13928,7 @@ parse_parameters( if (repeated) { pm_node_flag_set_repeated_parameter(UP(param)); } - pm_parameters_node_optionals_append(params, param); + pm_parameters_node_optionals_append(parser->arena, params, param); // If the value of the parameter increased the number of // reads of that parameter, then we need to warn that we @@ -14038,13 +13951,13 @@ parse_parameters( if (repeated) { pm_node_flag_set_repeated_parameter(UP(param)); } - pm_parameters_node_requireds_append(params, UP(param)); + pm_parameters_node_requireds_append(parser->arena, params, UP(param)); } else { pm_required_parameter_node_t *param = pm_required_parameter_node_create(parser, &name); if (repeated) { pm_node_flag_set_repeated_parameter(UP(param)); } - pm_parameters_node_posts_append(params, UP(param)); + pm_parameters_node_posts_append(parser->arena, params, UP(param)); } break; @@ -14080,7 +13993,7 @@ parse_parameters( pm_node_flag_set_repeated_parameter(param); } - pm_parameters_node_keywords_append(params, param); + pm_parameters_node_keywords_append(parser->arena, params, param); break; } case PM_TOKEN_SEMICOLON: @@ -14097,7 +14010,7 @@ parse_parameters( pm_node_flag_set_repeated_parameter(param); } - pm_parameters_node_keywords_append(params, param); + pm_parameters_node_keywords_append(parser->arena, params, param); break; } default: { @@ -14108,7 +14021,7 @@ parse_parameters( 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_KW, (uint16_t) (depth + 1)); + pm_node_t *value = parse_value_expression(parser, binding_power, PM_PARSE_ACCEPTS_DO_BLOCK, 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)) { @@ -14126,7 +14039,7 @@ parse_parameters( } context_pop(parser); - pm_parameters_node_keywords_append(params, param); + pm_parameters_node_keywords_append(parser->arena, 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 @@ -14167,7 +14080,7 @@ parse_parameters( pm_parameters_node_rest_set(params, param); } else { pm_parser_err_node(parser, param, PM_ERR_PARAMETER_SPLAT_MULTI); - pm_parameters_node_posts_append(params, param); + pm_parameters_node_posts_append(parser->arena, params, param); } break; @@ -14209,27 +14122,14 @@ parse_parameters( pm_parameters_node_keyword_rest_set(params, param); } else { pm_parser_err_node(parser, param, PM_ERR_PARAMETER_ASSOC_SPLAT_MULTI); - pm_parameters_node_posts_append(params, param); + pm_parameters_node_posts_append(parser->arena, params, param); } break; } default: if (parser->previous.type == PM_TOKEN_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 = UP(pm_implicit_rest_node_create(parser, &parser->previous)); - - if (params->rest == NULL) { - pm_parameters_node_rest_set(params, param); - } else { - pm_parser_err_node(parser, UP(param), PM_ERR_PARAMETER_SPLAT_MULTI); - pm_parameters_node_posts_append(params, UP(param)); - } - } else { - pm_parser_err_previous(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA); - } + parse_parameters_handle_trailing_comma(parser, params, order, in_block, allows_trailing_comma); } parsing = false; @@ -14262,7 +14162,6 @@ parse_parameters( // If we don't have any parameters, return `NULL` instead of an empty `ParametersNode`. if (PM_NODE_START(params) == PM_NODE_END(params)) { - pm_node_destroy(parser, UP(params)); return NULL; } @@ -14279,13 +14178,13 @@ token_newline_index(const pm_parser_t *parser) { // 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; + return parser->line_offsets.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, PM_TOKEN_START(parser, &parser->current), 0); + return (size_t) pm_line_offset_list_line(&parser->line_offsets, PM_TOKEN_START(parser, &parser->current), 0); } } @@ -14295,7 +14194,7 @@ token_newline_index(const pm_parser_t *parser) { */ 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 *cursor = parser->start + parser->line_offsets.offsets[newline_index]; const uint8_t *end = token->start; // Skip over the BOM if it is present. @@ -14402,7 +14301,7 @@ parse_rescues(pm_parser_t *parser, size_t opening_newline_index, const pm_token_ parser_lex(parser); pm_rescue_node_operator_set(parser, rescue, &parser->previous); - pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_RESCUE_VARIABLE, (uint16_t) (depth + 1)); + pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_RESCUE_VARIABLE, (uint16_t) (depth + 1)); reference = parse_target(parser, reference, false, false); pm_rescue_node_reference_set(rescue, reference); @@ -14421,7 +14320,7 @@ parse_rescues(pm_parser_t *parser, size_t opening_newline_index, const pm_token_ do { 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); + pm_rescue_node_exceptions_append(parser->arena, rescue, expression); // If we hit a newline, then this is the end of the rescue expression. We // can continue on to parse the statements. @@ -14432,7 +14331,7 @@ parse_rescues(pm_parser_t *parser, size_t opening_newline_index, const pm_token_ if (accept1(parser, PM_TOKEN_EQUAL_GREATER)) { pm_rescue_node_operator_set(parser, rescue, &parser->previous); - pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_RESCUE_VARIABLE, (uint16_t) (depth + 1)); + pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_RESCUE_VARIABLE, (uint16_t) (depth + 1)); reference = parse_target(parser, reference, false, false); pm_rescue_node_reference_set(rescue, reference); @@ -14618,6 +14517,7 @@ parse_block_parameters( false, accepts_blocks_in_defaults, true, + is_lambda_literal ? PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_LAMBDA : PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK, (uint16_t) (depth + 1) ); if (!is_lambda_literal) { @@ -14659,7 +14559,7 @@ parse_block_parameters( pm_block_local_variable_node_t *local = pm_block_local_variable_node_create(parser, &parser->previous); if (repeated) pm_node_flag_set_repeated_parameter(UP(local)); - pm_block_parameters_node_append_local(block_parameters, local); + pm_block_parameters_node_append_local(parser->arena, block_parameters, local); } while (accept1(parser, PM_TOKEN_COMMA)); } } @@ -14840,8 +14740,9 @@ parse_block(pm_parser_t *parser, uint16_t depth) { * arguments, or blocks). */ static bool -parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_block, bool accepts_command_call, uint16_t depth) { +parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_block, uint8_t flags, uint16_t depth) { bool found = false; + bool parsed_command_args = false; if (accept1(parser, PM_TOKEN_PARENTHESIS_LEFT)) { found |= true; @@ -14851,7 +14752,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept arguments->closing_loc = TOK2LOC(parser, &parser->previous); } else { pm_accepts_block_stack_push(parser, true); - parse_arguments(parser, arguments, accepts_block, PM_TOKEN_PARENTHESIS_RIGHT, (uint16_t) (depth + 1)); + parse_arguments(parser, arguments, accepts_block, PM_TOKEN_PARENTHESIS_RIGHT, (uint8_t) (flags & ~PM_PARSE_ACCEPTS_DO_BLOCK), (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)); @@ -14862,14 +14763,15 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept pm_accepts_block_stack_pop(parser); arguments->closing_loc = TOK2LOC(parser, &parser->previous); } - } else if (accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR, PM_TOKEN_UAMPERSAND)) && !match1(parser, PM_TOKEN_BRACE_LEFT)) { + } else if ((flags & PM_PARSE_ACCEPTS_COMMAND_CALL) && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR, PM_TOKEN_UAMPERSAND)) && !match1(parser, PM_TOKEN_BRACE_LEFT)) { found |= true; + parsed_command_args = true; pm_accepts_block_stack_push(parser, false); // 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, accepts_block, PM_TOKEN_EOF, (uint16_t) (depth + 1)); + parse_arguments(parser, arguments, accepts_block, PM_TOKEN_EOF, flags, (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 @@ -14894,6 +14796,9 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept } else if (pm_accepts_block_stack_p(parser) && accept1(parser, PM_TOKEN_KEYWORD_DO)) { found |= true; block = parse_block(parser, (uint16_t) (depth + 1)); + } else if (parsed_command_args && pm_accepts_block_stack_p(parser) && (flags & PM_PARSE_ACCEPTS_DO_BLOCK) && accept1(parser, PM_TOKEN_KEYWORD_DO_BLOCK)) { + found |= true; + block = parse_block(parser, (uint16_t) (depth + 1)); } if (block != NULL) { @@ -14906,7 +14811,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept if (arguments->arguments == NULL) { arguments->arguments = pm_arguments_node_create(parser); } - pm_arguments_node_arguments_append(arguments->arguments, arguments->block); + pm_arguments_node_arguments_append(parser->arena, arguments->arguments, arguments->block); } arguments->block = UP(block); } @@ -15050,7 +14955,7 @@ parse_block_exit(pm_parser_t *parser, pm_node_t *node) { // 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); + pm_node_list_append(parser->arena, parser->current_block_exits, node); return; case PM_CONTEXT_BEGIN_ELSE: case PM_CONTEXT_BEGIN_ENSURE: @@ -15141,7 +15046,7 @@ pop_block_exits(pm_parser_t *parser, pm_node_list_t *previous_block_exits) { // However, they could still become valid in a higher level context if // 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); + pm_node_list_concat(parser->arena, 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 @@ -15155,7 +15060,7 @@ 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, 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, false, error_id, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, binding_power, PM_PARSE_ACCEPTS_COMMAND_CALL | PM_PARSE_ACCEPTS_DO_BLOCK, 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); @@ -15299,8 +15204,6 @@ parse_conditional(pm_parser_t *parser, pm_context_t context, size_t opening_newl } pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return parent; } @@ -15311,7 +15214,7 @@ parse_conditional(pm_parser_t *parser, pm_context_t context, size_t opening_newl #define PM_CASE_KEYWORD PM_TOKEN_KEYWORD___ENCODING__: case PM_TOKEN_KEYWORD___FILE__: case PM_TOKEN_KEYWORD___LINE__: \ case PM_TOKEN_KEYWORD_ALIAS: case PM_TOKEN_KEYWORD_AND: case PM_TOKEN_KEYWORD_BEGIN: case PM_TOKEN_KEYWORD_BEGIN_UPCASE: \ case PM_TOKEN_KEYWORD_BREAK: case PM_TOKEN_KEYWORD_CASE: case PM_TOKEN_KEYWORD_CLASS: case PM_TOKEN_KEYWORD_DEF: \ - case PM_TOKEN_KEYWORD_DEFINED: case PM_TOKEN_KEYWORD_DO: case PM_TOKEN_KEYWORD_DO_LOOP: case PM_TOKEN_KEYWORD_ELSE: \ + case PM_TOKEN_KEYWORD_DEFINED: case PM_TOKEN_KEYWORD_DO: case PM_TOKEN_KEYWORD_DO_BLOCK: case PM_TOKEN_KEYWORD_DO_LOOP: case PM_TOKEN_KEYWORD_ELSE: \ case PM_TOKEN_KEYWORD_ELSIF: case PM_TOKEN_KEYWORD_END: case PM_TOKEN_KEYWORD_END_UPCASE: case PM_TOKEN_KEYWORD_ENSURE: \ case PM_TOKEN_KEYWORD_FALSE: case PM_TOKEN_KEYWORD_FOR: case PM_TOKEN_KEYWORD_IF: case PM_TOKEN_KEYWORD_IN: \ case PM_TOKEN_KEYWORD_MODULE: case PM_TOKEN_KEYWORD_NEXT: case PM_TOKEN_KEYWORD_NIL: case PM_TOKEN_KEYWORD_NOT: \ @@ -15433,7 +15336,7 @@ parse_string_part(pm_parser_t *parser, uint16_t depth) { pm_token_t opening = parser->previous; pm_statements_node_t *statements = NULL; - if (!match1(parser, PM_TOKEN_EMBEXPR_END)) { + if (!match3(parser, PM_TOKEN_EMBEXPR_END, PM_TOKEN_HEREDOC_END, PM_TOKEN_EOF)) { pm_accepts_block_stack_push(parser, true); statements = parse_statements(parser, PM_CONTEXT_EMBEXPR, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); @@ -15615,11 +15518,11 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s } pm_interpolated_symbol_node_t *symbol = pm_interpolated_symbol_node_create(parser, &opening, NULL, &opening); - if (part) pm_interpolated_symbol_node_append(symbol, part); + if (part) pm_interpolated_symbol_node_append(parser->arena, symbol, part); while (!match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) { if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) { - pm_interpolated_symbol_node_append(symbol, part); + pm_interpolated_symbol_node_append(parser->arena, symbol, part); } } @@ -15654,10 +15557,10 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s if (match1(parser, PM_TOKEN_STRING_CONTENT)) { pm_interpolated_symbol_node_t *symbol = pm_interpolated_symbol_node_create(parser, &opening, NULL, &opening); pm_node_t *part = UP(pm_string_node_create_unescaped(parser, NULL, &content, NULL, &unescaped)); - pm_interpolated_symbol_node_append(symbol, part); + pm_interpolated_symbol_node_append(parser->arena, symbol, part); part = UP(pm_string_node_create_unescaped(parser, NULL, &parser->current, NULL, &parser->current_string)); - pm_interpolated_symbol_node_append(symbol, part); + pm_interpolated_symbol_node_append(parser->arena, symbol, part); if (next_state != PM_LEX_STATE_NONE) { lex_state_set(parser, next_state); @@ -15796,12 +15699,12 @@ parse_variable(pm_parser_t *parser) { } pm_node_t *node = UP(pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, 0, false)); - pm_node_list_append(¤t_scope->implicit_parameters, node); + pm_node_list_append(parser->arena, ¤t_scope->implicit_parameters, node); return node; } else if ((parser->version >= PM_OPTIONS_VERSION_CRUBY_3_4) && pm_token_is_it(parser->previous.start, parser->previous.end)) { pm_node_t *node = UP(pm_it_local_variable_read_node_create(parser, &parser->previous)); - pm_node_list_append(¤t_scope->implicit_parameters, node); + pm_node_list_append(parser->arena, ¤t_scope->implicit_parameters, node); return node; } @@ -15857,16 +15760,25 @@ parse_method_definition_name(pm_parser_t *parser) { } static void -parse_heredoc_dedent_string(pm_string_t *string, size_t common_whitespace) { - // Get a reference to the string struct that is being held by the string - // node. This is the value we're going to actually manipulate. - pm_string_ensure_owned(string); +parse_heredoc_dedent_string(pm_arena_t *arena, pm_string_t *string, size_t common_whitespace) { + // Make a writable copy in the arena if the string isn't already writable. + // We keep a mutable pointer to the arena memory so we can memmove into it + // below without casting away const from the string's source field. + uint8_t *writable; + + if (string->type != PM_STRING_OWNED) { + size_t length = pm_string_length(string); + writable = (uint8_t *) pm_arena_memdup(arena, pm_string_source(string), length, PRISM_ALIGNOF(uint8_t)); + pm_string_constant_init(string, (const char *) writable, length); + } else { + writable = (uint8_t *) string->source; + } // Now get the bounds of the existing string. We'll use this as a // destination to move bytes into. We'll also use it for bounds checking // since we don't require that these strings be null terminated. size_t dest_length = pm_string_length(string); - const uint8_t *source_cursor = (uint8_t *) string->source; + const uint8_t *source_cursor = writable; const uint8_t *source_end = source_cursor + dest_length; // We're going to move bytes backward in the string when we get leading @@ -15890,10 +15802,23 @@ parse_heredoc_dedent_string(pm_string_t *string, size_t common_whitespace) { dest_length--; } - memmove((uint8_t *) string->source, source_cursor, (size_t) (source_end - source_cursor)); + memmove(writable, source_cursor, (size_t) (source_end - source_cursor)); string->length = dest_length; } +/** + * If we end up trimming all of the whitespace from a node and it isn't + * part of a line continuation, then we'll drop it from the list entirely. + */ +static inline bool +heredoc_dedent_discard_string_node(pm_parser_t *parser, pm_string_node_t *string_node) { + if (string_node->unescaped.length == 0) { + const uint8_t *cursor = parser->start + PM_LOCATION_START(&string_node->content_loc); + return pm_memchr(cursor, '\\', string_node->content_loc.length, parser->encoding_changed, parser->encoding) == NULL; + } + return false; +} + /** * Take a heredoc node that is indented by a ~ and trim the leading whitespace. */ @@ -15904,8 +15829,7 @@ parse_heredoc_dedent(pm_parser_t *parser, pm_node_list_t *nodes, size_t common_w bool dedent_next = true; // Iterate over all nodes, and trim whitespace accordingly. We're going to - // keep around two indices: a read and a write. If we end up trimming all of - // the whitespace from a node, then we'll drop it from the list entirely. + // keep around two indices: a read and a write. size_t write_index = 0; pm_node_t *node; @@ -15921,11 +15845,10 @@ parse_heredoc_dedent(pm_parser_t *parser, pm_node_list_t *nodes, size_t common_w pm_string_node_t *string_node = ((pm_string_node_t *) node); if (dedent_next) { - parse_heredoc_dedent_string(&string_node->unescaped, common_whitespace); + parse_heredoc_dedent_string(parser->arena, &string_node->unescaped, common_whitespace); } - if (string_node->unescaped.length == 0) { - pm_node_destroy(parser, node); + if (heredoc_dedent_discard_string_node(parser, string_node)) { } else { nodes->nodes[write_index++] = node; } @@ -16014,18 +15937,16 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1 if (match1(parser, PM_TOKEN_STRING_CONTENT)) { pm_node_list_t parts = { 0 }; pm_node_t *part = UP(pm_string_node_create_unescaped(parser, NULL, &content, NULL, &unescaped)); - pm_node_list_append(&parts, part); + pm_node_list_append(parser->arena, &parts, part); do { part = UP(pm_string_node_create_current_string(parser, NULL, &parser->current, NULL)); - pm_node_list_append(&parts, part); + pm_node_list_append(parser->arena, &parts, part); parser_lex(parser); } while (match1(parser, PM_TOKEN_STRING_CONTENT)); expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF); node = UP(pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous)); - - pm_node_list_free(&parts); } else if (accept1(parser, PM_TOKEN_LABEL_END)) { node = UP(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); @@ -16074,11 +15995,11 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1 pm_node_list_t parts = { 0 }; pm_node_t *part = UP(pm_string_node_create_unescaped(parser, NULL, &parser->previous, NULL, &unescaped)); pm_node_flag_set(part, parse_unescaped_encoding(parser)); - pm_node_list_append(&parts, part); + pm_node_list_append(parser->arena, &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); + pm_node_list_append(parser->arena, &parts, part); } } @@ -16092,8 +16013,6 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1 expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM); node = UP(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 @@ -16104,7 +16023,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1 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); + pm_node_list_append(parser->arena, &parts, part); } } @@ -16118,8 +16037,6 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1 expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM); node = UP(pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous)); } - - pm_node_list_free(&parts); } if (current == NULL) { @@ -16150,11 +16067,11 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1 concating = true; pm_interpolated_string_node_t *container = pm_interpolated_string_node_create(parser, NULL, NULL, NULL); - pm_interpolated_string_node_append(container, current); + pm_interpolated_string_node_append(parser->arena, container, current); current = UP(container); } - pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, node); + pm_interpolated_string_node_append(parser->arena, (pm_interpolated_string_node_t *) current, node); } } @@ -16181,7 +16098,7 @@ parse_pattern_capture(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_c if (pm_constant_id_list_includes(captures, capture)) { pm_parser_err(parser, location->start, location->length, PM_ERR_PATTERN_CAPTURE_DUPLICATE); } else { - pm_constant_id_list_append(captures, capture); + pm_constant_id_list_append(parser->arena, captures, capture); } } @@ -16301,7 +16218,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures // attaching its constant. In this case we'll create an array pattern and // attach our constant to it. pm_array_pattern_node_t *pattern_node = pm_array_pattern_node_constant_create(parser, node, &opening, &closing); - pm_array_pattern_node_requireds_append(pattern_node, inner); + pm_array_pattern_node_requireds_append(parser->arena, pattern_node, inner); return UP(pattern_node); } @@ -16444,7 +16361,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, parser->start_line, keys, node, true) != NULL) { + if (pm_static_literals_add(&parser->line_offsets, parser->start, parser->start_line, keys, node, true) != NULL) { pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_KEY_DUPLICATE); } } @@ -16479,7 +16396,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node } pm_node_t *assoc = UP(pm_assoc_node_create(parser, first_node, NULL, value)); - pm_node_list_append(&assocs, assoc); + pm_node_list_append(parser->arena, &assocs, assoc); break; } } @@ -16494,7 +16411,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node pm_node_t *value = UP(pm_missing_node_create(parser, PM_NODE_START(first_node), PM_NODE_LENGTH(first_node))); pm_node_t *assoc = UP(pm_assoc_node_create(parser, first_node, NULL, value)); - pm_node_list_append(&assocs, assoc); + pm_node_list_append(parser->arena, &assocs, assoc); break; } } @@ -16518,7 +16435,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node rest = assoc; } else { pm_parser_err_node(parser, assoc, PM_ERR_PATTERN_EXPRESSION_AFTER_REST); - pm_node_list_append(&assocs, assoc); + pm_node_list_append(parser->arena, &assocs, assoc); } } else { pm_node_t *key; @@ -16559,12 +16476,12 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node pm_parser_err_node(parser, assoc, PM_ERR_PATTERN_EXPRESSION_AFTER_REST); } - pm_node_list_append(&assocs, assoc); + pm_node_list_append(parser->arena, &assocs, assoc); } } pm_hash_pattern_node_t *node = pm_hash_pattern_node_node_list_create(parser, &assocs, rest); - xfree(assocs.nodes); + // assocs.nodes is arena-allocated; no explicit free needed. pm_static_literals_free(&keys); return node; @@ -16646,7 +16563,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm } pm_array_pattern_node_t *node = pm_array_pattern_node_empty_create(parser, &opening, &closing); - pm_array_pattern_node_requireds_append(node, inner); + pm_array_pattern_node_requireds_append(parser->arena, node, inner); return UP(node); } case PM_TOKEN_BRACE_LEFT: { @@ -16673,7 +16590,7 @@ 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, true, PM_ERR_PATTERN_HASH_KEY_LABEL, (uint16_t) (depth + 1)); + first_node = parse_expression(parser, PM_BINDING_POWER_MAX, PM_PARSE_ACCEPTS_DO_BLOCK | PM_PARSE_ACCEPTS_LABEL, 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)); @@ -16709,7 +16626,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, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE, (uint16_t) (depth + 1)); return UP(pm_range_node_create(parser, NULL, &operator, right)); } default: { @@ -16720,7 +16637,7 @@ 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, true, diag_id, (uint16_t) (depth + 1)); + pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_MAX, PM_PARSE_ACCEPTS_LABEL | PM_PARSE_ACCEPTS_DO_BLOCK, 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(parser, node)) return node; @@ -16731,7 +16648,6 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm pm_missing_node_t *missing_node = pm_missing_node_create(parser, PM_NODE_START(node), PM_NODE_LENGTH(node)); pm_node_unreference(parser, node); - pm_node_destroy(parser, node); return UP(missing_node); } @@ -16744,7 +16660,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, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE, (uint16_t) (depth + 1)); return UP(pm_range_node_create(parser, node, &operator, right)); } default: @@ -16809,7 +16725,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, false, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN, (uint16_t) (depth + 1)); + pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_PARSE_ACCEPTS_DO_BLOCK | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN, (uint16_t) (depth + 1)); parser->pattern_matching_newlines = previous_pattern_matching_newlines; accept1(parser, PM_TOKEN_NEWLINE); @@ -17043,14 +16959,14 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag // 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_append(parser->arena, &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 (match7(parser, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_SEMICOLON, PM_TOKEN_KEYWORD_AND, PM_TOKEN_KEYWORD_OR)) { node = UP(pm_implicit_rest_node_create(parser, &parser->previous)); - pm_node_list_append(&nodes, node); + pm_node_list_append(parser->arena, &nodes, node); trailing_rest = true; break; } @@ -17070,7 +16986,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag node = parse_pattern_primitives(parser, captures, NULL, PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1)); } - pm_node_list_append(&nodes, node); + pm_node_list_append(parser->arena, &nodes, node); } // If the first pattern and the last pattern are rest patterns, then we @@ -17091,7 +17007,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag } } - xfree(nodes.nodes); + // nodes.nodes is arena-allocated; no explicit free needed. } 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. @@ -17363,67 +17279,103 @@ 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. + * Determine if a given call node looks like a "command", which means it has + * arguments but does not have parentheses. */ -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; +static inline bool +pm_call_node_command_p(const pm_call_node_t *node) { + return ( + (node->opening_loc.length == 0) && + (node->block == NULL || PM_NODE_TYPE_P(node->block, PM_BLOCK_ARGUMENT_NODE)) && + (node->arguments != NULL || node->block != NULL) + ); +} /** - * This callback is called when the regular expression parser encounters a - * syntax error. + * Returns true if the given node is a command-style call (a method call without + * parentheses that has arguments), excluding operator calls (e.g., a + b) which + * satisfy the same structural criteria but are not commands. */ -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_token_t location; +static bool +pm_command_call_value_p(const pm_node_t *node) { + switch (PM_NODE_TYPE(node)) { + case PM_CALL_NODE: { + const pm_call_node_t *call = (const pm_call_node_t *) node; - if (callback_data->shared) { - location = (pm_token_t) { .type = 0, .start = start, .end = end }; - } else { - location = (pm_token_t) { .type = 0, .start = callback_data->start, .end = callback_data->end }; - } + // Command-style calls (e.g., foo bar, obj.foo bar). + // Attribute writes (e.g., a.b = 1) are not commands. + if (pm_call_node_command_p(call) && !PM_NODE_FLAG_P(node, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE) && (call->receiver == NULL || call->call_operator_loc.length > 0)) { + return true; + } - PM_PARSER_ERR_FORMAT(callback_data->parser, PM_TOKEN_START(callback_data->parser, &location), PM_TOKEN_LENGTH(&location), PM_ERR_REGEXP_PARSE_ERROR, message); + // A `!` or `not` prefix wrapping a command call (e.g., + // `!foo bar`, `not foo bar`) is also a command-call value. + if (call->receiver != NULL && call->arguments == NULL && call->opening_loc.length == 0 && call->call_operator_loc.length == 0) { + return pm_command_call_value_p(call->receiver); + } + + return false; + } + case PM_SUPER_NODE: { + const pm_super_node_t *cast = (const pm_super_node_t *) node; + return cast->lparen_loc.length == 0 && (cast->arguments != NULL || cast->block != NULL); + } + case PM_YIELD_NODE: { + const pm_yield_node_t *cast = (const pm_yield_node_t *) node; + return cast->lparen_loc.length == 0 && cast->arguments != NULL; + } + case PM_RESCUE_MODIFIER_NODE: + return pm_command_call_value_p(((const pm_rescue_modifier_node_t *) node)->expression); + case PM_DEF_NODE: { + const pm_def_node_t *cast = (const pm_def_node_t *) node; + if (cast->equal_loc.length > 0 && cast->body != NULL) { + const pm_node_t *body = cast->body; + if (PM_NODE_TYPE_P(body, PM_STATEMENTS_NODE)) { + body = ((const pm_statements_node_t *) body)->body.nodes[((const pm_statements_node_t *) body)->body.size - 1]; + } + return pm_command_call_value_p(body); + } + return false; + } + default: + return false; + } } /** - * Parse the errors for the regular expression and add them to the parser. + * Returns true if the given node is a block call: a command + * with a do-block, or any call chained (via `.`, `::`, `&.`) from such a node. + * Block calls can only be followed by call chaining, composition (and/or), and + * modifier operators. */ -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 = parser->start + PM_NODE_START(node), - .end = parser->start + PM_NODE_END(node), - .shared = unescaped->type == PM_STRING_SHARED - }; +static bool +pm_block_call_p(const pm_node_t *node) { + while (PM_NODE_TYPE_P(node, PM_CALL_NODE)) { + const pm_call_node_t *call = (const pm_call_node_t *) node; + if (call->opening_loc.length > 0) return false; - 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); + // Root: command with do-block (e.g., `foo bar do end`). + if (call->arguments != NULL && call->block != NULL && PM_NODE_TYPE_P(call->block, PM_BLOCK_NODE)) { + return true; + } + + // Walk up the receiver chain (e.g., `foo bar do end.baz`). + if (call->call_operator_loc.length > 0 && call->receiver != NULL) { + node = call->receiver; + continue; + } + + return false; + } + + return false; } /** * 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, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth) { +parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth) { switch (parser->current.type) { case PM_TOKEN_BRACKET_LEFT_ARRAY: { parser_lex(parser); @@ -17472,7 +17424,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, false, PM_ERR_ARRAY_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); + expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_ARRAY_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); } element = UP(pm_splat_node_create(parser, &operator, expression)); @@ -17484,14 +17436,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b element = UP(pm_keyword_hash_node_create(parser)); 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)) { + if (!match8(parser, PM_TOKEN_EOF, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_KEYWORD_DO_BLOCK, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_KEYWORD_DO, PM_TOKEN_PARENTHESIS_RIGHT)) { 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, true, PM_ERR_ARRAY_EXPRESSION, (uint16_t) (depth + 1)); + element = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_LABEL, PM_ERR_ARRAY_EXPRESSION, (uint16_t) (depth + 1)); if (pm_symbol_node_label_p(parser, element) || accept1(parser, PM_TOKEN_EQUAL_GREATER)) { if (parsed_bare_hash) { @@ -17507,9 +17459,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b operator = parser->previous; } - 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 *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); pm_node_t *assoc = UP(pm_assoc_node_create(parser, element, NTOK2PTR(operator), value)); - pm_keyword_hash_node_elements_append(hash, assoc); + pm_keyword_hash_node_elements_append(parser->arena, hash, assoc); element = UP(hash); if (accept1(parser, PM_TOKEN_COMMA) && !match1(parser, PM_TOKEN_BRACKET_RIGHT)) { @@ -17521,7 +17473,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } } - pm_array_node_elements_append(array, element); + pm_array_node_elements_append(parser->arena, array, element); if (PM_NODE_TYPE_P(element, PM_MISSING_NODE)) break; } @@ -17541,7 +17493,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b case PM_TOKEN_PARENTHESIS_LEFT: case PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES: { pm_token_t opening = parser->current; - pm_node_flags_t flags = 0; + pm_node_flags_t paren_flags = 0; pm_node_list_t current_block_exits = { 0 }; pm_node_list_t *previous_block_exits = push_block_exits(parser, ¤t_block_exits); @@ -17549,7 +17501,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); while (true) { if (accept1(parser, PM_TOKEN_SEMICOLON)) { - flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; + paren_flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; } else if (!accept1(parser, PM_TOKEN_NEWLINE)) { break; } @@ -17559,18 +17511,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // we have an empty parentheses node, and we can immediately return. if (match2(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_EOF)) { expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN); - pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - - return UP(pm_parentheses_node_create(parser, &opening, NULL, &parser->previous, flags)); + return UP(pm_parentheses_node_create(parser, &opening, NULL, &parser->previous, paren_flags)); } // Otherwise, we're going to parse the first statement in the list // 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, false, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1)); + pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_STATEMENT, PM_PARSE_ACCEPTS_COMMAND_CALL | PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1)); context_pop(parser); // Determine if this statement is followed by a terminator. In the @@ -17580,7 +17529,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (accept1(parser, PM_TOKEN_SEMICOLON)) { terminator_found = true; - flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; + paren_flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; } else if (accept1(parser, PM_TOKEN_NEWLINE)) { terminator_found = true; } @@ -17588,7 +17537,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (terminator_found) { while (true) { if (accept1(parser, PM_TOKEN_SEMICOLON)) { - flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; + paren_flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; } else if (!accept1(parser, PM_TOKEN_NEWLINE)) { break; } @@ -17605,9 +17554,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_accepts_block_stack_pop(parser); - pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); if (PM_NODE_TYPE_P(statement, PM_MULTI_TARGET_NODE) || PM_NODE_TYPE_P(statement, PM_SPLAT_NODE)) { // If we have a single statement and are ending on a right @@ -17661,14 +17608,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_statements_node_t *statements = pm_statements_node_create(parser); pm_statements_node_body_append(parser, statements, statement, true); - return UP(pm_parentheses_node_create(parser, &opening, UP(statements), &parser->previous, flags)); + return UP(pm_parentheses_node_create(parser, &opening, UP(statements), &parser->previous, paren_flags)); } // If we have more than one statement in the set of parentheses, // then we are going to parse all of them as a list of statements. // We'll do that here. context_push(parser, PM_CONTEXT_PARENS); - flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; + paren_flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; pm_statements_node_t *statements = pm_statements_node_create(parser); pm_statements_node_body_append(parser, statements, statement, true); @@ -17681,7 +17628,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // Parse each statement within the parentheses. while (true) { - pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, false, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1)); + pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, PM_PARSE_ACCEPTS_COMMAND_CALL | PM_PARSE_ACCEPTS_DO_BLOCK, 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 @@ -17743,10 +17690,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - pm_void_statements_check(parser, statements, true); - return UP(pm_parentheses_node_create(parser, &opening, UP(statements), &parser->previous, flags)); + return UP(pm_parentheses_node_create(parser, &opening, UP(statements), &parser->previous, paren_flags)); } case PM_TOKEN_BRACE_LEFT: { // If we were passed a current_hash_keys via the parser, then that @@ -17831,12 +17776,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // fact a method call, not a constant read. if ( match1(parser, PM_TOKEN_PARENTHESIS_LEFT) || - (accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) || + ((flags & PM_PARSE_ACCEPTS_COMMAND_CALL) && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) || (pm_accepts_block_stack_p(parser) && match1(parser, PM_TOKEN_KEYWORD_DO)) || match1(parser, PM_TOKEN_BRACE_LEFT) ) { pm_arguments_t arguments = { 0 }; - parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1)); + parse_arguments_list(parser, &arguments, true, flags, (uint16_t) (depth + 1)); return UP(pm_call_node_fcall_create(parser, &constant, &arguments)); } @@ -17868,7 +17813,7 @@ 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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, pm_binding_powers[operator.type].left, flags & PM_PARSE_ACCEPTS_DO_BLOCK, 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 @@ -17936,7 +17881,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, (uint16_t) (depth + 1))) { + if (parse_arguments_list(parser, &arguments, true, flags, (uint16_t) (depth + 1))) { // Since we found arguments, we need to turn off the // variable call bit in the flags. pm_node_flag_unset(UP(call), PM_CALL_NODE_FLAGS_VARIABLE_CALL); @@ -17958,12 +17903,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // can still be a method call if it is followed by arguments or // a block, so we need to check for that here. if ( - (accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) || + ((flags & PM_PARSE_ACCEPTS_COMMAND_CALL) && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) || (pm_accepts_block_stack_p(parser) && match1(parser, PM_TOKEN_KEYWORD_DO)) || match1(parser, PM_TOKEN_BRACE_LEFT) ) { pm_arguments_t arguments = { 0 }; - parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1)); + parse_arguments_list(parser, &arguments, true, flags, (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)) { @@ -17986,7 +17931,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } } - pm_node_destroy(parser, node); return UP(fcall); } } @@ -18051,7 +17995,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } if (lex_mode.indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) { - parse_heredoc_dedent_string(&cast->unescaped, common_whitespace); + parse_heredoc_dedent_string(parser->arena, &cast->unescaped, common_whitespace); } node = UP(cast); @@ -18061,11 +18005,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // so we'll need to create an interpolated string node to hold // them all. pm_node_list_t parts = { 0 }; - pm_node_list_append(&parts, part); + pm_node_list_append(parser->arena, &parts, part); while (!match2(parser, PM_TOKEN_HEREDOC_END, PM_TOKEN_EOF)) { if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) { - pm_node_list_append(&parts, part); + pm_node_list_append(parser->arena, &parts, part); } } @@ -18082,7 +18026,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b node = UP(cast); } else { 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.ident_start, lex_mode.ident_length); pm_interpolated_string_node_closing_set(parser, cast, &parser->previous); @@ -18204,17 +18147,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, false, PM_ERR_CASE_EXPRESSION_AFTER_CASE, (uint16_t) (depth + 1)); + predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CASE_EXPRESSION_AFTER_CASE, (uint16_t) (depth + 1)); while (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)); } 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); - pm_parser_err_token(parser, &case_keyword, PM_ERR_CASE_MISSING_CONDITIONS); return UP(pm_case_node_create(parser, &case_keyword, predicate, &parser->previous)); } @@ -18240,15 +18180,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b 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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); + pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, 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, UP(splat_node)); + pm_when_node_conditions_append(parser->arena, when_node, UP(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, false, PM_ERR_CASE_EXPRESSION_AFTER_WHEN, (uint16_t) (depth + 1)); - pm_when_node_conditions_append(when_node, condition); + pm_node_t *condition = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_CASE_EXPRESSION_AFTER_WHEN, (uint16_t) (depth + 1)); + pm_when_node_conditions_append(parser->arena, when_node, condition); // If we found a missing node, then this is a syntax // error and we should stop looping. @@ -18282,7 +18222,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } } - pm_case_node_condition_append(case_node, UP(when_node)); + pm_case_node_condition_append(parser->arena, case_node, UP(when_node)); } // If we didn't parse any conditions (in or when) then we need @@ -18321,18 +18261,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b 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); // Since we're in the top-level of the case-in node we need // to check for guard clauses in the form of `if` or // `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, false, PM_ERR_CONDITIONAL_IF_PREDICATE, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_IF_PREDICATE, (uint16_t) (depth + 1)); pattern = UP(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, false, PM_ERR_CONDITIONAL_UNLESS_PREDICATE, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_UNLESS_PREDICATE, (uint16_t) (depth + 1)); pattern = UP(pm_unless_node_modifier_create(parser, pattern, &keyword, predicate)); } @@ -18361,7 +18300,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // Now that we have the full pattern and statements, we can // create the node and attach it to the case node. pm_node_t *condition = UP(pm_in_node_create(parser, pattern, statements, &in_keyword, NTOK2PTR(then_keyword))); - pm_case_match_node_condition_append(case_node, condition); + pm_case_match_node_condition_append(parser->arena, case_node, condition); } // If we didn't parse any conditions (in or when) then we need @@ -18401,8 +18340,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return node; } case PM_TOKEN_KEYWORD_BEGIN: { @@ -18429,10 +18366,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b PM_NODE_LENGTH_SET_TOKEN(parser, begin_node, &parser->previous); pm_begin_node_end_keyword_set(parser, begin_node, &parser->previous); - pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return UP(begin_node); } case PM_TOKEN_KEYWORD_BEGIN_UPCASE: { @@ -18457,8 +18391,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } flush_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return UP(pm_pre_execution_node_create(parser, &keyword, &opening, statements, &parser->previous)); } case PM_TOKEN_KEYWORD_BREAK: @@ -18477,10 +18409,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (binding_power == PM_BINDING_POWER_UNSET || binding_power >= PM_BINDING_POWER_RANGE) { pm_token_t next = parser->current; - parse_arguments(parser, &arguments, false, PM_TOKEN_EOF, (uint16_t) (depth + 1)); + parse_arguments(parser, &arguments, false, PM_TOKEN_EOF, flags, (uint16_t) (depth + 1)); // Reject `foo && return bar`. - if (!accepts_command_call && arguments.arguments != NULL) { + if (!(flags & PM_PARSE_ACCEPTS_COMMAND_CALL) && arguments.arguments != NULL) { PM_PARSER_ERR_TOKEN_FORMAT(parser, &next, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(next.type)); } } @@ -18512,7 +18444,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, (uint16_t) (depth + 1)); + parse_arguments_list(parser, &arguments, true, flags, (uint16_t) (depth + 1)); if ( arguments.opening_loc.length == 0 && @@ -18529,7 +18461,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, (uint16_t) (depth + 1)); + parse_arguments_list(parser, &arguments, false, flags, (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 @@ -18538,7 +18470,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (arguments.block != NULL) { pm_parser_err_node(parser, arguments.block, PM_ERR_UNEXPECTED_BLOCK_ARGUMENT); pm_node_unreference(parser, arguments.block); - pm_node_destroy(parser, arguments.block); arguments.block = NULL; } @@ -18559,7 +18490,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (accept1(parser, PM_TOKEN_LESS_LESS)) { pm_token_t operator = parser->previous; - 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_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS, (uint16_t) (depth + 1)); pm_parser_scope_push(parser, true); if (!match2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { @@ -18589,12 +18520,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_do_loop_stack_pop(parser); flush_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return UP(pm_singleton_class_node_create(parser, &locals, &class_keyword, &operator, expression, statements, &parser->previous)); } - pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_CLASS_NAME, (uint16_t) (depth + 1)); + pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, flags & PM_PARSE_ACCEPTS_DO_BLOCK, 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); @@ -18610,7 +18539,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, false, PM_ERR_CLASS_SUPERCLASS, (uint16_t) (depth + 1)); + superclass = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CLASS_SUPERCLASS, (uint16_t) (depth + 1)); } else { superclass = NULL; } @@ -18654,8 +18583,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return UP(pm_class_node_create(parser, &locals, &class_keyword, constant_path, &name, NTOK2PTR(inheritance_operator), superclass, statements, &parser->previous)); } case PM_TOKEN_KEYWORD_DEF: { @@ -18788,7 +18715,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_COMPOSITION, true, false, PM_ERR_DEF_RECEIVER, (uint16_t) (depth + 1)); + pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_DEF_RECEIVER, (uint16_t) (depth + 1)); accept1(parser, PM_TOKEN_NEWLINE); expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN); @@ -18826,7 +18753,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, true, false, (uint16_t) (depth + 1)); + // https://bugs.ruby-lang.org/issues/19107 + bool allow_trailing_comma = parser->version >= PM_OPTIONS_VERSION_CRUBY_4_1; + params = parse_parameters( + parser, + PM_BINDING_POWER_DEFINED, + true, + allow_trailing_comma, + true, + true, + false, + PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES, + (uint16_t) (depth + 1) + ); } lex_state_set(parser, PM_LEX_STATE_BEG); @@ -18849,7 +18788,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b lex_state_set(parser, parser->lex_state | PM_LEX_STATE_LABEL); } - params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, false, false, true, true, false, (uint16_t) (depth + 1)); + params = parse_parameters( + parser, + PM_BINDING_POWER_DEFINED, + false, + false, + true, + true, + false, + PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES, + (uint16_t) (depth + 1) + ); // Reject `def * = 1` and similar. We have to specifically check // for them because they create ambiguity with optional arguments. @@ -18888,26 +18837,57 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_do_loop_stack_push(parser, false); statements = UP(pm_statements_node_create(parser)); - bool allow_command_call; + uint8_t allow_flags; if (parser->version >= PM_OPTIONS_VERSION_CRUBY_4_0) { - allow_command_call = accepts_command_call; + allow_flags = flags & PM_PARSE_ACCEPTS_COMMAND_CALL; } else { // Allow `def foo = puts "Hello"` but not `private def foo = puts "Hello"` - allow_command_call = binding_power == PM_BINDING_POWER_ASSIGNMENT || binding_power < PM_BINDING_POWER_COMPOSITION; + allow_flags = (binding_power == PM_BINDING_POWER_ASSIGNMENT || binding_power < PM_BINDING_POWER_COMPOSITION) ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0; } - pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, allow_command_call, false, PM_ERR_DEF_ENDLESS, (uint16_t) (depth + 1)); + // Inside a def body, we push true onto the + // accepts_block_stack so that `do` is lexed as + // PM_TOKEN_KEYWORD_DO (which can only start a block for + // primary-level constructs, not commands). During command + // argument parsing, the stack is pushed to false, causing + // `do` to be lexed as PM_TOKEN_KEYWORD_DO_BLOCK, which + // is not consumed inside the endless def body and instead + // left for the outer context. + pm_accepts_block_stack_push(parser, true); + pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, allow_flags | PM_PARSE_IN_ENDLESS_DEF, PM_ERR_DEF_ENDLESS, (uint16_t) (depth + 1)); + pm_accepts_block_stack_pop(parser); + + // If an unconsumed PM_TOKEN_KEYWORD_DO follows the body, + // it is an error (e.g., `def f = 1 do end`). + // PM_TOKEN_KEYWORD_DO_BLOCK is intentionally not caught + // here — it should bubble up to the outer context (e.g., + // `private def f = puts "Hello" do end` where the block + // attaches to `private`). + if (accept1(parser, PM_TOKEN_KEYWORD_DO)) { + pm_block_node_t *block = parse_block(parser, (uint16_t) (depth + 1)); + pm_parser_err_node(parser, UP(block), PM_ERR_DEF_ENDLESS_DO_BLOCK); + } 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, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, false, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); + + // In the Ruby grammar, the rescue value of an endless + // method command excludes and/or and in/=>. + pm_node_t *value = parse_expression(parser, PM_BINDING_POWER_MATCH + 1, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); statement = UP(pm_rescue_modifier_node_create(parser, statement, &rescue_keyword, value)); } + // A nested endless def whose body is a command call (e.g., + // `def f = def g = foo bar`) is a command assignment and + // cannot appear as a def body. + if (PM_NODE_TYPE_P(statement, PM_DEF_NODE) && pm_command_call_value_p(statement)) { + PM_PARSER_ERR_NODE_FORMAT(parser, statement, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); + } + pm_statements_node_body_append(parser, (pm_statements_node_t *) statements, statement, false); pm_do_loop_stack_pop(parser); context_pop(parser); @@ -18955,7 +18935,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_constant_id_t name_id = pm_parser_constant_id_raw(parser, name.start, parse_operator_symbol_name(&name)); flush_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); return UP(pm_def_node_create( parser, @@ -18991,7 +18970,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b expression = UP(pm_parentheses_node_create(parser, &lparen, NULL, &parser->previous, 0)); lparen = (pm_token_t) { 0 }; } else { - expression = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_DEFINED_EXPRESSION, (uint16_t) (depth + 1)); + expression = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_PARSE_ACCEPTS_COMMAND_CALL | PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_DEFINED_EXPRESSION, (uint16_t) (depth + 1)); if (!parser->recovering) { accept1(parser, PM_TOKEN_NEWLINE); @@ -19000,7 +18979,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } } } else { - expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_DEFINED_EXPRESSION, (uint16_t) (depth + 1)); + expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_DEFINED_EXPRESSION, (uint16_t) (depth + 1)); } context_pop(parser); @@ -19049,12 +19028,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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); + name = parse_expression(parser, PM_BINDING_POWER_INDEX, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); } index = UP(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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1)); + index = parse_expression(parser, PM_BINDING_POWER_INDEX, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1)); } else { pm_parser_err_token(parser, &for_keyword, PM_ERR_FOR_INDEX); index = UP(pm_missing_node_create(parser, PM_TOKEN_START(parser, &for_keyword), PM_TOKEN_LENGTH(&for_keyword))); @@ -19073,7 +19052,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, false, PM_ERR_FOR_COLLECTION, (uint16_t) (depth + 1)); + pm_node_t *collection = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_FOR_COLLECTION, (uint16_t) (depth + 1)); pm_do_loop_stack_pop(parser); pm_token_t do_keyword = { 0 }; @@ -19115,9 +19094,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b 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); } else { - pm_undef_node_append(undef, name); + pm_undef_node_append(parser->arena, undef, name); while (match1(parser, PM_TOKEN_COMMA)) { lex_state_set(parser, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM); @@ -19125,11 +19103,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b name = parse_undef_argument(parser, (uint16_t) (depth + 1)); if (PM_NODE_TYPE_P(name, PM_MISSING_NODE)) { - pm_node_destroy(parser, name); break; } - pm_undef_node_append(undef, name); + pm_undef_node_append(parser->arena, undef, name); } } @@ -19142,10 +19119,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_arguments_t arguments = { 0 }; pm_node_t *receiver = NULL; - // If we do not accept a command call, then we also do not accept a - // not without parentheses. In this case we need to reject this - // syntax. - if (!accepts_command_call && !match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) { + // The `not` keyword without parentheses is only valid in contexts + // where it would be parsed as an expression (i.e., at or below + // the `not` binding power level). In other contexts (e.g., method + // arguments, array elements, assignment right-hand sides), + // parentheses are required: `not(x)`. An exception is made for + // endless def bodies, where `not` is valid as both `arg` and + // `command` (e.g., `def f = not 1`, `def f = not foo bar`). + if (binding_power > PM_BINDING_POWER_NOT && !(flags & PM_PARSE_IN_ENDLESS_DEF) && !match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) { if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES)) { pm_parser_err(parser, PM_TOKEN_END(parser, &parser->previous), 1, PM_ERR_EXPECT_LPAREN_AFTER_NOT_LPAREN); } else { @@ -19165,7 +19146,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b receiver = UP(pm_parentheses_node_create(parser, &lparen, NULL, &parser->previous, 0)); } else { arguments.opening_loc = TOK2LOC(parser, &lparen); - receiver = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); + receiver = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_PARSE_ACCEPTS_COMMAND_CALL | PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); if (!parser->recovering) { accept1(parser, PM_TOKEN_NEWLINE); @@ -19174,7 +19155,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } } } else { - receiver = parse_expression(parser, PM_BINDING_POWER_NOT, true, false, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); + receiver = parse_expression(parser, PM_BINDING_POWER_NOT, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); } return UP(pm_call_node_not_create(parser, receiver, &message, &arguments)); @@ -19193,14 +19174,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t module_keyword = parser->previous; - pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_MODULE_NAME, (uint16_t) (depth + 1)); + pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_MODULE_NAME, (uint16_t) (depth + 1)); pm_token_t name; // If we can recover from a syntax error that occurred while parsing // the name of the module, then we'll handle that here. if (PM_NODE_TYPE_P(constant_path, PM_MISSING_NODE)) { pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); pm_token_t missing = (pm_token_t) { .type = 0, .start = parser->previous.end, .end = parser->previous.end }; return UP(pm_module_node_create(parser, NULL, &module_keyword, constant_path, &missing, NULL, &missing)); @@ -19249,7 +19229,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); return UP(pm_module_node_create(parser, &locals, &module_keyword, constant_path, &name, statements, &parser->previous)); } @@ -19286,7 +19265,7 @@ 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 *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, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_UNTIL_PREDICATE, (uint16_t) (depth + 1)); pm_do_loop_stack_pop(parser); context_pop(parser); @@ -19319,7 +19298,7 @@ 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 *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, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_WHILE_PREDICATE, (uint16_t) (depth + 1)); pm_do_loop_stack_pop(parser); context_pop(parser); @@ -19364,7 +19343,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_SYMBOL_NODE)) { pm_node_t *string = UP(pm_string_node_create_current_string(parser, NULL, &parser->current, NULL)); parser_lex(parser); - pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, string); + pm_interpolated_symbol_node_append(parser->arena, (pm_interpolated_symbol_node_t *) current, string); } else if (PM_NODE_TYPE_P(current, PM_SYMBOL_NODE)) { pm_symbol_node_t *cast = (pm_symbol_node_t *) current; pm_token_t content = { .type = PM_TOKEN_STRING_CONTENT, .start = parser->start + cast->value_loc.start, .end = parser->start + cast->value_loc.start + cast->value_loc.length }; @@ -19373,10 +19352,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, NULL, NULL, NULL); - pm_interpolated_symbol_node_append(interpolated, first_string); - pm_interpolated_symbol_node_append(interpolated, second_string); + pm_interpolated_symbol_node_append(parser->arena, interpolated, first_string); + pm_interpolated_symbol_node_append(parser->arena, interpolated, second_string); - xfree(current); + // current is arena-allocated so no explicit free is needed. current = UP(interpolated); } else { assert(false && "unreachable"); @@ -19384,7 +19363,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } if (current) { - pm_array_node_elements_append(array, current); + pm_array_node_elements_append(parser->arena, array, current); current = NULL; } else { expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_LIST_I_LOWER_ELEMENT); @@ -19420,7 +19399,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } else { // If we hit a separator after we've hit content, then we need to // append that content to the list and reset the current node. - pm_array_node_elements_append(array, current); + pm_array_node_elements_append(parser->arena, array, current); current = NULL; } @@ -19441,7 +19420,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *string = UP(pm_string_node_create_current_string(parser, NULL, &parser->current, NULL)); parser_lex(parser); - pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, string); + pm_interpolated_symbol_node_append(parser->arena, (pm_interpolated_symbol_node_t *) current, string); } else if (PM_NODE_TYPE_P(current, PM_SYMBOL_NODE)) { // If we hit string content and the current node is a symbol node, // then we need to convert the current node into an interpolated @@ -19458,10 +19437,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, NULL, NULL, NULL); - pm_interpolated_symbol_node_append(interpolated, first_string); - pm_interpolated_symbol_node_append(interpolated, second_string); + pm_interpolated_symbol_node_append(parser->arena, interpolated, first_string); + pm_interpolated_symbol_node_append(parser->arena, interpolated, second_string); - xfree(current); + // current is arena-allocated so no explicit free is needed. current = UP(interpolated); } else { assert(false && "unreachable"); @@ -19483,7 +19462,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, NULL, NULL, NULL); current = UP(pm_symbol_node_to_string_node(parser, (pm_symbol_node_t *) current)); - pm_interpolated_symbol_node_append(interpolated, current); + pm_interpolated_symbol_node_append(parser->arena, interpolated, current); PM_NODE_START_SET_NODE(interpolated, current); start_location_set = true; current = UP(interpolated); @@ -19493,7 +19472,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1)); - pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, part); + pm_interpolated_symbol_node_append(parser->arena, (pm_interpolated_symbol_node_t *) current, part); if (!start_location_set) { PM_NODE_START_SET_NODE(current, part); } @@ -19514,7 +19493,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, NULL, NULL, NULL); current = UP(pm_symbol_node_to_string_node(parser, (pm_symbol_node_t *) current)); - pm_interpolated_symbol_node_append(interpolated, current); + pm_interpolated_symbol_node_append(parser->arena, interpolated, current); PM_NODE_START_SET_NODE(interpolated, current); start_location_set = true; current = UP(interpolated); @@ -19526,7 +19505,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1)); - pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, part); + pm_interpolated_symbol_node_append(parser->arena, (pm_interpolated_symbol_node_t *) current, part); if (!start_location_set) { PM_NODE_START_SET_NODE(current, part); } @@ -19541,7 +19520,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // If we have a current node, then we need to append it to the list. if (current) { - pm_array_node_elements_append(array, current); + pm_array_node_elements_append(parser->arena, array, current); } pm_token_t closing = parser->current; @@ -19574,11 +19553,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (current == NULL) { current = string; } else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_STRING_NODE)) { - pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, string); + pm_interpolated_string_node_append(parser->arena, (pm_interpolated_string_node_t *) current, string); } else if (PM_NODE_TYPE_P(current, PM_STRING_NODE)) { pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, NULL, NULL, NULL); - pm_interpolated_string_node_append(interpolated, current); - pm_interpolated_string_node_append(interpolated, string); + pm_interpolated_string_node_append(parser->arena, interpolated, current); + pm_interpolated_string_node_append(parser->arena, interpolated, string); current = UP(interpolated); } else { assert(false && "unreachable"); @@ -19587,7 +19566,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } if (current) { - pm_array_node_elements_append(array, current); + pm_array_node_elements_append(parser->arena, array, current); current = NULL; } else { expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_LIST_W_LOWER_ELEMENT); @@ -19628,7 +19607,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // If we hit a separator after we've hit content, // then we need to append that content to the list // and reset the current node. - pm_array_node_elements_append(array, current); + pm_array_node_elements_append(parser->arena, array, current); current = NULL; } @@ -19650,15 +19629,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // If we hit string content and the current node is // an interpolated string, then we need to append // the string content to the list of child nodes. - pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, string); + pm_interpolated_string_node_append(parser->arena, (pm_interpolated_string_node_t *) current, string); } else if (PM_NODE_TYPE_P(current, PM_STRING_NODE)) { // If we hit string content and the current node is // a string node, then we need to convert the // current node into an interpolated string and add // the string content to the list of child nodes. pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, NULL, NULL, NULL); - pm_interpolated_string_node_append(interpolated, current); - pm_interpolated_string_node_append(interpolated, string); + pm_interpolated_string_node_append(parser->arena, interpolated, current); + pm_interpolated_string_node_append(parser->arena, interpolated, string); current = UP(interpolated); } else { assert(false && "unreachable"); @@ -19679,7 +19658,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // current into an interpolated string and add the // string node to the list of parts. pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, NULL, NULL, NULL); - pm_interpolated_string_node_append(interpolated, current); + pm_interpolated_string_node_append(parser->arena, interpolated, current); current = UP(interpolated); } else { // If we hit an embedded variable and the current @@ -19688,7 +19667,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1)); - pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, part); + pm_interpolated_string_node_append(parser->arena, (pm_interpolated_string_node_t *) current, part); break; } case PM_TOKEN_EMBEXPR_BEGIN: { @@ -19704,7 +19683,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // current into an interpolated string and add the // string node to the list of parts. pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, NULL, NULL, NULL); - pm_interpolated_string_node_append(interpolated, current); + pm_interpolated_string_node_append(parser->arena, interpolated, current); current = UP(interpolated); } else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_STRING_NODE)) { // If we hit an embedded expression and the current @@ -19715,7 +19694,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1)); - pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, part); + pm_interpolated_string_node_append(parser->arena, (pm_interpolated_string_node_t *) current, part); break; } default: @@ -19727,7 +19706,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // If we have a current node, then we need to append it to the list. if (current) { - pm_array_node_elements_append(array, current); + pm_array_node_elements_append(parser->arena, array, current); } pm_token_t closing = parser->current; @@ -19757,10 +19736,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); - pm_node_t *node = UP(pm_regular_expression_node_create(parser, &opening, &content, &parser->previous)); - pm_node_flag_set(node, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING); - - return node; + pm_regular_expression_node_t *node = pm_regular_expression_node_create(parser, &opening, &content, &parser->previous); + pm_node_flag_set(UP(node), pm_regexp_parse(parser, node, NULL, NULL)); + return UP(node); } pm_interpolated_regular_expression_node_t *interpolated; @@ -19772,7 +19750,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // regular expression) or if it's not then it has interpolation. pm_string_t unescaped = parser->current_string; pm_token_t content = parser->current; - bool ascii_only = parser->current_regular_expression_ascii_only; parser_lex(parser); // If we hit an end, then we can create a regular expression @@ -19781,15 +19758,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (accept1(parser, PM_TOKEN_REGEXP_END)) { 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 we're not immediately followed by a =~, then we + // parse and validate now. If it is followed by a =~, + // then it will get parsed in the =~ handler where + // named captures can also be extracted. if (!match1(parser, PM_TOKEN_EQUAL_TILDE)) { - parse_regular_expression_errors(parser, node); + pm_node_flag_set(UP(node), pm_regexp_parse(parser, node, NULL, NULL)); } - pm_node_flag_set(UP(node), parse_and_validate_regular_expression_encoding(parser, &unescaped, ascii_only, FL(node))); return UP(node); } @@ -19805,7 +19781,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_flag_set(part, PM_STRING_FLAGS_FORCED_BINARY_ENCODING); } - pm_interpolated_regular_expression_node_append(interpolated, part); + pm_interpolated_regular_expression_node_append(parser->arena, interpolated, part); } else { // If the first part of the body of the regular expression is not a // string content, then we have interpolation and we need to create an @@ -19818,7 +19794,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *part; while (!match2(parser, PM_TOKEN_REGEXP_END, PM_TOKEN_EOF)) { if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) { - pm_interpolated_regular_expression_node_append(interpolated, part); + pm_interpolated_regular_expression_node_append(parser->arena, interpolated, part); } } @@ -19881,7 +19857,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *part = UP(pm_string_node_create_unescaped(parser, NULL, &parser->previous, NULL, &unescaped)); pm_node_flag_set(part, parse_unescaped_encoding(parser)); - pm_interpolated_xstring_node_append(node, part); + pm_interpolated_xstring_node_append(parser->arena, node, part); } else { // If the first part of the body of the string is not a string // content, then we have interpolation and we need to create an @@ -19892,7 +19868,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, (uint16_t) (depth + 1))) != NULL) { - pm_interpolated_xstring_node_append(node, part); + pm_interpolated_xstring_node_append(parser->arena, node, part); } } @@ -19922,7 +19898,7 @@ 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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); + name = parse_expression(parser, PM_BINDING_POWER_INDEX, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); } pm_node_t *splat = UP(pm_splat_node_create(parser, &operator, name)); @@ -19941,7 +19917,7 @@ 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 *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_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (binding_power < PM_BINDING_POWER_MATCH ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0), 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); @@ -19954,7 +19930,7 @@ 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 *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); + pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "~"); return UP(node); @@ -19966,7 +19942,7 @@ 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 *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); + pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "-@"); return UP(node); @@ -19975,11 +19951,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, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); + pm_node_t *node = parse_expression(parser, pm_binding_powers[parser->previous.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, 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, false, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1)); + pm_node_t *exponent = parse_expression(parser, pm_binding_powers[exponent_operator.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1)); node = UP(pm_call_node_binary_create(parser, node, &exponent_operator, exponent, 0)); node = UP(pm_call_node_unary_create(parser, &operator, node, "-@")); } else { @@ -20058,9 +20034,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b 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 = UP(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)) { @@ -20089,13 +20063,13 @@ 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 *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); + pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "+@"); return UP(node); } case PM_TOKEN_STRING_BEGIN: - return parse_strings(parser, NULL, accepts_label, (uint16_t) (depth + 1)); + return parse_strings(parser, NULL, flags & PM_PARSE_ACCEPTS_LABEL, (uint16_t) (depth + 1)); case PM_TOKEN_SYMBOL_BEGIN: { pm_lex_mode_t lex_mode = *parser->lex_modes.current; parser_lex(parser); @@ -20143,8 +20117,18 @@ 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, 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)); +parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth) { + pm_node_t *value = parse_value_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? (flags & PM_PARSE_ACCEPTS_COMMAND_CALL) : (previous_binding_power < PM_BINDING_POWER_MATCH ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0)), diag_id, (uint16_t) (depth + 1)); + + // Assignments whose value is a command call (e.g., a = b c) can only + // be followed by modifiers (if/unless/while/until/rescue) and not by + // operators with higher binding power. If we find one, emit an error + // and skip the operator and its right-hand side. + if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER && (pm_command_call_value_p(value) || pm_block_call_p(value))) { + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); + parser_lex(parser); + parse_expression(parser, pm_binding_powers[parser->previous.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + } // Contradicting binding powers, the right-hand-side value of the assignment // allows the `rescue` modifier. @@ -20154,7 +20138,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, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, false, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); return UP(pm_rescue_modifier_node_create(parser, value, &rescue, right)); @@ -20212,33 +20196,46 @@ 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, uint16_t depth) { +parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, uint8_t flags, 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_MODIFIER, diag_id, (uint16_t) (depth + 1)); + pm_node_t *value = parse_starred_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? (flags & PM_PARSE_ACCEPTS_COMMAND_CALL) : (previous_binding_power < PM_BINDING_POWER_MODIFIER ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0)), 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))) { + // Block calls (command call + do block, e.g., `foo bar do end`) cannot + // be followed by a comma to form a multi-value RHS because each element + // of a multi-value assignment must be an `arg`, not a `block_call`. + if (previous_binding_power == PM_BINDING_POWER_STATEMENT && !pm_block_call_p(value) && (PM_NODE_TYPE_P(value, PM_SPLAT_NODE) || match1(parser, PM_TOKEN_COMMA))) { single_value = false; pm_array_node_t *array = pm_array_node_create(parser, NULL); - pm_array_node_elements_append(array, value); + pm_array_node_elements_append(parser->arena, array, value); value = UP(array); while (accept1(parser, PM_TOKEN_COMMA)) { 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); + pm_array_node_elements_append(parser->arena, array, element); if (PM_NODE_TYPE_P(element, PM_MISSING_NODE)) break; parse_assignment_value_local(parser, element); } } + // Assignments whose value is a command call (e.g., a = b c) can only + // be followed by modifiers (if/unless/while/until/rescue) and not by + // operators with higher binding power. If we find one, emit an error + // and skip the operator and its right-hand side. + if (single_value && pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER && (pm_command_call_value_p(value) || pm_block_call_p(value))) { + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); + parser_lex(parser); + parse_expression(parser, pm_binding_powers[parser->previous.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + } + // Contradicting binding powers, the right-hand-side value of the assignment // allows the `rescue` modifier. if ((single_value || (binding_power == (PM_BINDING_POWER_MULTI_ASSIGNMENT + 1))) && match1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) { @@ -20258,7 +20255,7 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding } } - pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, accepts_command_call_inner, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (accepts_command_call_inner ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0), PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); return UP(pm_rescue_modifier_node_create(parser, value, &rescue, right)); @@ -20279,43 +20276,16 @@ parse_call_operator_write(pm_parser_t *parser, pm_call_node_t *call_node, const if (call_node->arguments != NULL) { pm_parser_err_token(parser, operator, PM_ERR_OPERATOR_WRITE_ARGUMENTS); pm_node_unreference(parser, UP(call_node->arguments)); - pm_node_destroy(parser, UP(call_node->arguments)); call_node->arguments = NULL; } if (call_node->block != NULL) { pm_parser_err_token(parser, operator, PM_ERR_OPERATOR_WRITE_BLOCK); pm_node_unreference(parser, UP(call_node->block)); - pm_node_destroy(parser, UP(call_node->block)); call_node->block = NULL; } } -/** - * This struct is used to pass information between the regular expression parser - * and the named capture callback. - */ -typedef struct { - /** The parser that is parsing the regular expression. */ - pm_parser_t *parser; - - /** The call node wrapping the regular expression node. */ - pm_call_node_t *call; - - /** The match write node that is being created. */ - pm_match_write_node_t *match; - - /** The list of names that have been parsed. */ - pm_constant_id_list_t names; - - /** - * 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; - static inline const uint8_t * pm_named_capture_escape_hex(pm_buffer_t *unescaped, const uint8_t *cursor, const uint8_t *end) { cursor++; @@ -20368,7 +20338,7 @@ pm_named_capture_escape_unicode(pm_parser_t *parser, pm_buffer_t *unescaped, con if (*cursor != '{') { size_t length = pm_strspn_hexadecimal_digit(cursor, MIN(end - cursor, 4)); - uint32_t value = escape_unicode(parser, cursor, length, error_location); + uint32_t value = escape_unicode(parser, cursor, length, error_location, 0); if (!pm_buffer_append_unicode_codepoint(unescaped, value)) { pm_buffer_append_string(unescaped, (const char *) start, (size_t) ((cursor + length) - start)); @@ -20391,7 +20361,7 @@ pm_named_capture_escape_unicode(pm_parser_t *parser, pm_buffer_t *unescaped, con if (length == 0) { break; } - uint32_t value = escape_unicode(parser, cursor, length, error_location); + uint32_t value = escape_unicode(parser, cursor, length, error_location, 0); (void) pm_buffer_append_unicode_codepoint(unescaped, value); cursor += length; @@ -20441,10 +20411,7 @@ pm_named_capture_escape(pm_parser_t *parser, pm_buffer_t *unescaped, const uint8 * capture group. */ 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; - - pm_parser_t *parser = callback_data->parser; +parse_regular_expression_named_capture(pm_parser_t *parser, const pm_string_t *capture, bool shared, pm_regexp_name_data_t *callback_data) { pm_call_node_t *call = callback_data->call; pm_constant_id_list_t *names = &callback_data->names; @@ -20462,7 +20429,7 @@ parse_regular_expression_named_capture(const pm_string_t *capture, void *data) { // unescaped, which is what we need. const uint8_t *cursor = pm_memchr(source, '\\', length, parser->encoding_changed, parser->encoding); if (PRISM_UNLIKELY(cursor != NULL)) { - pm_named_capture_escape(parser, &unescaped, source, length, cursor, callback_data->shared ? NULL : &call->receiver->location); + pm_named_capture_escape(parser, &unescaped, source, length, cursor, shared ? NULL : &call->receiver->location); source = (const uint8_t *) pm_buffer_value(&unescaped); length = pm_buffer_length(&unescaped); } @@ -20478,7 +20445,7 @@ parse_regular_expression_named_capture(const pm_string_t *capture, void *data) { return; } - if (callback_data->shared) { + if (shared) { // If the unescaped string is a slice of the source, then we can // copy the names directly. The pointers will line up. start = source; @@ -20500,7 +20467,7 @@ parse_regular_expression_named_capture(const pm_string_t *capture, void *data) { // 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); + pm_constant_id_list_append(parser->arena, names, name); int depth; if ((depth = pm_parser_local_depth_constant_id(parser, name)) == -1) { @@ -20525,34 +20492,26 @@ parse_regular_expression_named_capture(const pm_string_t *capture, void *data) { // Next, create the local variable target and add it to the list of // targets for the match. pm_node_t *target = UP(pm_local_variable_target_node_create(parser, &TOK2LOC(parser, &((pm_token_t) { .type = 0, .start = start, .end = end })), name, depth == -1 ? 0 : (uint32_t) depth)); - pm_node_list_append(&callback_data->match->targets, target); + pm_node_list_append(parser->arena, &callback_data->match->targets, target); } pm_buffer_free(&unescaped); } /** - * Potentially change a =~ with a regular expression with named captures into a - * match write node. + * Potentially change a =~ with an interpolated regular expression with named + * captures into a match write node. This is for the interpolated case where + * we have concatenated content rather than a regular expression 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, +parse_interpolated_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t *content, pm_call_node_t *call, bool extended_mode) { + pm_regexp_name_data_t callback_data = { .call = call, + .match = NULL, .names = { 0 }, - .shared = content->type == PM_STRING_SHARED - }; - - parse_regular_expression_error_data_t error_data = { - .parser = parser, - .start = parser->start + PM_NODE_START(call->receiver), - .end = parser->start + PM_NODE_END(call->receiver), - .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); + pm_regexp_parse_named_captures(parser, pm_string_source(content), pm_string_length(content), false, extended_mode, parse_regular_expression_named_capture, &callback_data); if (callback_data.match != NULL) { return UP(callback_data.match); @@ -20562,7 +20521,7 @@ parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t * } 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, uint16_t depth) { +parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, uint8_t flags, uint16_t depth) { pm_token_t token = parser->current; switch (token.type) { @@ -20588,7 +20547,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t } 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, (uint16_t) (depth + 1)); + 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, flags, 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); @@ -20601,7 +20560,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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_BINDING_POWER_MULTI_ASSIGNMENT + 1, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1)); return parse_write(parser, UP(multi_target), &token, value); } case PM_SOURCE_ENCODING_NODE: @@ -20614,7 +20573,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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_values(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1)); return parse_unwriteable_write(parser, node, &token, value); } default: @@ -20635,25 +20594,23 @@ 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_global_variable_and_write_node_create(parser, node, &token, value)); - pm_node_destroy(parser, node); return result; } 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_class_variable_and_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return result; } 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *write = UP(pm_constant_path_and_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value)); return parse_shareable_constant_write(parser, write); @@ -20661,30 +20618,27 @@ 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *write = UP(pm_constant_and_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return parse_shareable_constant_write(parser, write); } 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_instance_variable_and_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return result; } case PM_IT_LOCAL_VARIABLE_READ_NODE: { pm_constant_id_t name = pm_parser_local_add_constant(parser, "it", 2); 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 *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_and_write_node_create(parser, node, &token, value, name, 0)); pm_node_unreference(parser, node); - pm_node_destroy(parser, node); return result; } case PM_LOCAL_VARIABLE_READ_NODE: { @@ -20696,10 +20650,9 @@ 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(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: { @@ -20713,10 +20666,9 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_constant_id_t constant_id = pm_parser_local_add_location(parser, &cast->message_loc, 1); 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 *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_and_write_node_create(parser, UP(cast), &token, value, constant_id, 0)); - pm_node_destroy(parser, UP(cast)); return result; } @@ -20728,7 +20680,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_AMPAMPEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); return UP(pm_index_and_write_node_create(parser, cast, &token, value)); } @@ -20740,7 +20692,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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); return UP(pm_call_and_write_node_create(parser, cast, &token, value)); } case PM_MULTI_WRITE_NODE: { @@ -20767,25 +20719,23 @@ 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_global_variable_or_write_node_create(parser, node, &token, value)); - pm_node_destroy(parser, node); return result; } 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_class_variable_or_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return result; } 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *write = UP(pm_constant_path_or_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value)); return parse_shareable_constant_write(parser, write); @@ -20793,30 +20743,27 @@ 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *write = UP(pm_constant_or_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return parse_shareable_constant_write(parser, write); } 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_instance_variable_or_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return result; } case PM_IT_LOCAL_VARIABLE_READ_NODE: { pm_constant_id_t name = pm_parser_local_add_constant(parser, "it", 2); 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 *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_or_write_node_create(parser, node, &token, value, name, 0)); pm_node_unreference(parser, node); - pm_node_destroy(parser, node); return result; } case PM_LOCAL_VARIABLE_READ_NODE: { @@ -20828,10 +20775,9 @@ 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(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: { @@ -20845,10 +20791,9 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_constant_id_t constant_id = pm_parser_local_add_location(parser, &cast->message_loc, 1); 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 *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_or_write_node_create(parser, UP(cast), &token, value, constant_id, 0)); - pm_node_destroy(parser, UP(cast)); return result; } @@ -20860,7 +20805,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_PIPEPIPEEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); return UP(pm_index_or_write_node_create(parser, cast, &token, value)); } @@ -20872,7 +20817,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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); return UP(pm_call_or_write_node_create(parser, cast, &token, value)); } case PM_MULTI_WRITE_NODE: { @@ -20909,25 +20854,23 @@ 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_global_variable_operator_write_node_create(parser, node, &token, value)); - pm_node_destroy(parser, node); return result; } 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_class_variable_operator_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return result; } 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *write = UP(pm_constant_path_operator_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value)); return parse_shareable_constant_write(parser, write); @@ -20935,30 +20878,27 @@ 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *write = UP(pm_constant_operator_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return parse_shareable_constant_write(parser, write); } 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_instance_variable_operator_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return result; } case PM_IT_LOCAL_VARIABLE_READ_NODE: { pm_constant_id_t name = pm_parser_local_add_constant(parser, "it", 2); 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_operator_write_node_create(parser, node, &token, value, name, 0)); pm_node_unreference(parser, node); - pm_node_destroy(parser, node); return result; } case PM_LOCAL_VARIABLE_READ_NODE: { @@ -20970,10 +20910,9 @@ 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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_operator_write_node_create(parser, node, &token, value, cast->name, cast->depth)); - pm_node_destroy(parser, node); return result; } case PM_CALL_NODE: { @@ -20986,10 +20925,9 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { pm_refute_numbered_parameter(parser, cast->message_loc.start, cast->message_loc.length); pm_constant_id_t constant_id = pm_parser_local_add_location(parser, &cast->message_loc, 1); - 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 *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_operator_write_node_create(parser, UP(cast), &token, value, constant_id, 0)); - pm_node_destroy(parser, UP(cast)); return result; } @@ -20997,7 +20935,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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return UP(pm_index_operator_write_node_create(parser, cast, &token, value)); } @@ -21009,7 +20947,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, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return UP(pm_call_operator_write_node_create(parser, cast, &token, value)); } case PM_MULTI_WRITE_NODE: { @@ -21031,14 +20969,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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (parser->previous.type == PM_TOKEN_KEYWORD_AND ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0), PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return UP(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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (parser->previous.type == PM_TOKEN_KEYWORD_OR ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0), PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return UP(pm_or_node_create(parser, node, &token, right)); } case PM_TOKEN_EQUAL_TILDE: { @@ -21050,7 +20988,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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *argument = parse_expression(parser, binding_power, flags & PM_PARSE_ACCEPTS_DO_BLOCK, 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); @@ -21095,14 +21033,25 @@ 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, PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)); + result = parse_interpolated_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, PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)); + // If we have a regular expression node, then we can parse + // the named captures and validate encoding in one pass. + pm_regular_expression_node_t *regexp = (pm_regular_expression_node_t *) node; + + pm_regexp_name_data_t name_data = { + .call = call, + .match = NULL, + .names = { 0 }, + }; + + pm_node_flag_set(UP(regexp), pm_regexp_parse(parser, regexp, parse_regular_expression_named_capture, &name_data)); + + if (name_data.match != NULL) { + result = UP(name_data.match); + } } return result; @@ -21156,7 +21105,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t break; } - pm_node_t *argument = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *argument = parse_expression(parser, binding_power, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return UP(pm_call_node_binary_create(parser, node, &token, argument, 0)); } case PM_TOKEN_GREATER: @@ -21168,7 +21117,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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *argument = parse_expression(parser, binding_power, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return UP(pm_call_node_binary_create(parser, node, &token, argument, PM_CALL_NODE_FLAGS_COMPARISON)); } case PM_TOKEN_AMPERSAND_DOT: @@ -21227,7 +21176,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, (uint16_t) (depth + 1)); + parse_arguments_list(parser, &arguments, true, flags, (uint16_t) (depth + 1)); pm_call_node_t *call = pm_call_node_call_create(parser, node, &operator, &message, &arguments); if ( @@ -21247,7 +21196,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, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + right = parse_expression(parser, binding_power, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); } return UP(pm_range_node_create(parser, node, &token, right)); @@ -21256,14 +21205,14 @@ 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, false, PM_ERR_CONDITIONAL_IF_PREDICATE, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_IF_PREDICATE, (uint16_t) (depth + 1)); return UP(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, false, PM_ERR_CONDITIONAL_UNLESS_PREDICATE, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_UNLESS_PREDICATE, (uint16_t) (depth + 1)); return UP(pm_unless_node_modifier_create(parser, node, &keyword, predicate)); } case PM_TOKEN_KEYWORD_UNTIL_MODIFIER: { @@ -21271,7 +21220,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_statements_node_t *statements = pm_statements_node_create(parser); pm_statements_node_body_append(parser, statements, node, true); - pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_UNTIL_PREDICATE, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_UNTIL_PREDICATE, (uint16_t) (depth + 1)); return UP(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: { @@ -21279,7 +21228,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_statements_node_t *statements = pm_statements_node_create(parser); pm_statements_node_body_append(parser, statements, node, true); - pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_WHILE_PREDICATE, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_WHILE_PREDICATE, (uint16_t) (depth + 1)); return UP(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: { @@ -21290,7 +21239,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, false, PM_ERR_TERNARY_EXPRESSION_TRUE, (uint16_t) (depth + 1)); + pm_node_t *true_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_TERNARY_EXPRESSION_TRUE, (uint16_t) (depth + 1)); if (parser->recovering) { // If parsing the true expression of this ternary resulted in a syntax @@ -21304,8 +21253,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t context_pop(parser); pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return UP(pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression)); } @@ -21313,12 +21260,10 @@ 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, false, PM_ERR_TERNARY_EXPRESSION_FALSE, (uint16_t) (depth + 1)); + pm_node_t *false_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_TERNARY_EXPRESSION_FALSE, (uint16_t) (depth + 1)); context_pop(parser); pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return UP(pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression)); } case PM_TOKEN_COLON_COLON: { @@ -21332,7 +21277,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t if ( (parser->current.type == PM_TOKEN_PARENTHESIS_LEFT) || - (accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) + ((flags & PM_PARSE_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 @@ -21343,7 +21288,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, (uint16_t) (depth + 1)); + parse_arguments_list(parser, &arguments, true, flags, (uint16_t) (depth + 1)); path = UP(pm_call_node_call_create(parser, node, &delimiter, &message, &arguments)); } else { // Otherwise, this is a constant path. That would look like Foo::Bar. @@ -21367,7 +21312,7 @@ 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, (uint16_t) (depth + 1)); + parse_arguments_list(parser, &arguments, true, flags, (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. @@ -21396,7 +21341,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, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); + pm_node_t *value = parse_expression(parser, binding_power, (uint8_t) ((flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL), PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); return UP(pm_rescue_modifier_node_create(parser, node, &token, value)); @@ -21409,7 +21354,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, (uint16_t) (depth + 1)); + parse_arguments(parser, &arguments, false, PM_TOKEN_BRACKET_RIGHT, (uint8_t) (flags & ~PM_PARSE_ACCEPTS_DO_BLOCK), (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); expect1(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_EXPECT_RBRACKET); } @@ -21440,7 +21385,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t if (arguments.arguments == NULL) { arguments.arguments = pm_arguments_node_create(parser); } - pm_arguments_node_arguments_append(arguments.arguments, arguments.block); + pm_arguments_node_arguments_append(parser->arena, arguments.arguments, arguments.block); } arguments.block = UP(block); @@ -21461,7 +21406,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t 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); return UP(pm_match_predicate_node_create(parser, node, pattern, &operator)); } @@ -21478,7 +21422,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t 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); return UP(pm_match_required_node_create(parser, node, pattern, &operator)); } @@ -21493,16 +21436,83 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t #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. + * Some nodes act as statements and limit which operators can follow. This + * function inspects the node and the upcoming token to determine whether the + * expression loop should stop. It is called both after prefix parsing and after + * each infix operator. + * + * As a side effect, this function also attaches do-blocks to command-style call + * nodes when appropriate. + * + * Returns true if the expression loop should stop (i.e., the next operator + * should not be consumed). */ -static inline bool -pm_call_node_command_p(const pm_call_node_t *node) { - return ( - (node->opening_loc.length == 0) && - (node->block == NULL || PM_NODE_TYPE_P(node->block, PM_BLOCK_ARGUMENT_NODE)) && - (node->arguments != NULL || node->block != NULL) - ); +static bool +parse_expression_terminator(pm_parser_t *parser, pm_node_t *node) { + pm_binding_power_t left = pm_binding_powers[parser->current.type].left; + + switch (PM_NODE_TYPE(node)) { + case PM_MULTI_WRITE_NODE: + case PM_RETURN_NODE: + case PM_BREAK_NODE: + case PM_NEXT_NODE: + return left > PM_BINDING_POWER_MODIFIER; + 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: + return PM_NODE_FLAG_P(node, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY) && left > PM_BINDING_POWER_MODIFIER; + case PM_CALL_NODE: { + // Calls with an implicit array on the right-hand side are + // statements and can only be followed by modifiers. + if (PM_NODE_FLAG_P(node, PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY)) { + return left > PM_BINDING_POWER_MODIFIER; + } + + // Command-style calls (including block commands like + // `foo bar do end`) can only be followed by composition + // (and/or) and modifier (if/unless/etc.) operators. + if (pm_command_call_value_p(node)) { + return left > PM_BINDING_POWER_COMPOSITION; + } + + // A block call (command with do-block, or any call chained + // from one) can only be followed by call chaining (., ::, + // &.), composition (and/or), and modifier operators. + if (pm_block_call_p(node)) { + return left > PM_BINDING_POWER_COMPOSITION && left < PM_BINDING_POWER_CALL; + } + + return false; + } + case PM_SUPER_NODE: + case PM_YIELD_NODE: + // Command-style super/yield (without parens) can only be followed + // by composition and modifier operators. + if (pm_command_call_value_p(node)) { + return left > PM_BINDING_POWER_COMPOSITION; + } + return false; + case PM_DEF_NODE: + // An endless method whose body is a command-style call (e.g., + // `def f = foo bar`) is a command assignment and can only be + // followed by modifiers. + return left > PM_BINDING_POWER_MODIFIER && pm_command_call_value_p(node); + case PM_RESCUE_MODIFIER_NODE: + // A rescue modifier whose handler is a pattern match (=> or in) + // produces a statement and cannot be followed by operators above + // the modifier level. + if (left > PM_BINDING_POWER_MODIFIER) { + pm_rescue_modifier_node_t *cast = (pm_rescue_modifier_node_t *) node; + pm_node_t *rescue_expression = cast->rescue_expression; + return PM_NODE_TYPE_P(rescue_expression, PM_MATCH_REQUIRED_NODE) || PM_NODE_TYPE_P(rescue_expression, PM_MATCH_PREDICATE_NODE); + } + return false; + default: + return false; + } } /** @@ -21514,45 +21524,39 @@ pm_call_node_command_p(const pm_call_node_t *node) { * 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, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth) { +parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t flags, 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 UP(pm_missing_node_create(parser, PM_TOKEN_START(parser, &parser->current), PM_TOKEN_LENGTH(&parser->current))); } - pm_node_t *node = parse_expression_prefix(parser, binding_power, accepts_command_call, accepts_label, diag_id, depth); + pm_node_t *node = parse_expression_prefix(parser, binding_power, flags, diag_id, depth); + // Some prefix nodes are statements and can only be followed by modifiers + // (if/unless/while/until/rescue) or nothing at all. We check these cheaply + // here before entering the infix loop. switch (PM_NODE_TYPE(node)) { case PM_MISSING_NODE: - // If we found a syntax error, then the type of node returned by - // parse_expression_prefix is going to be a missing node. return node; case PM_PRE_EXECUTION_NODE: + return node; 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). if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { return node; } break; 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)) { + case PM_SUPER_NODE: + case PM_YIELD_NODE: + case PM_DEF_NODE: + if (parse_expression_terminator(parser, 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(parser, node)) { return node; } @@ -21561,8 +21565,8 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc break; } - // 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. + // 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; @@ -21572,45 +21576,8 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc 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, (uint16_t) (depth + 1)); - - if (context_terminator(parser->current_context->context, &parser->current)) { - // If this token terminates the current context, then we need to - // stop parsing the expression, as it has become a statement. - return node; - } - - 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; - } + node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, flags, (uint16_t) (depth + 1)); + if (parse_expression_terminator(parser, node)) return node; // If the operator is nonassoc and we should not be able to parse the // upcoming infix operator, break. @@ -21643,7 +21610,7 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc } } - if (accepts_command_call) { + if (flags & PM_PARSE_ACCEPTS_COMMAND_CALL) { // A command-style method call is only accepted on method chains. // Thus, we check whether the parsed node can continue method chains. // The method chain can continue if the parsed node is one of the following five kinds: @@ -21680,7 +21647,7 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc cast->block != NULL && PM_NODE_TYPE_P(cast->block, PM_BLOCK_NODE) ) ) { - accepts_command_call = false; + flags &= (uint8_t) ~PM_PARSE_ACCEPTS_COMMAND_CALL; } break; } @@ -21688,10 +21655,21 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc case PM_CONSTANT_PATH_NODE: break; default: - accepts_command_call = false; + flags &= (uint8_t) ~PM_PARSE_ACCEPTS_COMMAND_CALL; break; } } + + if (context_terminator(parser->current_context->context, &parser->current)) { + pm_binding_powers_t next_binding_powers = pm_binding_powers[parser->current.type]; + if ( + !next_binding_powers.binary || + binding_power > next_binding_powers.left || + (PM_NODE_TYPE_P(node, PM_CALL_NODE) && pm_call_node_command_p((pm_call_node_t *) node)) + ) { + return node; + } + } } return node; @@ -21710,6 +21688,7 @@ wrap_statements(pm_parser_t *parser, pm_statements_node_t *statements) { pm_arguments_node_t *arguments = pm_arguments_node_create(parser); pm_arguments_node_arguments_append( + parser->arena, arguments, UP(pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$_", 2))) ); @@ -21729,6 +21708,7 @@ wrap_statements(pm_parser_t *parser, pm_statements_node_t *statements) { pm_arguments_node_t *arguments = pm_arguments_node_create(parser); pm_arguments_node_arguments_append( + parser->arena, arguments, UP(pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$;", 2))) ); @@ -21742,25 +21722,26 @@ wrap_statements(pm_parser_t *parser, pm_statements_node_t *statements) { UP(call) ); - pm_statements_node_body_prepend(statements, UP(write)); + pm_statements_node_body_prepend(parser->arena, statements, UP(write)); } pm_arguments_node_t *arguments = pm_arguments_node_create(parser); pm_arguments_node_arguments_append( + parser->arena, arguments, UP(pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$/", 2))) ); if (PM_PARSER_COMMAND_LINE_OPTION_L(parser)) { pm_keyword_hash_node_t *keywords = pm_keyword_hash_node_create(parser); - pm_keyword_hash_node_elements_append(keywords, UP(pm_assoc_node_create( + pm_keyword_hash_node_elements_append(parser->arena, keywords, UP(pm_assoc_node_create( parser, UP(pm_symbol_node_synthesized_create(parser, "chomp")), NULL, UP(pm_true_node_synthesized_create(parser)) ))); - pm_arguments_node_arguments_append(arguments, UP(keywords)); + pm_arguments_node_arguments_append(parser->arena, arguments, UP(keywords)); pm_node_flag_set(UP(arguments), PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS); } @@ -21815,8 +21796,6 @@ parse_program(pm_parser_t *parser) { flush_block_exits(parser, previous_block_exits); } - pm_node_list_free(¤t_block_exits); - // If this is an empty file, then we're still going to parse all of the // statements in order to gather up all of the comments and such. Here we'll // correct the location information. @@ -21899,10 +21878,12 @@ pm_parser_init_shebang(pm_parser_t *parser, const pm_options_t *options, const c * Initialize a parser with the given start and end pointers. */ PRISM_EXPORTED_FUNCTION void -pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options) { +pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options) { + assert(arena != NULL); assert(source != NULL); *parser = (pm_parser_t) { + .arena = arena, .node_id = 0, .lex_state = PM_LEX_STATE_BEG, .enclosure_nesting = 0, @@ -21934,7 +21915,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm .lex_callback = NULL, .filepath = { 0 }, .constant_pool = { 0 }, - .newline_list = { 0 }, + .line_offsets = { 0 }, .integer_base = 0, .current_string = PM_STRING_EMPTY, .start_line = 1, @@ -21944,6 +21925,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm .partial_script = false, .command_start = true, .recovering = false, + .continuable = true, .encoding_locked = false, .encoding_changed = false, .pattern_matching_newlines = false, @@ -21951,7 +21933,6 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm .current_block_exits = NULL, .semantic_token_seen = false, .frozen_string_literal = PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET, - .current_regular_expression_ascii_only = false, .warn_mismatched_indentation = true }; @@ -21976,7 +21957,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm // guess at the number of newlines that we'll need based on the size of the // input. size_t newline_size = size / 22; - pm_newline_list_init(&parser->newline_list, newline_size < 4 ? 4 : newline_size); + pm_line_offset_list_init(&parser->line_offsets, newline_size < 4 ? 4 : newline_size); // If options were provided to this parse, establish them here. if (options != NULL) { @@ -22115,7 +22096,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm const uint8_t *newline = next_newline(cursor, parser->end - cursor); while (newline != NULL) { - pm_newline_list_append(&parser->newline_list, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(newline - parser->start + 1)); cursor = newline + 1; newline = next_newline(cursor, parser->end - cursor); @@ -22145,7 +22126,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm parser->current = (pm_token_t) { .type = PM_TOKEN_EOF, .start = cursor, .end = cursor }; } else { pm_parser_err(parser, 0, 0, PM_ERR_SCRIPT_NOT_FOUND); - pm_newline_list_clear(&parser->newline_list); + pm_line_offset_list_clear(&parser->line_offsets); } } @@ -22175,7 +22156,7 @@ pm_comment_list_free(pm_list_t *list) { next = node->next; pm_comment_t *comment = (pm_comment_t *) node; - xfree(comment); + xfree_sized(comment, sizeof(pm_comment_t)); } } @@ -22190,7 +22171,7 @@ pm_magic_comment_list_free(pm_list_t *list) { next = node->next; pm_magic_comment_t *magic_comment = (pm_magic_comment_t *) node; - xfree(magic_comment); + xfree_sized(magic_comment, sizeof(pm_magic_comment_t)); } } @@ -22205,7 +22186,7 @@ pm_parser_free(pm_parser_t *parser) { pm_comment_list_free(&parser->comment_list); pm_magic_comment_list_free(&parser->magic_comment_list); pm_constant_pool_free(&parser->constant_pool); - pm_newline_list_free(&parser->newline_list); + pm_line_offset_list_free(&parser->line_offsets); while (parser->current_scope != NULL) { // Normally, popping the scope doesn't free the locals since it is @@ -22220,12 +22201,176 @@ pm_parser_free(pm_parser_t *parser) { } } +/** + * Returns true if the given diagnostic ID represents an error that cannot be + * fixed by appending more input. These are errors where the existing source + * contains definitively invalid syntax (as opposed to merely incomplete input). + */ +static bool +pm_parse_err_is_fatal(pm_diagnostic_id_t diag_id) { + switch (diag_id) { + case PM_ERR_ARRAY_EXPRESSION_AFTER_STAR: + case PM_ERR_BEGIN_UPCASE_BRACE: + case PM_ERR_CLASS_VARIABLE_BARE: + case PM_ERR_END_UPCASE_BRACE: + case PM_ERR_ESCAPE_INVALID_HEXADECIMAL: + case PM_ERR_ESCAPE_INVALID_UNICODE_LIST: + case PM_ERR_ESCAPE_INVALID_UNICODE_SHORT: + case PM_ERR_EXPRESSION_NOT_WRITABLE: + case PM_ERR_EXPRESSION_NOT_WRITABLE_SELF: + case PM_ERR_FLOAT_PARSE: + case PM_ERR_GLOBAL_VARIABLE_BARE: + case PM_ERR_HASH_KEY: + case PM_ERR_HEREDOC_IDENTIFIER: + case PM_ERR_INSTANCE_VARIABLE_BARE: + case PM_ERR_INVALID_BLOCK_EXIT: + case PM_ERR_INVALID_ENCODING_MAGIC_COMMENT: + case PM_ERR_INVALID_FLOAT_EXPONENT: + case PM_ERR_INVALID_NUMBER_BINARY: + case PM_ERR_INVALID_NUMBER_DECIMAL: + case PM_ERR_INVALID_NUMBER_HEXADECIMAL: + case PM_ERR_INVALID_NUMBER_OCTAL: + case PM_ERR_INVALID_NUMBER_UNDERSCORE_TRAILING: + case PM_ERR_NO_LOCAL_VARIABLE: + case PM_ERR_PARAMETER_ORDER: + case PM_ERR_STATEMENT_UNDEF: + case PM_ERR_VOID_EXPRESSION: + return true; + default: + return false; + } +} + +/** + * Determine whether the source parsed by the given parser could become valid if + * more input were appended. This is used by tools like IRB to decide whether to + * prompt for continuation or to display an error. + * + * The parser starts with continuable=true. This function scans all errors to + * detect two categories of non-continuable errors: + * + * 1. Fatal errors: errors like invalid number literals or bare global variables + * that indicate definitively invalid syntax. These are only considered fatal + * if they occur before EOF (at EOF they could be from truncated input, e.g. + * `"\x` is an incomplete hex escape). + * + * 2. Stray tokens: unexpected_token_ignore and unexpected_token_close_context + * errors indicate tokens that don't belong. A stray token is a cascade + * effect (and does not prevent continuability) if: + * + * a. A non-stray, non-fatal error appeared earlier in the error list at a + * strictly earlier source position (the stray was caused by a preceding + * parse failure, e.g. a truncated heredoc), OR + * b. The stray token is at EOF, starts after position 0 (there is valid + * code before it), and either is a single byte (likely a truncated + * token like `\`) or there are non-stray errors elsewhere. + * + * Closing delimiters (`)`, `]`, `}`) at EOF are always genuinely stray — + * they are complete tokens and cannot become part of a longer valid + * construct by appending more input. + * + * c. The stray token is `=` at the start of a line, which could be the + * beginning of `=begin` (an embedded document). The remaining bytes + * after `=` may parse as an identifier, so the error is not at EOF, + * but the construct is genuinely incomplete. + */ +static void +pm_parse_continuable(pm_parser_t *parser) { + // If there are no errors then there is nothing to continue. + if (parser->error_list.size == 0) { + parser->continuable = false; + return; + } + + if (!parser->continuable) return; + + size_t source_length = (size_t) (parser->end - parser->start); + + // First pass: check if there are any non-stray, non-fatal errors. + bool has_non_stray_error = false; + for (pm_diagnostic_t *error = (pm_diagnostic_t *) parser->error_list.head; error != NULL; error = (pm_diagnostic_t *) error->node.next) { + if (error->diag_id != PM_ERR_UNEXPECTED_TOKEN_IGNORE && error->diag_id != PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT && !pm_parse_err_is_fatal(error->diag_id)) { + has_non_stray_error = true; + break; + } + } + + // Second pass: check each error. We track the minimum source position + // among non-stray, non-fatal errors seen so far in list order, which + // lets us detect cascade stray tokens. + size_t non_stray_min_start = SIZE_MAX; + + for (pm_diagnostic_t *error = (pm_diagnostic_t *) parser->error_list.head; error != NULL; error = (pm_diagnostic_t *) error->node.next) { + size_t error_start = (size_t) error->location.start; + size_t error_end = error_start + (size_t) error->location.length; + bool at_eof = error_end >= source_length; + + // Fatal errors are non-continuable unless they occur at EOF. + if (pm_parse_err_is_fatal(error->diag_id) && !at_eof) { + parser->continuable = false; + return; + } + + // Track non-stray, non-fatal error positions in list order. + if (error->diag_id != PM_ERR_UNEXPECTED_TOKEN_IGNORE && + error->diag_id != PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT) { + if (error_start < non_stray_min_start) non_stray_min_start = error_start; + continue; + } + + // This is a stray token. Determine if it is a cascade effect + // of a preceding error or genuinely stray. + + // Rule (a): a non-stray error was seen earlier in the list at a + // strictly earlier position — this stray is a cascade effect. + if (non_stray_min_start < error_start) continue; + + // Rule (b): this stray is at EOF with valid code before it. + // Single-byte stray tokens at EOF (like `\` for line continuation) + // are likely truncated tokens. Multi-byte stray tokens (like the + // keyword `end`) need additional evidence that they are cascade + // effects (i.e. non-stray errors exist elsewhere). + if (at_eof && error_start > 0) { + // Exception: closing delimiters at EOF are genuinely stray. + if (error->location.length == 1) { + const uint8_t *byte = parser->start + error_start; + if (*byte == ')' || *byte == ']' || *byte == '}') { + parser->continuable = false; + return; + } + + // Single-byte non-delimiter stray at EOF: cascade. + continue; + } + + // Multi-byte stray at EOF: cascade only if there are + // non-stray errors (evidence of a preceding parse failure). + if (has_non_stray_error) continue; + } + + // Rule (c): a stray `=` at the start of a line could be the + // beginning of an embedded document (`=begin`). The remaining + // bytes after `=` parse as an identifier, so the error is not + // at EOF, but the construct is genuinely incomplete. + if (error->location.length == 1) { + const uint8_t *byte = parser->start + error_start; + if (*byte == '=' && (error_start == 0 || *(byte - 1) == '\n')) continue; + } + + // This stray token is genuinely non-continuable. + parser->continuable = false; + return; + } +} + /** * Parse the Ruby source associated with the given parser and return the tree. */ PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse(pm_parser_t *parser) { - return parse_program(parser); + pm_node_t *node = parse_program(parser); + pm_parse_continuable(parser); + return node; } /** @@ -22282,28 +22427,6 @@ pm_parse_stream_read(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t #undef LINE_SIZE } -/** - * Determine if there was an unterminated heredoc at the end of the input, which - * would mean the stream isn't finished and we should keep reading. - * - * For the other lex modes we can check if the lex mode has been closed, but for - * heredocs when we hit EOF we close the lex mode and then go back to parse the - * rest of the line after the heredoc declaration so that we get more of the - * syntax tree. - */ -static bool -pm_parse_stream_unterminated_heredoc_p(pm_parser_t *parser) { - pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) parser->error_list.head; - - for (; diagnostic != NULL; diagnostic = (pm_diagnostic_t *) diagnostic->node.next) { - if (diagnostic->diag_id == PM_ERR_HEREDOC_TERM) { - return true; - } - } - - return false; -} - /** * Parse a stream of Ruby source and return the tree. * @@ -22311,20 +22434,20 @@ pm_parse_stream_unterminated_heredoc_p(pm_parser_t *parser) { * can stream stdin in to Ruby so we need to support a streaming API. */ PRISM_EXPORTED_FUNCTION pm_node_t * -pm_parse_stream(pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options) { +pm_parse_stream(pm_arena_t *arena, pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options) { pm_buffer_init(buffer); bool eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof); - pm_parser_init(parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); + pm_parser_init(arena, parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); pm_node_t *node = pm_parse(parser); - while (!eof && parser->error_list.size > 0 && (parser->lex_modes.index > 0 || pm_parse_stream_unterminated_heredoc_p(parser))) { - pm_node_destroy(parser, node); + while (!eof && parser->error_list.size > 0) { eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof); pm_parser_free(parser); - pm_parser_init(parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); + pm_arena_free(arena); + pm_parser_init(arena, parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); node = pm_parse(parser); } @@ -22339,14 +22462,15 @@ pm_parse_success_p(const uint8_t *source, size_t size, const char *data) { pm_options_t options = { 0 }; pm_options_read(&options, data); + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, source, size, &options); + pm_parser_init(&arena, &parser, source, size, &options); - pm_node_t *node = pm_parse(&parser); - pm_node_destroy(&parser, node); + pm_parse(&parser); bool result = parser.error_list.size == 0; pm_parser_free(&parser); + pm_arena_free(&arena); pm_options_free(&options); return result; @@ -22390,8 +22514,9 @@ pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, cons pm_options_t options = { 0 }; pm_options_read(&options, data); + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, source, size, &options); + pm_parser_init(&arena, &parser, source, size, &options); pm_node_t *node = pm_parse(&parser); @@ -22399,8 +22524,8 @@ pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, cons pm_serialize_content(&parser, node, buffer); pm_buffer_append_byte(buffer, '\0'); - pm_node_destroy(&parser, node); pm_parser_free(&parser); + pm_arena_free(&arena); pm_options_free(&options); } @@ -22410,19 +22535,20 @@ pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, cons */ PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const char *data) { + pm_arena_t arena = { 0 }; pm_parser_t parser; pm_options_t options = { 0 }; pm_options_read(&options, data); pm_buffer_t parser_buffer; - pm_node_t *node = pm_parse_stream(&parser, &parser_buffer, stream, stream_fgets, stream_feof, &options); + pm_node_t *node = pm_parse_stream(&arena, &parser, &parser_buffer, stream, stream_fgets, stream_feof, &options); pm_serialize_header(buffer); pm_serialize_content(&parser, node, buffer); pm_buffer_append_byte(buffer, '\0'); - pm_node_destroy(&parser, node); pm_buffer_free(&parser_buffer); pm_parser_free(&parser); + pm_arena_free(&arena); pm_options_free(&options); } @@ -22434,17 +22560,18 @@ pm_serialize_parse_comments(pm_buffer_t *buffer, const uint8_t *source, size_t s pm_options_t options = { 0 }; pm_options_read(&options, data); + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, source, size, &options); + pm_parser_init(&arena, &parser, source, size, &options); - pm_node_t *node = pm_parse(&parser); + pm_parse(&parser); pm_serialize_header(buffer); pm_serialize_encoding(parser.encoding, buffer); pm_buffer_append_varsint(buffer, parser.start_line); pm_serialize_comment_list(&parser.comment_list, buffer); - pm_node_destroy(&parser, node); pm_parser_free(&parser); + pm_arena_free(&arena); pm_options_free(&options); } diff --git a/src/regexp.c b/src/regexp.c index dcc7476244..f864e187c9 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -1,5 +1,9 @@ #include "prism/regexp.h" +#include "prism/diagnostic.h" +#include "prism/util/pm_buffer.h" +#include "prism/util/pm_strncasecmp.h" +/** The maximum depth of nested groups allowed in a regular expression. */ #define PM_REGEXP_PARSE_DEPTH_MAX 4096 /** @@ -18,6 +22,54 @@ typedef struct { /** A pointer to the end of the source that we are parsing. */ const uint8_t *end; + /** 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. */ + pm_regexp_name_data_t *name_data; + + /** The start of the regexp node (for error locations). */ + const uint8_t *node_start; + + /** The end of the regexp node (for error locations). */ + const uint8_t *node_end; + + /** + * The explicit encoding determined by escape sequences. NULL if no + * encoding-setting escape has been seen, UTF-8 for `\u` escapes, or the + * source encoding for `\x` escapes. + */ + const pm_encoding_t *explicit_encoding; + + /** + * Pointer to the first non-POSIX property name (for /n error messages). + * POSIX properties (Alnum, Alpha, etc.) work in all encodings. + * Script properties (Hiragana, Katakana, etc.) work in /e, /s, /u. + * Unicode-only properties (L, Ll, etc.) work only in /u. + */ + const uint8_t *property_name; + + /** Length of the first non-POSIX property name found. */ + size_t property_name_length; + + /** + * Pointer to the first Unicode-only property name (for /e, /s error + * messages). NULL if only POSIX or script properties have been seen. + */ + const uint8_t *unicode_property_name; + + /** Length of the first Unicode-only property name found. */ + size_t unicode_property_name_length; + + /** Buffer of hex escape byte values >= 0x80, separated by 0x00 sentinels. */ + pm_buffer_t hex_escape_buffer; + + /** Count of non-ASCII literal bytes (not from escapes). */ + uint32_t non_ascii_literal_count; + /** * Whether or not the regular expression currently being parsed is in * extended mode, wherein whitespace is ignored and comments are allowed. @@ -27,30 +79,76 @@ typedef struct { /** Whether the encoding has changed from the default. */ bool encoding_changed; - /** The encoding of the source. */ - const pm_encoding_t *encoding; + /** Whether the source content is shared (for named capture callback). */ + bool shared; - /** The callback to call when a named capture group is found. */ - pm_regexp_name_callback_t name_callback; + /** Whether a `\u{...}` escape with value >= 0x80 was seen. */ + bool has_unicode_escape; - /** The data to pass to the name callback. */ - void *name_data; + /** Whether a `\xNN` escape (or `\M-x`, etc.) with value >= 0x80 was seen. */ + bool has_hex_escape; + + /** + * Tracks whether the last encoding-setting escape was `\u` (true) or `\x` + * (false). This matters for error messages when both types are mixed. + */ + bool last_escape_was_unicode; - /** The callback to call when a parse error is found. */ - pm_regexp_error_callback_t error_callback; + /** Whether any `\p{...}` or `\P{...}` property escape was found. */ + bool has_property_escape; - /** The data to pass to the error callback. */ - void *error_data; + /** Whether a Unicode-only property escape was found (not POSIX or script). */ + bool has_unicode_property_escape; + + /** Whether a `\u` escape with invalid range (surrogate or > 0x10FFFF) was seen. */ + bool invalid_unicode_range; + + /** Whether we are accumulating consecutive hex escape bytes. */ + bool hex_group_active; + + /** Whether an invalid multibyte character was found during parsing. */ + bool has_invalid_multibyte; } pm_regexp_parser_t; /** - * Append an error to the parser. + * Append a syntax error to the parser's error list. If the source is shared + * (points into the original source), we can point to the exact error location. + * Otherwise, we point to the whole regexp node. */ 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); + pm_parser_t *pm = parser->parser; + uint32_t loc_start, loc_length; + + if (parser->shared) { + loc_start = (uint32_t) (start - pm->start); + loc_length = (uint32_t) (end - start); + } else { + loc_start = (uint32_t) (parser->node_start - pm->start); + loc_length = (uint32_t) (parser->node_end - parser->node_start); + } + + pm_diagnostic_list_append_format(&pm->error_list, loc_start, loc_length, PM_ERR_REGEXP_PARSE_ERROR, message); } +/** + * Append a formatted diagnostic error with proper shared/non-shared location + * handling. This is a macro because we need variadic args for the format string. + */ +#define pm_regexp_parse_error_format(parser_, err_start_, err_end_, diag_id, ...) \ + do { \ + pm_parser_t *pm__ = (parser_)->parser; \ + uint32_t loc_start__, loc_length__; \ + if ((parser_)->shared) { \ + loc_start__ = (uint32_t) ((err_start_) - pm__->start); \ + loc_length__ = (uint32_t) ((err_end_) - (err_start_)); \ + } else { \ + loc_start__ = (uint32_t) ((parser_)->node_start - pm__->start); \ + loc_length__ = (uint32_t) ((parser_)->node_end - (parser_)->node_start); \ + } \ + pm_diagnostic_list_append_format(&pm__->error_list, loc_start__, loc_length__, diag_id, __VA_ARGS__); \ + } while (0) + /** * 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. @@ -59,7 +157,7 @@ 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); - parser->name_callback(&string, parser->name_data); + parser->name_callback(parser->parser, &string, parser->shared, parser->name_data); pm_string_free(&string); } @@ -113,6 +211,47 @@ pm_regexp_char_find(pm_regexp_parser_t *parser, uint8_t value) { return true; } +/** + * Mark a group boundary in the hex escape byte buffer. When consecutive hex + * escape bytes >= 0x80 are followed by a non-hex-escape, this appends a 0x00 + * sentinel to separate the groups for later multibyte validation. + */ +static inline void +pm_regexp_hex_group_boundary(pm_regexp_parser_t *parser) { + if (parser->hex_group_active) { + pm_buffer_append_byte(&parser->hex_escape_buffer, 0x00); + parser->hex_group_active = false; + } +} + +/** + * Track a hex escape byte value >= 0x80 for multibyte validation. + */ +static inline void +pm_regexp_track_hex_escape(pm_regexp_parser_t *parser, uint8_t byte) { + if (byte >= 0x80) { + pm_buffer_append_byte(&parser->hex_escape_buffer, byte); + parser->hex_group_active = true; + parser->has_hex_escape = true; + + parser->explicit_encoding = parser->encoding; + parser->last_escape_was_unicode = false; + } else { + pm_regexp_hex_group_boundary(parser); + } +} + +/** + * Parse a hex digit character and return its value, or -1 if not a hex digit. + */ +static inline int +pm_regexp_hex_digit_value(uint8_t byte) { + if (byte >= '0' && byte <= '9') return byte - '0'; + if (byte >= 'a' && byte <= 'f') return byte - 'a' + 10; + if (byte >= 'A' && byte <= 'F') return byte - 'A' + 10; + return -1; +} + /** * Range quantifiers are a special class of quantifiers that look like * @@ -121,13 +260,12 @@ pm_regexp_char_find(pm_regexp_parser_t *parser, uint8_t value) { * * {digit,digit} * * {,digit} * - * Unfortunately, if there are any spaces in between, then this just becomes a - * regular character match expression and we have to backtrack. So when this - * function first starts running, we'll create a "save" point and then attempt - * to parse the quantifier. If it fails, we'll restore the save point and - * return. + * If there are any spaces in between, then this just becomes a regular + * character match expression and we have to backtrack. So when this function + * first starts running, we'll create a "save" point and then attempt to parse + * the quantifier. If it fails, we'll restore the save point and return. * - * The properly track everything, we're going to build a little state machine. + * To properly track everything, we're going to build a little state machine. * It looks something like the following: * * +-------+ +---------+ ------------+ @@ -275,10 +413,392 @@ pm_regexp_parse_posix_class(pm_regexp_parser_t *parser) { ); } +/** + * Property escape classification. Onigmo supports three tiers of property + * names depending on the encoding: + * + * - POSIX properties (Alnum, Alpha, ASCII, Blank, Cntrl, Digit, Graph, Lower, + * Print, Punct, Space, Upper, XDigit, Word): valid in all encodings. + * - Script properties (Hiragana, Katakana, Han, Latin, Greek, Cyrillic): valid + * in EUC-JP (/e), Windows-31J (/s), and UTF-8 (/u), but not ASCII-8BIT (/n). + * - Unicode-only properties (general categories like L, Ll, Lu, etc., plus + * Any, Assigned): valid only in UTF-8 (/u). + */ +typedef enum { + PM_REGEXP_PROPERTY_POSIX, + PM_REGEXP_PROPERTY_SCRIPT, + PM_REGEXP_PROPERTY_UNICODE +} pm_regexp_property_type_t; + +/** + * Classify a property name. The name may start with '^' for negation, which + * is skipped before matching. + */ +static pm_regexp_property_type_t +pm_regexp_classify_property(const uint8_t *name, size_t length) { + // Skip leading '^' for negated properties like \p{^Hiragana}. + if (length > 0 && name[0] == '^') { + name++; + length--; + } + +#define PM_REGEXP_CASECMP(str_) (pm_strncasecmp(name, (const uint8_t *) (str_), length) == 0) + + switch (length) { + case 3: + if (PM_REGEXP_CASECMP("Han")) return PM_REGEXP_PROPERTY_SCRIPT; + break; + case 4: + if (PM_REGEXP_CASECMP("Word")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 5: + /* Most properties are length 5, so dispatch on first character. */ + switch (name[0] | 0x20) { + case 'a': + if (PM_REGEXP_CASECMP("Alnum")) return PM_REGEXP_PROPERTY_POSIX; + if (PM_REGEXP_CASECMP("Alpha")) return PM_REGEXP_PROPERTY_POSIX; + if (PM_REGEXP_CASECMP("ASCII")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 'b': + if (PM_REGEXP_CASECMP("Blank")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 'c': + if (PM_REGEXP_CASECMP("Cntrl")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 'd': + if (PM_REGEXP_CASECMP("Digit")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 'g': + if (PM_REGEXP_CASECMP("Graph")) return PM_REGEXP_PROPERTY_POSIX; + if (PM_REGEXP_CASECMP("Greek")) return PM_REGEXP_PROPERTY_SCRIPT; + break; + case 'l': + if (PM_REGEXP_CASECMP("Lower")) return PM_REGEXP_PROPERTY_POSIX; + if (PM_REGEXP_CASECMP("Latin")) return PM_REGEXP_PROPERTY_SCRIPT; + break; + case 'p': + if (PM_REGEXP_CASECMP("Print")) return PM_REGEXP_PROPERTY_POSIX; + if (PM_REGEXP_CASECMP("Punct")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 's': + if (PM_REGEXP_CASECMP("Space")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 'u': + if (PM_REGEXP_CASECMP("Upper")) return PM_REGEXP_PROPERTY_POSIX; + break; + } + break; + case 6: + if (PM_REGEXP_CASECMP("XDigit")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 8: + if (PM_REGEXP_CASECMP("Hiragana")) return PM_REGEXP_PROPERTY_SCRIPT; + if (PM_REGEXP_CASECMP("Katakana")) return PM_REGEXP_PROPERTY_SCRIPT; + if (PM_REGEXP_CASECMP("Cyrillic")) return PM_REGEXP_PROPERTY_SCRIPT; + break; + } + +#undef PM_REGEXP_CASECMP + + // Everything else is Unicode-only (general categories, other scripts, etc.). + return PM_REGEXP_PROPERTY_UNICODE; +} + +/** + * Check for and skip a `\p{...}` or `\P{...}` Unicode property escape. The + * cursor should be pointing at 'p' or 'P' when this is called. If a property + * escape is found, record it on the regexp parser and advance past the closing + * '}'. + * + * Properties are classified into three tiers (POSIX, script, Unicode-only) to + * determine which encoding modifiers they are valid with. + */ +static bool +pm_regexp_parse_property_escape(pm_regexp_parser_t *parser) { + assert(*parser->cursor == 'p' || *parser->cursor == 'P'); + + if (parser->cursor + 1 < parser->end && parser->cursor[1] == '{') { + const uint8_t *name_start = parser->cursor + 2; + const uint8_t *search = name_start; + + while (search < parser->end && *search != '}') search++; + + if (search < parser->end) { + size_t name_length = (size_t) (search - name_start); + parser->has_property_escape = true; + + pm_regexp_property_type_t type = pm_regexp_classify_property(name_start, name_length); + + // Track the first non-POSIX property name (for /n error messages). + if (type >= PM_REGEXP_PROPERTY_SCRIPT && parser->property_name == NULL) { + parser->property_name = name_start; + parser->property_name_length = name_length; + } + + // Track the first Unicode-only property name (for /e, /s error messages). + if (type == PM_REGEXP_PROPERTY_UNICODE) { + parser->has_unicode_property_escape = true; + if (parser->unicode_property_name == NULL) { + parser->unicode_property_name = name_start; + parser->unicode_property_name_length = name_length; + } + } + + parser->cursor = search + 1; // skip past '}' + return true; + } + } + + // Not a property escape, just skip the single character after '\'. + parser->cursor++; + return false; +} + +/** + * Validate and skip a \u escape sequence in a regular expression. The cursor + * should be pointing at the character after 'u' when this is called. This + * handles both the \u{NNNN MMMM} and \uNNNN forms. Also tracks encoding + * state for validation. + */ +static void +pm_regexp_parse_unicode_escape(pm_regexp_parser_t *parser) { + const uint8_t *escape_start = parser->cursor - 2; // points to '\' + + if (pm_regexp_char_is_eof(parser)) { + pm_regexp_parse_error(parser, escape_start, parser->cursor, "invalid Unicode escape"); + return; + } + + if (*parser->cursor == '{') { + parser->cursor++; // skip '{' + + // Skip leading whitespace. + while (!pm_regexp_char_is_eof(parser) && pm_char_is_whitespace(*parser->cursor)) { + parser->cursor++; + } + + bool has_codepoint = false; + + while (!pm_regexp_char_is_eof(parser) && *parser->cursor != '}') { + // Parse the hex digits to compute the codepoint value. + uint32_t value = 0; + size_t hex_count = 0; + + int digit; + while (!pm_regexp_char_is_eof(parser) && (digit = pm_regexp_hex_digit_value(*parser->cursor)) >= 0) { + value = (value << 4) | (uint32_t) digit; + hex_count++; + parser->cursor++; + } + + if (hex_count == 0) { + // Skip to '}' or end of regexp to find the full extent. + while (!pm_regexp_char_is_eof(parser) && *parser->cursor != '}') { + parser->cursor++; + } + + const uint8_t *escape_end = parser->cursor; + if (!pm_regexp_char_is_eof(parser)) { + escape_end++; + parser->cursor++; // skip '}' + } + + pm_regexp_parse_error_format(parser, escape_start, escape_end, PM_ERR_ESCAPE_INVALID_UNICODE_LIST, (int) (escape_end - escape_start), (const char *) escape_start); + return; + } + + if (hex_count > 6) { + pm_regexp_parse_error(parser, escape_start, parser->cursor, "invalid Unicode range"); + } + + // Track encoding state for this codepoint. + if (value >= 0x80) { + parser->has_unicode_escape = true; + parser->explicit_encoding = PM_ENCODING_UTF_8_ENTRY; + parser->last_escape_was_unicode = true; + pm_regexp_hex_group_boundary(parser); + } + + // Check for invalid Unicode range (surrogates or > 0x10FFFF). + if (value > 0x10FFFF || (value >= 0xD800 && value <= 0xDFFF)) { + parser->invalid_unicode_range = true; + } + + has_codepoint = true; + + // Skip whitespace between codepoints. + while (!pm_regexp_char_is_eof(parser) && pm_char_is_whitespace(*parser->cursor)) { + parser->cursor++; + } + } + + if (pm_regexp_char_is_eof(parser)) { + pm_regexp_parse_error(parser, escape_start, parser->cursor, "unterminated Unicode escape"); + } else { + if (!has_codepoint) { + pm_regexp_parse_error_format(parser, escape_start, parser->cursor + 1, PM_ERR_ESCAPE_INVALID_UNICODE_LIST, (int) (parser->cursor + 1 - escape_start), (const char *) escape_start); + } + parser->cursor++; // skip '}' + } + } else { + // \uNNNN form — need exactly 4 hex digits. + uint32_t value = 0; + size_t hex_count = 0; + + int digit; + while (hex_count < 4 && !pm_regexp_char_is_eof(parser) && (digit = pm_regexp_hex_digit_value(*parser->cursor)) >= 0) { + value = (value << 4) | (uint32_t) digit; + hex_count++; + parser->cursor++; + } + + if (hex_count < 4) { + pm_regexp_parse_error(parser, escape_start, parser->cursor, "invalid Unicode escape"); + } else if (value >= 0x80) { + parser->has_unicode_escape = true; + parser->explicit_encoding = PM_ENCODING_UTF_8_ENTRY; + parser->last_escape_was_unicode = true; + pm_regexp_hex_group_boundary(parser); + } + + // Check for invalid Unicode range. + if (hex_count == 4 && (value > 0x10FFFF || (value >= 0xD800 && value <= 0xDFFF))) { + parser->invalid_unicode_range = true; + } + } +} + // Forward declaration because character sets can be nested. static bool pm_regexp_parse_lbracket(pm_regexp_parser_t *parser, uint16_t depth); +/** + * Parse a \x escape and return the byte value. The cursor should be pointing + * at the character after 'x'. Returns -1 if no hex digits follow. + */ +static int +pm_regexp_parse_hex_escape(pm_regexp_parser_t *parser) { + int value = -1; + + if (!pm_regexp_char_is_eof(parser)) { + int digit = pm_regexp_hex_digit_value(*parser->cursor); + if (digit >= 0) { + value = digit; + parser->cursor++; + + if (!pm_regexp_char_is_eof(parser)) { + digit = pm_regexp_hex_digit_value(*parser->cursor); + if (digit >= 0) { + value = (value << 4) | digit; + parser->cursor++; + } + } + } + } + + if (value >= 0) { + pm_regexp_track_hex_escape(parser, (uint8_t) value); + } + + return value; +} + +/** + * Parse a backslash escape sequence in a regexp, handling \u (unicode), + * \p/\P (property), \x (hex), and other single-character escapes. Also + * tracks encoding state for \M-x and \C-\M-x escapes. + */ +static void +pm_regexp_parse_backslash_escape(pm_regexp_parser_t *parser) { + if (pm_regexp_char_is_eof(parser)) return; + + switch (*parser->cursor) { + case 'u': + parser->cursor++; // skip 'u' + pm_regexp_parse_unicode_escape(parser); + break; + case 'p': + case 'P': + pm_regexp_parse_property_escape(parser); + break; + case 'x': + parser->cursor++; // skip 'x' + pm_regexp_parse_hex_escape(parser); + break; + case 'M': + // \M-x produces (x | 0x80), always >= 0x80 + if (parser->cursor + 2 < parser->end && parser->cursor[1] == '-') { + parser->cursor += 2; // skip 'M-' + if (!pm_regexp_char_is_eof(parser)) { + if (*parser->cursor == '\\') { + parser->cursor++; + // \M-\C-x or \M-\cx — the resulting byte is always >= 0x80 + // We just need to track it as a hex escape >= 0x80. + pm_regexp_parse_backslash_escape(parser); + } else { + parser->cursor++; + } + // \M-x always produces a byte >= 0x80 + pm_regexp_track_hex_escape(parser, 0x80); + } + } else { + parser->cursor++; + } + break; + case 'C': + // \C-x produces (x & 0x1F) + if (parser->cursor + 2 < parser->end && parser->cursor[1] == '-') { + parser->cursor += 2; // skip 'C-' + if (!pm_regexp_char_is_eof(parser)) { + if (*parser->cursor == '\\') { + parser->cursor++; + pm_regexp_parse_backslash_escape(parser); + } else { + parser->cursor++; + } + } + } else { + parser->cursor++; + } + break; + case 'c': + // \cx produces (x & 0x1F) + parser->cursor++; // skip 'c' + if (!pm_regexp_char_is_eof(parser)) { + if (*parser->cursor == '\\') { + parser->cursor++; + pm_regexp_parse_backslash_escape(parser); + } else { + parser->cursor++; + } + } + break; + default: + pm_regexp_hex_group_boundary(parser); + parser->cursor++; + break; + } +} + +/** + * Check if a byte at the current position is a non-ASCII byte in a multibyte + * encoding that produces an invalid character. If so, emit an error at the + * byte location immediately. + */ +static void +pm_regexp_parse_invalid_multibyte(pm_regexp_parser_t *parser, const uint8_t *cursor) { + uint8_t byte = *cursor; + if (byte >= 0x80 && parser->encoding_changed && parser->encoding->multibyte) { + size_t width = parser->encoding->char_width(cursor, (ptrdiff_t) (parser->end - cursor)); + if (width > 1) { + parser->cursor += width - 1; + } else if (width == 0) { + parser->has_invalid_multibyte = true; + pm_regexp_parse_error_format(parser, cursor, cursor + 1, PM_ERR_INVALID_MULTIBYTE_CHAR, parser->encoding->name); + } + } +} + /** * match-char-set : '[' '^'? (match-range | match-char)* ']' * ; @@ -293,12 +813,16 @@ pm_regexp_parse_character_set(pm_regexp_parser_t *parser, uint16_t depth) { pm_regexp_parse_lbracket(parser, (uint16_t) (depth + 1)); break; case '\\': - if (!pm_regexp_char_is_eof(parser)) { - parser->cursor++; - } + pm_regexp_parse_backslash_escape(parser); break; default: - // do nothing, we've already advanced the cursor + // We've already advanced the cursor by one byte. If the byte + // was >= 0x80 in a multibyte encoding, we may need to consume + // additional continuation bytes and validate the character. + if (*(parser->cursor - 1) >= 0x80) { + parser->non_ascii_literal_count++; + } + pm_regexp_parse_invalid_multibyte(parser, parser->cursor - 1); break; } } @@ -354,8 +878,13 @@ typedef enum { // These are the options that are configurable on the regular expression (or // from within a group). +/** The minimum character value for a regexp option slot. */ #define PRISM_REGEXP_OPTION_STATE_SLOT_MINIMUM 'a' + +/** The maximum character value for a regexp option slot. */ #define PRISM_REGEXP_OPTION_STATE_SLOT_MAXIMUM 'x' + +/** The number of regexp option slots. */ #define PRISM_REGEXP_OPTION_STATE_SLOTS (PRISM_REGEXP_OPTION_STATE_SLOT_MAXIMUM - PRISM_REGEXP_OPTION_STATE_SLOT_MINIMUM + 1) /** @@ -498,7 +1027,15 @@ pm_regexp_parse_group(pm_regexp_parser_t *parser, uint16_t depth) { } size_t width = parser->encoding->char_width(parser->cursor, (ptrdiff_t) (parser->end - parser->cursor)); - if (width == 0) return false; + if (width == 0) { + if (*parser->cursor >= 0x80) { + parser->has_invalid_multibyte = true; + pm_regexp_parse_error_format(parser, parser->cursor, parser->cursor + 1, PM_ERR_INVALID_MULTIBYTE_CHAR, parser->encoding->name); + parser->cursor++; + continue; + } + return false; + } escaped = (width == 1) && (*parser->cursor == '\\'); parser->cursor += width; @@ -686,9 +1223,7 @@ pm_regexp_parse_item(pm_regexp_parser_t *parser, uint16_t depth) { return pm_regexp_parse_quantifier(parser); case '\\': parser->cursor++; - if (!pm_regexp_char_is_eof(parser)) { - parser->cursor++; - } + pm_regexp_parse_backslash_escape(parser); return pm_regexp_parse_quantifier(parser); case '(': parser->cursor++; @@ -720,9 +1255,30 @@ pm_regexp_parse_item(pm_regexp_parser_t *parser, uint16_t depth) { width = parser->encoding->char_width(parser->cursor, (ptrdiff_t) (parser->end - parser->cursor)); } - if (width == 0) return false; // TODO: add appropriate error - parser->cursor += width; + if (width == 0) { + if (*parser->cursor >= 0x80 && parser->encoding_changed) { + if (parser->encoding->multibyte) { + // Invalid multibyte character in a multibyte encoding. + // Emit the error at the byte location immediately. + parser->has_invalid_multibyte = true; + pm_regexp_parse_error_format(parser, parser->cursor, parser->cursor + 1, PM_ERR_INVALID_MULTIBYTE_CHAR, parser->encoding->name); + } else { + // Non-ASCII byte in a single-byte encoding (e.g., + // US-ASCII). Count it for later error reporting. + parser->non_ascii_literal_count++; + } + parser->cursor++; + return pm_regexp_parse_quantifier(parser); + } + return false; + } + // Count non-ASCII literal bytes. + for (size_t i = 0; i < width; i++) { + if (parser->cursor[i] >= 0x80) parser->non_ascii_literal_count++; + } + + parser->cursor += width; return pm_regexp_parse_quantifier(parser); } } @@ -768,13 +1324,353 @@ pm_regexp_parse_pattern(pm_regexp_parser_t *parser) { return pm_regexp_char_is_eof(parser); } +// --------------------------------------------------------------------------- +// Encoding validation +// --------------------------------------------------------------------------- + +/** + * Validate that groups of hex escape bytes in the buffer form valid multibyte + * characters in the given encoding. Groups are separated by 0x00 sentinels. + */ +static bool +pm_regexp_validate_hex_escapes(const pm_encoding_t *encoding, const pm_buffer_t *buffer) { + const uint8_t *data = (const uint8_t *) pm_buffer_value(buffer); + size_t len = pm_buffer_length(buffer); + size_t i = 0; + + while (i < len) { + size_t group_start = i; + while (i < len && data[i] != 0x00) i++; + + for (size_t j = group_start; j < i; ) { + size_t width = encoding->char_width(data + j, (ptrdiff_t) (i - j)); + if (width == 0) return false; + j += width; + } + + if (i < len) i++; // skip sentinel + } + + return true; +} + +/** + * Format regexp source content for use in error messages, hex-escaping + * non-ASCII bytes. + */ +static void +pm_regexp_format_for_error(pm_buffer_t *buffer, const pm_encoding_t *encoding, const uint8_t *source, size_t length) { + size_t index = 0; + + if (encoding == PM_ENCODING_UTF_8_ENTRY) { + pm_buffer_append_string(buffer, (const char *) source, length); + return; + } + + while (index < length) { + if (source[index] < 0x80) { + pm_buffer_append_byte(buffer, source[index]); + index++; + } else if (encoding->multibyte) { + size_t width = encoding->char_width(source + index, (ptrdiff_t) (length - index)); + + if (width > 1) { + pm_buffer_append_string(buffer, "\\x{", 3); + for (size_t i = 0; i < width; i++) { + pm_buffer_append_format(buffer, "%02X", source[index + i]); + } + pm_buffer_append_byte(buffer, '}'); + index += width; + } else { + pm_buffer_append_format(buffer, "\\x%02X", source[index]); + index++; + } + } else { + pm_buffer_append_format(buffer, "\\x%02X", source[index]); + index++; + } + } +} + +/** + * Emit an encoding validation error on the regexp node. + */ +#define PM_REGEXP_ENCODING_ERROR(parser, diag_id, ...) \ + pm_diagnostic_list_append_format( \ + &(parser)->parser->error_list, \ + (uint32_t) ((parser)->node_start - (parser)->parser->start), \ + (uint32_t) ((parser)->node_end - (parser)->node_start), \ + diag_id, __VA_ARGS__) + +/** + * Validate encoding for a regexp with an encoding modifier (/e, /s, /u, /n). + * + * The decision tree is: + * + * 1. No escape-set encoding (explicit_encoding == NULL): + * a. ASCII-only content: validate property escapes, return forced US-ASCII + * for /n or the modifier flags for others. + * b. US-ASCII source with non-ASCII literals: emit per-byte errors. + * c. Source encoding differs from modifier encoding: emit mismatch error. + * + * 2. Mixed \u and \x escapes: emit the appropriate conflict error depending + * on the modifier and which escape type was last. + * + * 3. \u escape with non-/u modifier: incompatible encoding error. + * + * 4. Validate that hex escape byte sequences form valid multibyte characters + * in the modifier's encoding. + */ +static pm_node_flags_t +pm_regexp_validate_encoding_modifier(pm_regexp_parser_t *parser, bool ascii_only, pm_node_flags_t flags, char modifier, const pm_encoding_t *modifier_encoding, const char *source_start, int source_length) { + + if (parser->explicit_encoding == NULL) { + if (ascii_only) { + // Check property escapes against the modifier's encoding tier. + // /n (ASCII-8BIT): only POSIX properties are valid. + // /e, /s: POSIX and script properties are valid. + // /u: all properties are valid. + if (modifier == 'n' && parser->property_name != NULL) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_INVALID_CHAR_PROPERTY, + (int) parser->property_name_length, (const char *) parser->property_name, + source_length, source_start); + } else if (modifier != 'u' && parser->has_unicode_property_escape) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_INVALID_CHAR_PROPERTY, + (int) parser->unicode_property_name_length, (const char *) parser->unicode_property_name, + source_length, source_start); + } + return modifier == 'n' ? PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING : flags; + } + + if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) { + for (uint32_t i = 0; i < parser->non_ascii_literal_count; i++) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_INVALID_MULTIBYTE_CHAR, parser->encoding->name); + } + } else if (parser->encoding != modifier_encoding) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_ENCODING_OPTION_MISMATCH, modifier, parser->encoding->name); + + if (modifier == 'n' && !ascii_only) { + pm_buffer_t formatted = { 0 }; + pm_regexp_format_for_error(&formatted, parser->encoding, (const uint8_t *) source_start, (size_t) source_length); + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_NON_ESCAPED_MBC, (int) formatted.length, (const char *) formatted.value); + pm_buffer_free(&formatted); + } + } + + return flags; + } + + // Mixed unicode + hex escapes. + if (parser->has_unicode_escape && parser->has_hex_escape) { + if (modifier == 'n') { + if (parser->last_escape_was_unicode) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_UTF8_CHAR_NON_UTF8_REGEXP, source_length, source_start); + } else { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_ESCAPED_NON_ASCII_IN_UTF8, source_length, source_start); + } + } else { + if (!pm_regexp_validate_hex_escapes(modifier_encoding, &parser->hex_escape_buffer)) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_INVALID_MULTIBYTE_ESCAPE, source_length, source_start); + } + } + + return flags; + } + + if (modifier != 'u' && parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { + if (parser->last_escape_was_unicode) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_INCOMPAT_CHAR_ENCODING, source_length, source_start); + } else if (parser->encoding != PM_ENCODING_UTF_8_ENTRY) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_INCOMPAT_CHAR_ENCODING, source_length, source_start); + } + } + + if (modifier != 'n' && !pm_regexp_validate_hex_escapes(modifier_encoding, &parser->hex_escape_buffer)) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_INVALID_MULTIBYTE_ESCAPE, source_length, source_start); + } + + return flags; +} + +/** + * Validate encoding for a regexp without a modifier and compute the encoding + * flags to set on the node. + * + * The decision tree is: + * + * 1. If a modifier (/n, /u, /e, /s) is present, delegate to + * pm_regexp_validate_encoding_modifier. + * 2. Invalid multibyte chars or unicode ranges: suppress further checks (errors + * were already emitted during parsing). + * 3. US-ASCII source with non-ASCII literals: emit per-byte errors. + * 4. ASCII-only content: return forced US-ASCII (or forced UTF-8 if \p{...}). + * 5. Escape-set encoding present: validate hex escapes against the target + * encoding, handle mixed \u + \x conflicts, and return the appropriate + * forced encoding flag. + */ +static pm_node_flags_t +pm_regexp_validate_encoding(pm_regexp_parser_t *parser, bool ascii_only, pm_node_flags_t flags, const char *source_start, int source_length) { + + // Invalid multibyte characters suppress further validation. + // Errors were already emitted at the byte locations during parsing. + if (parser->has_invalid_multibyte) { + return flags; + } + + if (parser->invalid_unicode_range) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_INVALID_UNICODE_RANGE, source_length, source_start); + return flags; + } + + // Check modifier flags first. + if (flags & PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT) { + return pm_regexp_validate_encoding_modifier(parser, ascii_only, flags, 'n', PM_ENCODING_ASCII_8BIT_ENTRY, source_start, source_length); + } + if (flags & PM_REGULAR_EXPRESSION_FLAGS_UTF_8) { + return pm_regexp_validate_encoding_modifier(parser, ascii_only, flags, 'u', PM_ENCODING_UTF_8_ENTRY, source_start, source_length); + } + if (flags & PM_REGULAR_EXPRESSION_FLAGS_EUC_JP) { + return pm_regexp_validate_encoding_modifier(parser, ascii_only, flags, 'e', PM_ENCODING_EUC_JP_ENTRY, source_start, source_length); + } + if (flags & PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J) { + return pm_regexp_validate_encoding_modifier(parser, ascii_only, flags, 's', PM_ENCODING_WINDOWS_31J_ENTRY, source_start, source_length); + } + + // No modifier — check for non-ASCII literals in US-ASCII encoding. + if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY && parser->explicit_encoding == NULL && !ascii_only) { + for (uint32_t i = 0; i < parser->non_ascii_literal_count; i++) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_INVALID_MULTIBYTE_CHAR, parser->encoding->name); + } + } + + // ASCII-only regexps get downgraded to US-ASCII, unless property escapes + // force UTF-8. + if (ascii_only) { + if (parser->has_property_escape) { + return PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING; + } + return PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING; + } + + // Check explicit encoding from escape sequences. + if (parser->explicit_encoding != NULL) { + // Mixed unicode + hex escapes without modifier. + if (parser->has_unicode_escape && parser->has_hex_escape && parser->encoding != PM_ENCODING_UTF_8_ENTRY) { + if (parser->encoding != PM_ENCODING_US_ASCII_ENTRY && + parser->encoding != PM_ENCODING_ASCII_8BIT_ENTRY && + !pm_regexp_validate_hex_escapes(parser->encoding, &parser->hex_escape_buffer)) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_INVALID_MULTIBYTE_ESCAPE, source_length, source_start); + } else if (parser->last_escape_was_unicode) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_UTF8_CHAR_NON_UTF8_REGEXP, source_length, source_start); + } else { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_ESCAPED_NON_ASCII_IN_UTF8, source_length, source_start); + } + + return 0; + } + + if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { + if (!pm_regexp_validate_hex_escapes(parser->explicit_encoding, &parser->hex_escape_buffer)) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_INVALID_MULTIBYTE_ESCAPE, source_length, source_start); + } + + return PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING; + } else if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) { + return PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING; + } else { + if (!pm_regexp_validate_hex_escapes(parser->explicit_encoding, &parser->hex_escape_buffer)) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_INVALID_MULTIBYTE_ESCAPE, source_length, source_start); + } + } + } + + return 0; +} + +/** + * Parse a regular expression, validate its encoding, and optionally extract + * named capture groups. Encoding validation walks the raw source (content_loc) + * to distinguish escape-produced bytes from literal bytes. Named capture + * extraction walks the unescaped content since escape sequences in group names + * (e.g., line continuations) have already been processed by the lexer. + */ +PRISM_EXPORTED_FUNCTION pm_node_flags_t +pm_regexp_parse(pm_parser_t *parser, pm_regular_expression_node_t *node, pm_regexp_name_callback_t name_callback, pm_regexp_name_data_t *name_data) { + const uint8_t *source = parser->start + node->content_loc.start; + size_t size = node->content_loc.length; + bool extended_mode = PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED); + pm_node_flags_t flags = PM_NODE_FLAGS(node); + + const uint8_t *node_start = parser->start + node->base.location.start; + const uint8_t *node_end = parser->start + node->base.location.start + node->base.location.length; + + // First pass: walk raw source for encoding validation (no name extraction). + pm_regexp_parser_t regexp_parser = { + .parser = parser, + .start = source, + .cursor = source, + .end = source + size, + .extended_mode = extended_mode, + .encoding_changed = parser->encoding_changed, + .encoding = parser->encoding, + .name_callback = NULL, + .name_data = NULL, + .shared = true, + .node_start = node_start, + .node_end = node_end, + .has_unicode_escape = false, + .has_hex_escape = false, + .last_escape_was_unicode = false, + .explicit_encoding = NULL, + .has_property_escape = false, + .has_unicode_property_escape = false, + .property_name = NULL, + .property_name_length = 0, + .unicode_property_name = NULL, + .unicode_property_name_length = 0, + .non_ascii_literal_count = 0, + .invalid_unicode_range = false, + .hex_escape_buffer = { 0 }, + .hex_group_active = false, + .has_invalid_multibyte = false, + }; + + pm_regexp_parse_pattern(®exp_parser); + + // Compute ascii_only from the regexp parser's tracked state. We cannot + // use node->unescaped for this because regexp unescaped content preserves + // escape text (e.g., \x80 is 4 ASCII chars), not the binary values. + bool ascii_only = !regexp_parser.has_hex_escape && !regexp_parser.has_unicode_escape && regexp_parser.non_ascii_literal_count == 0; + // Use the unescaped content for error messages to match CRuby's format, + // where Ruby escapes like \M-\C-? are resolved to bytes but regexp escapes + // like \u{80} are preserved as text. + const char *error_source = (const char *) pm_string_source(&node->unescaped); + int error_source_length = (int) pm_string_length(&node->unescaped); + pm_node_flags_t encoding_flags = pm_regexp_validate_encoding(®exp_parser, ascii_only, flags, error_source, error_source_length); + pm_buffer_free(®exp_parser.hex_escape_buffer); + + // Second pass: walk unescaped content for named capture extraction. + if (name_callback != NULL) { + bool shared = node->unescaped.type == PM_STRING_SHARED; + pm_regexp_parse_named_captures(parser, pm_string_source(&node->unescaped), pm_string_length(&node->unescaped), shared, extended_mode, name_callback, name_data); + } + + return encoding_flags; +} + /** - * Parse a regular expression and extract the names of all of the named capture - * groups. + * Parse an interpolated regular expression for named capture groups only. + * This is used for the =~ operator with interpolated regexps where we don't + * have a pm_regular_expression_node_t. No encoding validation is performed. + * + * Note: The encoding-tracking fields (has_unicode_escape, has_hex_escape, etc.) + * are initialized but not used for the result. They exist because the parsing + * functions (pm_regexp_parse_backslash_escape, etc.) unconditionally update + * them as they walk through the content. */ -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) { +void +pm_regexp_parse_named_captures(pm_parser_t *parser, const uint8_t *source, size_t size, bool shared, bool extended_mode, pm_regexp_name_callback_t name_callback, pm_regexp_name_data_t *name_data) { + pm_regexp_parser_t regexp_parser = { .parser = parser, .start = source, .cursor = source, @@ -784,7 +1680,26 @@ pm_regexp_parse(pm_parser_t *parser, const uint8_t *source, size_t size, bool ex .encoding = parser->encoding, .name_callback = name_callback, .name_data = name_data, - .error_callback = error_callback, - .error_data = error_data - }); + .shared = shared, + .node_start = source, + .node_end = source + size, + .has_unicode_escape = false, + .has_hex_escape = false, + .last_escape_was_unicode = false, + .explicit_encoding = NULL, + .has_property_escape = false, + .has_unicode_property_escape = false, + .property_name = NULL, + .property_name_length = 0, + .unicode_property_name = NULL, + .unicode_property_name_length = 0, + .non_ascii_literal_count = 0, + .invalid_unicode_range = false, + .hex_escape_buffer = { 0 }, + .hex_group_active = false, + .has_invalid_multibyte = false, + }; + + pm_regexp_parse_pattern(®exp_parser); + pm_buffer_free(®exp_parser.hex_escape_buffer); } diff --git a/src/static_literals.c b/src/static_literals.c index 13a52378dd..f3a5650d31 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -7,7 +7,7 @@ */ typedef struct { /** The list of newline offsets to use to calculate line numbers. */ - const pm_newline_list_t *newline_list; + const pm_line_offset_list_t *line_offsets; /** The start of the source being parsed. */ const uint8_t *start; @@ -95,7 +95,7 @@ node_hash(const pm_static_literals_metadata_t *metadata, const pm_node_t *node) } case PM_SOURCE_LINE_NODE: { // Source lines hash their line number. - const pm_line_column_t line_column = pm_newline_list_line_column(metadata->newline_list, node->location.start, metadata->start_line); + const pm_line_column_t line_column = pm_line_offset_list_line_column(metadata->line_offsets, node->location.start, metadata->start_line); const int32_t *value = &line_column.line; return murmur_hash((const uint8_t *) value, sizeof(int32_t)); } @@ -183,7 +183,7 @@ pm_node_hash_insert(pm_node_hash_t *hash, const pm_static_literals_metadata_t *m } // Finally, free the old node list and update the hash. - xfree(hash->nodes); + xfree_sized(hash->nodes, hash->capacity * sizeof(pm_node_t *)); hash->nodes = new_nodes; hash->capacity = new_capacity; } @@ -221,7 +221,7 @@ pm_node_hash_insert(pm_node_hash_t *hash, const pm_static_literals_metadata_t *m */ static void pm_node_hash_free(pm_node_hash_t *hash) { - if (hash->capacity > 0) xfree(hash->nodes); + if (hash->capacity > 0) xfree_sized(hash->nodes, hash->capacity * sizeof(pm_node_t *)); } /** @@ -243,7 +243,7 @@ pm_int64_value(const pm_static_literals_metadata_t *metadata, const pm_node_t *n return integer->negative ? -value : value; } case PM_SOURCE_LINE_NODE: - return (int64_t) pm_newline_list_line_column(metadata->newline_list, node->location.start, metadata->start_line).line; + return (int64_t) pm_line_offset_list_line_column(metadata->line_offsets, node->location.start, metadata->start_line).line; default: assert(false && "unreachable"); return 0; @@ -356,14 +356,14 @@ 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, const uint8_t *start, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace) { +pm_static_literals_add(const pm_line_offset_list_t *line_offsets, const uint8_t *start, 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: return pm_node_hash_insert( &literals->integer_nodes, &(pm_static_literals_metadata_t) { - .newline_list = newline_list, + .line_offsets = line_offsets, .start = start, .start_line = start_line, .encoding_name = NULL @@ -376,7 +376,7 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, const uint8_t *sta return pm_node_hash_insert( &literals->float_nodes, &(pm_static_literals_metadata_t) { - .newline_list = newline_list, + .line_offsets = line_offsets, .start = start, .start_line = start_line, .encoding_name = NULL @@ -390,7 +390,7 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, const uint8_t *sta return pm_node_hash_insert( &literals->number_nodes, &(pm_static_literals_metadata_t) { - .newline_list = newline_list, + .line_offsets = line_offsets, .start = start, .start_line = start_line, .encoding_name = NULL @@ -404,7 +404,7 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, const uint8_t *sta return pm_node_hash_insert( &literals->string_nodes, &(pm_static_literals_metadata_t) { - .newline_list = newline_list, + .line_offsets = line_offsets, .start = start, .start_line = start_line, .encoding_name = NULL @@ -417,7 +417,7 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, const uint8_t *sta return pm_node_hash_insert( &literals->regexp_nodes, &(pm_static_literals_metadata_t) { - .newline_list = newline_list, + .line_offsets = line_offsets, .start = start, .start_line = start_line, .encoding_name = NULL @@ -430,7 +430,7 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, const uint8_t *sta return pm_node_hash_insert( &literals->symbol_nodes, &(pm_static_literals_metadata_t) { - .newline_list = newline_list, + .line_offsets = line_offsets, .start = start, .start_line = start_line, .encoding_name = NULL @@ -585,7 +585,7 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met break; } case PM_SOURCE_LINE_NODE: - pm_buffer_append_format(buffer, "%d", pm_newline_list_line_column(metadata->newline_list, node->location.start, metadata->start_line).line); + pm_buffer_append_format(buffer, "%d", pm_line_offset_list_line_column(metadata->line_offsets, node->location.start, metadata->start_line).line); break; case PM_STRING_NODE: { const pm_string_t *unescaped = &((const pm_string_node_t *) node)->unescaped; @@ -613,11 +613,11 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met * Create a string-based representation of the given static literal. */ void -pm_static_literal_inspect(pm_buffer_t *buffer, const pm_newline_list_t *newline_list, const uint8_t *start, int32_t start_line, const char *encoding_name, const pm_node_t *node) { +pm_static_literal_inspect(pm_buffer_t *buffer, const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, const char *encoding_name, const pm_node_t *node) { pm_static_literal_inspect_node( buffer, &(pm_static_literals_metadata_t) { - .newline_list = newline_list, + .line_offsets = line_offsets, .start = start, .start_line = start_line, .encoding_name = encoding_name diff --git a/src/util/pm_arena.c b/src/util/pm_arena.c new file mode 100644 index 0000000000..a9b69b3c8d --- /dev/null +++ b/src/util/pm_arena.c @@ -0,0 +1,105 @@ +#include "prism/util/pm_arena.h" + +/** + * Compute the block allocation size using offsetof so it is correct regardless + * of PM_FLEX_ARY_LEN. + */ +#define PM_ARENA_BLOCK_SIZE(data_size) (offsetof(pm_arena_block_t, data) + (data_size)) + +/** Initial block data size: 8 KB. */ +#define PM_ARENA_INITIAL_SIZE 8192 + +/** Double the block size every this many blocks. */ +#define PM_ARENA_GROWTH_INTERVAL 8 + +/** Maximum block data size: 1 MB. */ +#define PM_ARENA_MAX_SIZE (1024 * 1024) + +/** + * Compute the data size for the next block. + */ +static size_t +pm_arena_next_block_size(const pm_arena_t *arena, size_t min_size) { + size_t size = PM_ARENA_INITIAL_SIZE; + + for (size_t i = PM_ARENA_GROWTH_INTERVAL; i <= arena->block_count; i += PM_ARENA_GROWTH_INTERVAL) { + if (size < PM_ARENA_MAX_SIZE) size *= 2; + } + + return size > min_size ? size : min_size; +} + +/** + * Allocate memory from the arena. The returned memory is NOT zeroed. This + * function is infallible — it aborts on allocation failure. + */ +void * +pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment) { + // Try current block. + if (arena->current != NULL) { + size_t used_aligned = (arena->current->used + alignment - 1) & ~(alignment - 1); + size_t needed = used_aligned + size; + + // Guard against overflow in the alignment or size arithmetic. + if (used_aligned >= arena->current->used && needed >= used_aligned && needed <= arena->current->capacity) { + arena->current->used = needed; + return arena->current->data + used_aligned; + } + } + + // Allocate new block via xmalloc — memory is NOT zeroed. + // New blocks from xmalloc are max-aligned, so data[] starts aligned for + // any C type. No padding needed at the start. + size_t block_data_size = pm_arena_next_block_size(arena, size); + pm_arena_block_t *block = (pm_arena_block_t *) xmalloc(PM_ARENA_BLOCK_SIZE(block_data_size)); + + if (block == NULL) { + fprintf(stderr, "prism: out of memory; aborting\n"); + abort(); + } + + block->capacity = block_data_size; + block->used = size; + block->prev = arena->current; + arena->current = block; + arena->block_count++; + + return block->data; +} + +/** + * Allocate zero-initialized memory from the arena. This function is infallible + * — it aborts on allocation failure. + */ +void * +pm_arena_zalloc(pm_arena_t *arena, size_t size, size_t alignment) { + void *ptr = pm_arena_alloc(arena, size, alignment); + memset(ptr, 0, size); + return ptr; +} + +/** + * Allocate memory from the arena and copy the given data into it. + */ +void * +pm_arena_memdup(pm_arena_t *arena, const void *src, size_t size, size_t alignment) { + void *dst = pm_arena_alloc(arena, size, alignment); + memcpy(dst, src, size); + return dst; +} + +/** + * Free all blocks in the arena. + */ +void +pm_arena_free(pm_arena_t *arena) { + pm_arena_block_t *block = arena->current; + + while (block != NULL) { + pm_arena_block_t *prev = block->prev; + xfree_sized(block, PM_ARENA_BLOCK_SIZE(block->capacity)); + block = prev; + } + + *arena = (pm_arena_t) { 0 }; +} diff --git a/src/util/pm_buffer.c b/src/util/pm_buffer.c index 2136a7c43e..9e392427c6 100644 --- a/src/util/pm_buffer.c +++ b/src/util/pm_buffer.c @@ -50,6 +50,7 @@ pm_buffer_length(const pm_buffer_t *buffer) { static inline bool pm_buffer_append_length(pm_buffer_t *buffer, size_t length) { size_t next_length = buffer->length + length; + const size_t original_capacity = buffer->capacity; if (next_length > buffer->capacity) { if (buffer->capacity == 0) { @@ -60,7 +61,7 @@ pm_buffer_append_length(pm_buffer_t *buffer, size_t length) { buffer->capacity *= 2; } - buffer->value = xrealloc(buffer->value, buffer->capacity); + buffer->value = xrealloc_sized(buffer->value, buffer->capacity, original_capacity); if (buffer->value == NULL) return false; } @@ -353,5 +354,5 @@ pm_buffer_insert(pm_buffer_t *buffer, size_t index, const char *value, size_t le */ void pm_buffer_free(pm_buffer_t *buffer) { - xfree(buffer->value); + xfree_sized(buffer->value, buffer->capacity); } diff --git a/src/util/pm_char.c b/src/util/pm_char.c index 748582b7fe..f0baf47784 100644 --- a/src/util/pm_char.c +++ b/src/util/pm_char.c @@ -83,7 +83,7 @@ pm_strspn_whitespace(const uint8_t *string, ptrdiff_t length) { * searching past the given maximum number of characters. */ size_t -pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_newline_list_t *newline_list, uint32_t start_offset) { +pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_line_offset_list_t *line_offsets, uint32_t start_offset) { if (length <= 0) return 0; uint32_t size = 0; @@ -91,7 +91,7 @@ pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_newlin while (size < maximum && (pm_byte_table[string[size]] & PRISM_CHAR_BIT_WHITESPACE)) { if (string[size] == '\n') { - pm_newline_list_append(newline_list, start_offset + size + 1); + pm_line_offset_list_append(line_offsets, start_offset + size + 1); } size++; diff --git a/src/util/pm_constant_pool.c b/src/util/pm_constant_pool.c index 922ce6a18c..f7173dd062 100644 --- a/src/util/pm_constant_pool.c +++ b/src/util/pm_constant_pool.c @@ -1,4 +1,5 @@ #include "prism/util/pm_constant_pool.h" +#include "prism/util/pm_arena.h" /** * Initialize a list of constant ids. @@ -14,10 +15,9 @@ pm_constant_id_list_init(pm_constant_id_list_t *list) { * Initialize a list of constant ids with a given capacity. */ void -pm_constant_id_list_init_capacity(pm_constant_id_list_t *list, size_t capacity) { +pm_constant_id_list_init_capacity(pm_arena_t *arena, pm_constant_id_list_t *list, size_t capacity) { if (capacity) { - list->ids = xcalloc(capacity, sizeof(pm_constant_id_t)); - if (list->ids == NULL) abort(); + list->ids = (pm_constant_id_t *) pm_arena_zalloc(arena, capacity * sizeof(pm_constant_id_t), PRISM_ALIGNOF(pm_constant_id_t)); } else { list->ids = NULL; } @@ -27,19 +27,23 @@ pm_constant_id_list_init_capacity(pm_constant_id_list_t *list, size_t capacity) } /** - * Append a constant id to a list of constant ids. Returns false if any - * potential reallocations fail. + * Append a constant id to a list of constant ids. */ -bool -pm_constant_id_list_append(pm_constant_id_list_t *list, pm_constant_id_t id) { +void +pm_constant_id_list_append(pm_arena_t *arena, pm_constant_id_list_t *list, pm_constant_id_t id) { if (list->size >= list->capacity) { - list->capacity = list->capacity == 0 ? 8 : list->capacity * 2; - list->ids = (pm_constant_id_t *) xrealloc(list->ids, sizeof(pm_constant_id_t) * list->capacity); - if (list->ids == NULL) return false; + size_t new_capacity = list->capacity == 0 ? 8 : list->capacity * 2; + pm_constant_id_t *new_ids = (pm_constant_id_t *) pm_arena_alloc(arena, sizeof(pm_constant_id_t) * new_capacity, PRISM_ALIGNOF(pm_constant_id_t)); + + if (list->size > 0) { + memcpy(new_ids, list->ids, list->size * sizeof(pm_constant_id_t)); + } + + list->ids = new_ids; + list->capacity = new_capacity; } list->ids[list->size++] = id; - return true; } /** @@ -65,16 +69,6 @@ pm_constant_id_list_includes(pm_constant_id_list_t *list, pm_constant_id_t id) { return false; } -/** - * Free the memory associated with a list of constant ids. - */ -void -pm_constant_id_list_free(pm_constant_id_list_t *list) { - if (list->ids != NULL) { - xfree(list->ids); - } -} - /** * A relatively simple hash function (djb2) that is used to hash strings. We are * optimizing here for simplicity and speed. @@ -165,7 +159,7 @@ pm_constant_pool_resize(pm_constant_pool_t *pool) { // pool->constants and pool->buckets are allocated out of the same chunk // of memory, with the buckets coming first. - xfree(pool->buckets); + xfree_sized(pool->buckets, pool->capacity * element_size); pool->constants = next_constants; pool->buckets = next_buckets; pool->capacity = next_capacity; @@ -257,12 +251,12 @@ pm_constant_pool_insert(pm_constant_pool_t *pool, const uint8_t *start, size_t l // an existing constant, then either way we don't want the given // memory. Either it's duplicated with the existing constant or // it's not necessary because we have a shared version. - xfree((void *) start); + xfree_sized((void *) start, length); } else if (bucket->type == PM_CONSTANT_POOL_BUCKET_OWNED) { // If we're attempting to insert a shared constant and the // existing constant is owned, then we can free the owned // constant and replace it with the shared constant. - xfree((void *) constant->start); + xfree_sized((void *) constant->start, constant->length); constant->start = start; bucket->type = (unsigned int) (type & 0x3); } @@ -334,9 +328,9 @@ pm_constant_pool_free(pm_constant_pool_t *pool) { // If an id is set on this constant, then we know we have content here. if (bucket->id != PM_CONSTANT_ID_UNSET && bucket->type == PM_CONSTANT_POOL_BUCKET_OWNED) { pm_constant_t *constant = &pool->constants[bucket->id - 1]; - xfree((void *) constant->start); + xfree_sized((void *) constant->start, constant->length); } } - xfree(pool->buckets); + xfree_sized(pool->buckets, pool->capacity * (sizeof(pm_constant_pool_bucket_t) + sizeof(pm_constant_t))); } diff --git a/src/util/pm_integer.c b/src/util/pm_integer.c index 4170ecc58d..2b77a4b5d2 100644 --- a/src/util/pm_integer.c +++ b/src/util/pm_integer.c @@ -374,7 +374,7 @@ pm_integer_convert_base(pm_integer_t *destination, const pm_integer_t *source, u } } - xfree(bigints); + xfree_sized(bigints, bigints_length * sizeof(pm_integer_t)); bigints = next_bigints; bigints_length = next_length; } @@ -383,7 +383,7 @@ pm_integer_convert_base(pm_integer_t *destination, const pm_integer_t *source, u destination->negative = source->negative; pm_integer_normalize(destination); - xfree(bigints); + xfree_sized(bigints, bigints_length * sizeof(pm_integer_t)); pm_integer_free(&base); } @@ -422,7 +422,7 @@ pm_integer_parse_powof2(pm_integer_t *integer, uint32_t base, const uint8_t *dig static void pm_integer_parse_decimal(pm_integer_t *integer, const uint8_t *digits, size_t digits_length) { const size_t batch = 9; - size_t length = (digits_length + batch - 1) / batch; + const size_t length = (digits_length + batch - 1) / batch; uint32_t *values = (uint32_t *) xcalloc(length, sizeof(uint32_t)); uint32_t value = 0; @@ -439,7 +439,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) { .length = length, .values = values, .value = 0, .negative = false }), 1000000000, ((uint64_t) 1 << 32)); - xfree(values); + xfree_sized(values, length * sizeof(uint32_t)); } /** @@ -448,7 +448,8 @@ pm_integer_parse_decimal(pm_integer_t *integer, const uint8_t *digits, size_t di static void pm_integer_parse_big(pm_integer_t *integer, uint32_t multiplier, const uint8_t *start, const uint8_t *end) { // Allocate an array to store digits. - uint8_t *digits = xmalloc(sizeof(uint8_t) * (size_t) (end - start)); + const size_t digits_capa = sizeof(uint8_t) * (size_t) (end - start); + uint8_t *digits = xmalloc(digits_capa); size_t digits_length = 0; for (; start < end; start++) { @@ -463,7 +464,7 @@ pm_integer_parse_big(pm_integer_t *integer, uint32_t multiplier, const uint8_t * pm_integer_parse_powof2(integer, multiplier, digits, digits_length); } - xfree(digits); + xfree_sized(digits, digits_capa); } /** @@ -635,7 +636,7 @@ pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer) { } // Allocate a buffer that we'll copy the decimal digits into. - size_t digits_length = converted.length * 9; + const size_t digits_length = converted.length * 9; char *digits = xcalloc(digits_length, sizeof(char)); if (digits == NULL) return; @@ -654,7 +655,7 @@ pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer) { // Finally, append the string to the buffer and free the digits. pm_buffer_append_string(buffer, digits + start_offset, digits_length - start_offset); - xfree(digits); + xfree_sized(digits, sizeof(char) * digits_length); pm_integer_free(&converted); } diff --git a/src/util/pm_newline_list.c b/src/util/pm_line_offset_list.c similarity index 80% rename from src/util/pm_newline_list.c rename to src/util/pm_line_offset_list.c index 89c294a6d7..d55b2f6874 100644 --- a/src/util/pm_newline_list.c +++ b/src/util/pm_line_offset_list.c @@ -1,11 +1,11 @@ -#include "prism/util/pm_newline_list.h" +#include "prism/util/pm_line_offset_list.h" /** * Initialize a new newline list with the given capacity. Returns true if the * allocation of the offsets succeeds, otherwise returns false. */ bool -pm_newline_list_init(pm_newline_list_t *list, size_t capacity) { +pm_line_offset_list_init(pm_line_offset_list_t *list, size_t capacity) { list->offsets = (uint32_t *) xcalloc(capacity, sizeof(uint32_t)); if (list->offsets == NULL) return false; @@ -21,7 +21,7 @@ pm_newline_list_init(pm_newline_list_t *list, size_t capacity) { * Clear out the newlines that have been appended to the list. */ void -pm_newline_list_clear(pm_newline_list_t *list) { +pm_line_offset_list_clear(pm_line_offset_list_t *list) { list->size = 1; } @@ -30,7 +30,7 @@ pm_newline_list_clear(pm_newline_list_t *list) { * the offsets succeeds (if one was necessary), otherwise returns false. */ bool -pm_newline_list_append(pm_newline_list_t *list, uint32_t cursor) { +pm_line_offset_list_append(pm_line_offset_list_t *list, uint32_t cursor) { if (list->size == list->capacity) { uint32_t *original_offsets = list->offsets; @@ -39,7 +39,7 @@ pm_newline_list_append(pm_newline_list_t *list, uint32_t cursor) { if (list->offsets == NULL) return false; memcpy(list->offsets, original_offsets, list->size * sizeof(uint32_t)); - xfree(original_offsets); + xfree_sized(original_offsets, list->size * sizeof(uint32_t)); } assert(list->size == 0 || cursor > list->offsets[list->size - 1]); @@ -53,7 +53,7 @@ pm_newline_list_append(pm_newline_list_t *list, uint32_t cursor) { * line of the closest offset less than the given offset is returned. */ int32_t -pm_newline_list_line(const pm_newline_list_t *list, uint32_t cursor, int32_t start_line) { +pm_line_offset_list_line(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) { size_t left = 0; size_t right = list->size - 1; @@ -80,7 +80,7 @@ pm_newline_list_line(const pm_newline_list_t *list, uint32_t cursor, int32_t sta * are returned. */ pm_line_column_t -pm_newline_list_line_column(const pm_newline_list_t *list, uint32_t cursor, int32_t start_line) { +pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) { size_t left = 0; size_t right = list->size - 1; @@ -108,6 +108,6 @@ pm_newline_list_line_column(const pm_newline_list_t *list, uint32_t cursor, int3 * Free the internal memory allocated for the newline list. */ void -pm_newline_list_free(pm_newline_list_t *list) { - xfree(list->offsets); +pm_line_offset_list_free(pm_line_offset_list_t *list) { + xfree_sized(list->offsets, list->capacity * sizeof(uint32_t)); } diff --git a/src/util/pm_list.c b/src/util/pm_list.c index ad2294cd60..940baffb64 100644 --- a/src/util/pm_list.c +++ b/src/util/pm_list.c @@ -41,7 +41,7 @@ pm_list_free(pm_list_t *list) { while (node != NULL) { next = node->next; - xfree(node); + xfree_sized(node, sizeof(pm_list_node_t)); node = next; } diff --git a/src/util/pm_string.c b/src/util/pm_string.c index a7493c468b..5ba8c78ec1 100644 --- a/src/util/pm_string.c +++ b/src/util/pm_string.c @@ -71,9 +71,10 @@ 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)); + const size_t path_size = sizeof(WCHAR) * ((size_t) length); + handle->path = xmalloc(path_size); if ((handle->path == NULL) || (MultiByteToWideChar(CP_UTF8, 0, filepath, -1, handle->path, length) == 0)) { - xfree(handle->path); + xfree_sized(handle->path, path_size); return PM_STRING_INIT_ERROR_GENERIC; } @@ -88,7 +89,7 @@ pm_string_file_handle_open(pm_string_file_handle_t *handle, const char *filepath } } - xfree(handle->path); + xfree_sized(handle->path, path_size); return result; } @@ -215,7 +216,7 @@ pm_string_file_init(pm_string_t *string, const char *filepath) { if (result != PM_STRING_INIT_SUCCESS) return result; // Get the file size. - DWORD file_size = GetFileSize(handle.file, NULL); + const DWORD file_size = GetFileSize(handle.file, NULL); if (file_size == INVALID_FILE_SIZE) { pm_string_file_handle_close(&handle); return PM_STRING_INIT_ERROR_GENERIC; @@ -245,7 +246,7 @@ pm_string_file_init(pm_string_t *string, const char *filepath) { // Check the number of bytes read if (bytes_read != file_size) { - xfree(source); + xfree_sized(source, file_size); pm_string_file_handle_close(&handle); return PM_STRING_INIT_ERROR_GENERIC; } @@ -281,7 +282,7 @@ pm_string_file_init(pm_string_t *string, const char *filepath) { return PM_STRING_INIT_SUCCESS; } - size_t length = (size_t) size; + const size_t length = (size_t) size; uint8_t *source = xmalloc(length); if (source == NULL) { close(fd); @@ -292,7 +293,7 @@ pm_string_file_init(pm_string_t *string, const char *filepath) { close(fd); if (bytes_read == -1) { - xfree(source); + xfree_sized(source, length); return PM_STRING_INIT_ERROR_GENERIC; } diff --git a/templates/ext/prism/api_node.c.erb b/templates/ext/prism/api_node.c.erb index e9c3742085..e3bcf116cc 100644 --- a/templates/ext/prism/api_node.c.erb +++ b/templates/ext/prism/api_node.c.erb @@ -76,9 +76,9 @@ VALUE pm_source_new(const pm_parser_t *parser, rb_encoding *encoding, bool freeze) { VALUE source_string = rb_enc_str_new((const char *) parser->start, parser->end - parser->start, encoding); - VALUE offsets = rb_ary_new_capa(parser->newline_list.size); - for (size_t index = 0; index < parser->newline_list.size; index++) { - rb_ary_push(offsets, ULONG2NUM(parser->newline_list.offsets[index])); + VALUE offsets = rb_ary_new_capa(parser->line_offsets.size); + for (size_t index = 0; index < parser->line_offsets.size; index++) { + rb_ary_push(offsets, ULONG2NUM(parser->line_offsets.offsets[index])); } if (freeze) { @@ -113,7 +113,7 @@ pm_node_stack_pop(pm_node_stack_node_t **stack) { const pm_node_t *visit = current->visit; *stack = current->prev; - xfree(current); + xfree_sized(current, sizeof(pm_node_stack_node_t)); return visit; } diff --git a/templates/include/prism/node_new.h.erb b/templates/include/prism/node_new.h.erb new file mode 100644 index 0000000000..56c214e006 --- /dev/null +++ b/templates/include/prism/node_new.h.erb @@ -0,0 +1,42 @@ +/** + * @file node_new.h + * + * Static inline functions for allocating and initializing AST nodes. + * + * -- + */ +#ifndef PRISM_NODE_NEW_H +#define PRISM_NODE_NEW_H + +#include "prism/node.h" + +<%- nodes.each do |node| -%> +<%- params = node.fields.map(&:c_param) -%> +/** + * Allocate and initialize a new <%= node.name %> node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. +<%- node.fields.each do |field| -%> + * @param <%= field.name %> <%= field.comment ? Prism::Template::Doxygen.verbatim(field.comment.lines.first.strip) : "The #{field.name} field." %> +<%- end -%> + * @return The newly allocated and initialized node. + */ +static inline pm_<%= node.human %>_t * +pm_<%= node.human %>_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location<%= params.empty? ? "" : ", #{params.join(", ")}" %>) { + pm_<%= node.human %>_t *node = (pm_<%= node.human %>_t *) pm_arena_alloc(arena, sizeof(pm_<%= node.human %>_t), PRISM_ALIGNOF(pm_<%= node.human %>_t)); + + *node = (pm_<%= node.human %>_t) { + .base = { .type = <%= node.type %>, .flags = flags, .node_id = node_id, .location = location }<%= node.fields.empty? ? "" : "," %> +<%- node.fields.each_with_index do |field, index| -%> + .<%= field.name %> = <%= field.name %><%= index < node.fields.size - 1 ? "," : "" %> +<%- end -%> + }; + + return node; +} + +<%- end -%> +#endif diff --git a/templates/java/org/prism/AbstractNodeVisitor.java.erb b/templates/java/org/ruby_lang/prism/AbstractNodeVisitor.java.erb similarity index 94% rename from templates/java/org/prism/AbstractNodeVisitor.java.erb rename to templates/java/org/ruby_lang/prism/AbstractNodeVisitor.java.erb index a66daedf63..58eabebae8 100644 --- a/templates/java/org/prism/AbstractNodeVisitor.java.erb +++ b/templates/java/org/ruby_lang/prism/AbstractNodeVisitor.java.erb @@ -1,4 +1,4 @@ -package org.prism; +package org.ruby_lang.prism; // GENERATED BY <%= File.basename(__FILE__) %> // @formatter:off diff --git a/templates/java/org/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb similarity index 84% rename from templates/java/org/prism/Loader.java.erb rename to templates/java/org/ruby_lang/prism/Loader.java.erb index aa8e1e30c9..e2fe114ca9 100644 --- a/templates/java/org/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -1,7 +1,7 @@ <%- string_type = Prism::Template::JAVA_STRING_TYPE -%> -package org.prism; +package org.ruby_lang.prism; -import org.prism.Nodes; +import org.ruby_lang.prism.Nodes; import java.lang.Short; import java.math.BigInteger; @@ -16,7 +16,7 @@ import java.util.Locale; public class Loader { public static ParseResult load(byte[] serialized, byte[] sourceBytes) { - return new Loader(serialized, sourceBytes).load(); + return new Loader(serialized).load(sourceBytes); } // Overridable methods @@ -40,13 +40,11 @@ public class Loader { private static final class ConstantPool { private final Loader loader; - private final byte[] source; private final int bufferOffset; private final <%= string_type %>[] cache; - ConstantPool(Loader loader, byte[] source, int bufferOffset, int length) { + ConstantPool(Loader loader, int bufferOffset, int length) { this.loader = loader; - this.source = source; this.bufferOffset = bufferOffset; cache = new <%= string_type %>[length]; } @@ -61,15 +59,7 @@ public class Loader { int length = buffer.getInt(offset + 4); byte[] bytes = new byte[length]; - - if (Integer.compareUnsigned(start, 0x7FFFFFFF) <= 0) { - System.arraycopy(source, start, bytes, 0, length); - } else { - int position = buffer.position(); - buffer.position(start & 0x7FFFFFFF); - buffer.get(bytes, 0, length); - buffer.position(position); - } + buffer.get(start, bytes); constant = loader.bytesToName(bytes); cache[index] = constant; @@ -81,19 +71,21 @@ public class Loader { } private final ByteBuffer buffer; - private final Nodes.Source source; protected String encodingName; <%- if string_type == "String" -%> private Charset encodingCharset; <%- end -%> private ConstantPool constantPool; - protected Loader(byte[] serialized, byte[] sourceBytes) { + protected Loader(byte[] serialized) { this.buffer = ByteBuffer.wrap(serialized).order(ByteOrder.nativeOrder()); - this.source = new Nodes.Source(sourceBytes); } - protected ParseResult load() { + // We pass sourceBytes here and not in the constructor to avoid keeping + // the sourceBytes in memory unnecessarily with lazy DefNode's which hold on the Loader. + protected ParseResult load(byte[] sourceBytes) { + Nodes.Source source = new Nodes.Source(sourceBytes); + expect((byte) 'P', "incorrect prism header"); expect((byte) 'R', "incorrect prism header"); expect((byte) 'I', "incorrect prism header"); @@ -122,10 +114,11 @@ public class Loader { Nodes.Location dataLocation = loadOptionalLocation(); ParseResult.Error[] errors = loadErrors(); ParseResult.Warning[] warnings = loadWarnings(); + boolean continuable = buffer.get() != 0; int constantPoolBufferOffset = buffer.getInt(); int constantPoolLength = loadVarUInt(); - this.constantPool = new ConstantPool(this, source.bytes, constantPoolBufferOffset, constantPoolLength); + this.constantPool = new ConstantPool(this, constantPoolBufferOffset, constantPoolLength); Nodes.Node node; if (errors.length == 0) { @@ -143,31 +136,16 @@ public class Loader { node = null; } - return new ParseResult(node, magicComments, dataLocation, errors, warnings, source); + return new ParseResult(node, magicComments, dataLocation, errors, warnings, continuable, source); } - private byte[] loadEmbeddedString() { + private byte[] loadString() { int length = loadVarUInt(); byte[] bytes = new byte[length]; buffer.get(bytes); return bytes; } - private byte[] loadString() { - switch (buffer.get()) { - case 1: - int start = loadVarUInt(); - int length = loadVarUInt(); - byte[] bytes = new byte[length]; - System.arraycopy(source.bytes, start, bytes, 0, length); - return bytes; - case 2: - return loadEmbeddedString(); - default: - throw new Error("Expected 0 or 1 but was " + buffer.get()); - } - } - private int[] loadLineOffsets() { int count = loadVarUInt(); int[] lineOffsets = new int[count]; @@ -199,7 +177,7 @@ public class Loader { // error messages only contain ASCII characters for (int i = 0; i < count; i++) { Nodes.ErrorType type = Nodes.ERROR_TYPES[loadVarUInt()]; - byte[] bytes = loadEmbeddedString(); + byte[] bytes = loadString(); String message = new String(bytes, StandardCharsets.US_ASCII); Nodes.Location location = loadLocation(); ParseResult.ErrorLevel level = ParseResult.ERROR_LEVELS[buffer.get()]; @@ -218,7 +196,7 @@ public class Loader { // warning messages only contain ASCII characters for (int i = 0; i < count; i++) { Nodes.WarningType type = Nodes.WARNING_TYPES[loadVarUInt() - <%= errors.length %>]; - byte[] bytes = loadEmbeddedString(); + byte[] bytes = loadString(); String message = new String(bytes, StandardCharsets.US_ASCII); Nodes.Location location = loadLocation(); ParseResult.WarningLevel level = ParseResult.WARNING_LEVELS[buffer.get()]; @@ -356,6 +334,10 @@ public class Loader { return negative ? result.negate() : result; } + <%- + base_params = [*("nodeId" if Prism::Template::INCLUDE_NODE_ID), "startOffset", "length"] + base_params_sig = base_params.map { "int #{_1}" }.join(", ") + -%> private Nodes.Node loadNode() { int type = buffer.get() & 0xFF; <%- if Prism::Template::INCLUDE_NODE_ID -%> @@ -372,7 +354,7 @@ public class Loader { params = [] params << "nodeId" if Prism::Template::INCLUDE_NODE_ID params << "startOffset" << "length" - params << "buffer.getInt()" if node.needs_serialized_length? + params << "buffer.getInt()" << "null" if node.needs_serialized_length? params << "loadFlags()" if node.flags params.concat node.semantic_fields.map { |field| case field @@ -395,13 +377,44 @@ public class Loader { else raise end } + $DefNode_params = params if node.name == "DefNode" -%> + <%- if node.name == "DefNode" -%> + return loadDefNode(<%= base_params.join(", ") -%>); + <%- else -%> return new Nodes.<%= node.name %>(<%= params.join(", ") -%>); + <%- end -%> <%- end -%> default: throw new Error("Unknown node type: " + type); } } + + // Can be overridden to use createLazyDefNode instead + protected Nodes.DefNode loadDefNode(<%= base_params_sig -%>) { + return createDefNode(<%= base_params.join(", ") -%>); + } + + protected Nodes.DefNode createLazyDefNode(<%= base_params_sig -%>) { + int bufferPosition = buffer.position(); + int serializedLength = buffer.getInt(); + // Load everything except the body and locals, because the name, receiver, parameters are still needed for lazily defining the method + Nodes.DefNode lazyDefNode = new Nodes.DefNode(<%= base_params.join(", ") -%>, -bufferPosition, this, loadConstant(), loadOptionalNode(), (Nodes.ParametersNode) loadOptionalNode(), null, Nodes.EMPTY_STRING_ARRAY); + buffer.position(bufferPosition + serializedLength); // skip past the serialized DefNode + return lazyDefNode; + } + + protected Nodes.DefNode createDefNode(<%= base_params_sig -%>) { + return new Nodes.DefNode(<%= $DefNode_params.join(", ") -%>); + } + + Nodes.DefNode createDefNodeFromSavedPosition(<%= base_params_sig -%>, int bufferPosition) { + // This method mutates the buffer position and may be called from different threads so we must synchronize + synchronized (this) { + buffer.position(bufferPosition); + return createDefNode(<%= base_params.join(", ") -%>); + } + } <%- array_types.uniq.each do |type| -%> private static final Nodes.<%= type %>[] EMPTY_<%= type %>_ARRAY = {}; diff --git a/templates/java/org/prism/Nodes.java.erb b/templates/java/org/ruby_lang/prism/Nodes.java.erb similarity index 94% rename from templates/java/org/prism/Nodes.java.erb rename to templates/java/org/ruby_lang/prism/Nodes.java.erb index 8b0a9ce20d..e234faa6f5 100644 --- a/templates/java/org/prism/Nodes.java.erb +++ b/templates/java/org/ruby_lang/prism/Nodes.java.erb @@ -1,5 +1,5 @@ <%- string_type = Prism::Template::JAVA_STRING_TYPE -%> -package org.prism; +package org.ruby_lang.prism; import java.lang.Override; import java.lang.String; @@ -142,7 +142,7 @@ public abstract class Nodes { protected abstract String toString(String indent); } -<%# FLAGS -%> +<%-# FLAGS -%> <%- flags.each do |flag| -%> /** @@ -194,7 +194,7 @@ public abstract class Nodes { <%- end -%> } <%- end -%> -<%# NODES -%> +<%-# NODES -%> <%- nodes.each do |node| -%> /** @@ -207,6 +207,7 @@ public abstract class Nodes { public static final class <%= node.name -%> extends Node { <%- if node.needs_serialized_length? -%> public final int serializedLength; + public final Loader loader; <%- end -%> <%- if node.flags -%> public final short flags; @@ -234,7 +235,10 @@ public abstract class Nodes { params = [] params << "int nodeId" if Prism::Template::INCLUDE_NODE_ID params << "int startOffset" << "int length" - params << "int serializedLength" if node.needs_serialized_length? + if node.needs_serialized_length? + params << "int serializedLength" + params << "Loader loader" + end params << "short flags" if node.flags params.concat(node.semantic_fields.map { |field| "#{field.java_type} #{field.name}" }) -%> @@ -246,6 +250,7 @@ public abstract class Nodes { <%- end -%> <%- if node.needs_serialized_length? -%> this.serializedLength = serializedLength; + this.loader = loader; <%- end -%> <%- if node.flags -%> this.flags = flags; @@ -254,7 +259,22 @@ public abstract class Nodes { this.<%= field.name %> = <%= field.name %>; <%- end -%> } - <%# methods for flags -%> + <%-# extra methods for DefNode -%> + <%- if node.needs_serialized_length? -%> + + public boolean isLazy() { + return serializedLength < 0; + } + + public <%= node.name -%> getNonLazy() { + if (isLazy()) { + return loader.createDefNodeFromSavedPosition(<%= "nodeId, " if Prism::Template::INCLUDE_NODE_ID %>startOffset, length, -serializedLength); + } else { + return this; + } + } + <%- end -%> + <%-# methods for flags -%> <%- if (node_flags = node.flags) -%> <%- node_flags.values.each do |value| -%> @@ -263,7 +283,7 @@ public abstract class Nodes { } <%- end -%> <%- end -%> - <%# potential override of setNewLineFlag() -%> + <%-# potential override of setNewLineFlag() -%> <%- if node.newline == false -%> @Override diff --git a/templates/javascript/src/deserialize.js.erb b/templates/javascript/src/deserialize.js.erb index 7aebee750c..34ff1574da 100644 --- a/templates/javascript/src/deserialize.js.erb +++ b/templates/javascript/src/deserialize.js.erb @@ -29,8 +29,7 @@ class SerializationBuffer { ["ascii-8bit", "ascii"] ]); - constructor(source, array) { - this.source = source; + constructor(array) { this.array = array; this.index = 0; this.fileEncoding = "utf-8"; @@ -96,32 +95,15 @@ class SerializationBuffer { readStringField(flags) { if (flags === undefined) flags = 0; - const type = this.readByte(); - - switch (type) { - case 1: { - const startOffset = this.readVarInt(); - const length = this.readVarInt(); - return this.decodeString(this.source.slice(startOffset, startOffset + length), flags); - } - case 2: - return this.decodeString(this.readBytes(this.readVarInt()), flags); - default: - throw new Error(`Unknown serialized string type: ${type}`); - } + return this.decodeString(this.readBytes(this.readVarInt()), flags); } scanConstant(constantPoolOffset, constantIndex) { const offset = constantPoolOffset + constantIndex * 8; - let startOffset = this.scanUint32(offset); + const startOffset = this.scanUint32(offset); const length = this.scanUint32(offset + 4); - if (startOffset & (1 << 31)) { - startOffset &= (1 << 31) - 1; - return new TextDecoder().decode(this.array.slice(startOffset, startOffset + length)); - } else { - return new TextDecoder().decode(this.source.slice(startOffset, startOffset + length)); - } + return this.getDecoder(this.fileEncoding).decode(this.array.slice(startOffset, startOffset + length)); } readDouble() { @@ -293,13 +275,12 @@ const warningTypes = [ * Accept two Uint8Arrays, one for the source and one for the serialized format. * Return the AST corresponding to the serialized form. * - * @param {Uint8Array} source * @param {Uint8Array} array * @returns {ParseResult} * @throws {Error} */ -export function deserialize(source, array) { - const buffer = new SerializationBuffer(source, array); +export function deserialize(array) { + const buffer = new SerializationBuffer(array); if (buffer.readString(5) !== "PRISM") { throw new Error("Invalid serialization"); @@ -353,10 +334,12 @@ export function deserialize(source, array) { level: warningLevels[buffer.readByte()] })); + const continuable = buffer.readByte() !== 0; + const constantPoolOffset = buffer.readUint32(); const constants = Array.from({ length: buffer.readVarInt() }, () => null); - return new ParseResult(readRequiredNode(), comments, magicComments, dataLoc, errors, warnings); + return new ParseResult(readRequiredNode(), comments, magicComments, dataLoc, errors, warnings, continuable); function readRequiredNode() { const type = buffer.readByte(); diff --git a/templates/lib/prism/compiler.rb.erb b/templates/lib/prism/compiler.rb.erb index 66dbe666b9..13317cac04 100644 --- a/templates/lib/prism/compiler.rb.erb +++ b/templates/lib/prism/compiler.rb.erb @@ -1,3 +1,6 @@ +#-- +# rbs_inline: enabled + module Prism # A compiler is a visitor that returns the value of each node as it visits. # This is as opposed to a visitor which will only walk the tree. This can be @@ -18,24 +21,30 @@ module Prism # class Compiler < Visitor # Visit an individual node. - def visit(node) + #-- + #: (node?) -> untyped + def visit(node) # :nodoc: node&.accept(self) end # Visit a list of nodes. - def visit_all(nodes) + #-- + #: (Array[node?]) -> untyped + def visit_all(nodes) # :nodoc: nodes.map { |node| node&.accept(self) } end # Visit the child nodes of the given node. - def visit_child_nodes(node) + #-- + #: (node) -> Array[untyped] + def visit_child_nodes(node) # :nodoc: node.each_child_node.map { |node| node.accept(self) } end <%- nodes.each_with_index do |node, index| -%> <%= "\n" if index != 0 -%> - # Compile a <%= node.name %> node - def visit_<%= node.human %>(node) + #: (<%= node.name %>) -> Array[untyped] + def visit_<%= node.human %>(node) # :nodoc: node.each_child_node.map { |node| node.accept(self) } end <%- end -%> diff --git a/templates/lib/prism/dispatcher.rb.erb b/templates/lib/prism/dispatcher.rb.erb index 52478451c9..5991b0c904 100644 --- a/templates/lib/prism/dispatcher.rb.erb +++ b/templates/lib/prism/dispatcher.rb.erb @@ -1,3 +1,6 @@ +#-- +# rbs_inline: enabled + module Prism # The dispatcher class fires events for nodes that are found while walking an # AST to all registered listeners. It's useful for performing different types @@ -32,50 +35,52 @@ module Prism # dispatcher.dispatch_once(integer) # class Dispatcher < Visitor - # attr_reader listeners: Hash[Symbol, Array[Listener]] - attr_reader :listeners + # A hash mapping event names to arrays of listeners that should be notified + # when that event is fired. + attr_reader :listeners #: Hash[Symbol, Array[untyped]] # Initialize a new dispatcher. + #-- + #: () -> void def initialize @listeners = {} end # Register a listener for one or more events. - # - # def register: (Listener, *Symbol) -> void + #-- + #: (untyped, *Symbol) -> void def register(listener, *events) register_events(listener, events) end # Register all public methods of a listener that match the pattern # `on__(enter|leave)`. - # - # def register_public_methods: (Listener) -> void + #-- + #: (untyped) -> void def register_public_methods(listener) register_events(listener, listener.public_methods(false).grep(/\Aon_.+_(?:enter|leave)\z/)) end # Register a listener for the given events. - private def register_events(listener, events) + #-- + #: (untyped, Array[Symbol]) -> void + private def register_events(listener, events) # :nodoc: events.each { |event| (listeners[event] ||= []) << listener } end # Walks `root` dispatching events to all registered listeners. - # - # def dispatch: (Node) -> void alias dispatch visit # Dispatches a single event for `node` to all registered listeners. - # - # def dispatch_once: (Node) -> void + #-- + #: (node node) -> void def dispatch_once(node) node.accept(DispatchOnce.new(listeners)) end <%- nodes.each do |node| -%> - # Dispatch enter and leave events for <%= node.name %> nodes and continue - # walking the tree. - def visit_<%= node.human %>(node) + #: (<%= node.name %> node) -> void + def visit_<%= node.human %>(node) # :nodoc: listeners[:on_<%= node.human %>_enter]&.each { |listener| listener.on_<%= node.human %>_enter(node) } super listeners[:on_<%= node.human %>_leave]&.each { |listener| listener.on_<%= node.human %>_leave(node) } @@ -83,14 +88,17 @@ module Prism <%- end -%> class DispatchOnce < Visitor # :nodoc: - attr_reader :listeners + attr_reader :listeners #: Hash[Symbol, Array[untyped]] + #: (Hash[Symbol, Array[untyped]] listeners) -> void def initialize(listeners) @listeners = listeners end <%- nodes.each do |node| -%> # Dispatch enter and leave events for <%= node.name %> nodes. + #-- + #: (<%= node.name %> node) -> void def visit_<%= node.human %>(node) listeners[:on_<%= node.human %>_enter]&.each { |listener| listener.on_<%= node.human %>_enter(node) } listeners[:on_<%= node.human %>_leave]&.each { |listener| listener.on_<%= node.human %>_leave(node) } diff --git a/templates/lib/prism/dot_visitor.rb.erb b/templates/lib/prism/dot_visitor.rb.erb index 87de1965b0..88ef1e1f36 100644 --- a/templates/lib/prism/dot_visitor.rb.erb +++ b/templates/lib/prism/dot_visitor.rb.erb @@ -1,3 +1,6 @@ +#-- +# rbs_inline: enabled + require "cgi/escape" require "cgi/util" unless defined?(CGI::EscapeExt) @@ -6,14 +9,18 @@ module Prism # subtree into a graphviz dot graph. class DotVisitor < Visitor class Field # :nodoc: - attr_reader :name, :value, :port + attr_reader :name #: String + attr_reader :value #: String? + attr_reader :port #: bool + #: (String name, String? value, bool port) -> void def initialize(name, value, port) @name = name @value = value @port = port end + #: () -> String def to_dot if port "#{name}" @@ -24,17 +31,21 @@ module Prism end class Table # :nodoc: - attr_reader :name, :fields + attr_reader :name #: String + attr_reader :fields #: Array[Field] + #: (String name) -> void def initialize(name) @name = name @fields = [] end + #: (String name, ?String? value, ?port: bool) -> void def field(name, value = nil, port: false) fields << Field.new(name, value, port) end + #: () -> String def to_dot dot = <<~DOT @@ -50,26 +61,31 @@ module Prism end class Digraph # :nodoc: - attr_reader :nodes, :waypoints, :edges + attr_reader :nodes, :waypoints, :edges #: Array[String] + #: () -> void def initialize @nodes = [] @waypoints = [] @edges = [] end + #: (String value) -> void def node(value) nodes << value end + #: (String value) -> void def waypoint(value) waypoints << value end + #: (String value) -> void def edge(value) edges << value end + #: () -> String def to_dot <<~DOT digraph "Prism" { @@ -93,21 +109,25 @@ module Prism private_constant :Field, :Table, :Digraph # The digraph that is being built. - attr_reader :digraph + attr_reader :digraph #: Digraph # Initialize a new dot visitor. + #-- + #: () -> void def initialize @digraph = Digraph.new end # Convert this visitor into a graphviz dot graph string. + #-- + #: () -> String def to_dot digraph.to_dot end <%- nodes.each do |node| -%> - # Visit a <%= node.name %> node. - def visit_<%= node.human %>(node) + #: (<%= node.name %>) -> void + def visit_<%= node.human %>(node) # :nodoc: table = Table.new("<%= node.name %>") id = node_id(node) <%- if (node_flags = node.flags) -%> @@ -152,7 +172,7 @@ module Prism <%- end -%> <%- end -%> - digraph.nodes << <<~DOT + digraph.node(<<~DOT) #{id} [ label=<#{table.to_dot.gsub(/\n/, "\n ")}> ]; @@ -165,19 +185,25 @@ module Prism private # Generate a unique node ID for a node throughout the digraph. - def node_id(node) + #-- + #: (node) -> String + def node_id(node) # :nodoc: "Node_#{node.object_id}" end # Inspect a location to display the start and end line and columns in bytes. - def location_inspect(location) + #-- + #: (Location) -> String + def location_inspect(location) # :nodoc: "(#{location.start_line},#{location.start_column})-(#{location.end_line},#{location.end_column})" end <%- flags.each do |flag| -%> # Inspect a node that has <%= flag.human %> flags to display the flags as a # comma-separated list. - def <%= flag.human %>_inspect(node) + #-- + #: (<%= nodes.filter_map { |node| node.name if node.flags == flag }.join(" | ") %> node) -> String + def <%= flag.human %>_inspect(node) # :nodoc: flags = [] #: Array[String] <%- flag.values.each do |value| -%> flags << "<%= value.name.downcase %>" if node.<%= value.name.downcase %>? diff --git a/templates/lib/prism/dsl.rb.erb b/templates/lib/prism/dsl.rb.erb index e16ebb7110..6dcbbec100 100644 --- a/templates/lib/prism/dsl.rb.erb +++ b/templates/lib/prism/dsl.rb.erb @@ -1,8 +1,11 @@ +#-- +# rbs_inline: enabled + module Prism # The DSL module provides a set of methods that can be used to create prism # nodes in a more concise manner. For example, instead of writing: # - # source = Prism::Source.for("[1]") + # source = Prism::Source.for("[1]", 1, []) # # Prism::ArrayNode.new( # source, @@ -56,17 +59,31 @@ module Prism extend self # Create a new Source object. + #-- + #: (String string) -> Source def source(string) - Source.for(string) + Source.for(string, 1, []) end # Create a new Location object. + #-- + #: (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location def location(source: default_source, start_offset: 0, length: 0) Location.new(source, start_offset, length) end <%- nodes.each do |node| -%> + <%- + params = [ + ["source", "Source"], + ["node_id", "Integer"], + ["location", "Location"], + ["flags", "Integer"] + ].concat(node.fields.map { |field| [field.name, field.rbs_class] }) + -%> # Create a new <%= node.name %> node. + #-- + #: (<%= params.map { |(name, type)| "?#{name}: #{type}" }.join(", ") %>) -> <%= node.name %> def <%= node.human %>(<%= ["source: default_source", "node_id: 0", "location: default_location", "flags: 0", *node.fields.map { |field| case field when Prism::Template::NodeField @@ -100,6 +117,8 @@ module Prism <%- flags.each do |flag| -%> # Retrieve the value of one of the <%= flag.name %> flags. + #-- + #: (Symbol name) -> Integer def <%= flag.human.chomp("s") %>(name) case name <%- flag.values.each do |value| -%> @@ -114,18 +133,24 @@ module Prism # The default source object that gets attached to nodes and locations if no # source is specified. + #-- + #: () -> Source def default_source - Source.for("") + Source.for("", 1, []) end # The default location object that gets attached to nodes if no location is # specified, which uses the given source. + #-- + #: () -> Location 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. + #-- + #: (Source source, Location location) -> node def default_node(source, location) MissingNode.new(source, -1, location, 0) end diff --git a/templates/lib/prism/inspect_visitor.rb.erb b/templates/lib/prism/inspect_visitor.rb.erb index 3cfe615d85..820f5ae75f 100644 --- a/templates/lib/prism/inspect_visitor.rb.erb +++ b/templates/lib/prism/inspect_visitor.rb.erb @@ -1,3 +1,6 @@ +#-- +# rbs_inline: enabled + module Prism # This visitor is responsible for composing the strings that get returned by # the various #inspect methods defined on each of the nodes. @@ -7,8 +10,9 @@ module Prism # when we hit an element in that list. In this case, we have a special # command that replaces the subsequent indent with the given value. class Replace # :nodoc: - attr_reader :value + attr_reader :value #: String + #: (String value) -> void def initialize(value) @value = value end @@ -17,19 +21,25 @@ module Prism private_constant :Replace # The current prefix string. - attr_reader :indent + # :stopdoc: + attr_reader :indent #: String + # :startdoc: # The list of commands that we need to execute in order to compose the # final string. - attr_reader :commands + #: stopdoc: + attr_reader :commands #: Array[[String | node | Replace, String]] + # :startdoc: - # Initializes a new instance of the InspectVisitor. - def initialize(indent = +"") + #: (?String indent) -> void + def initialize(indent = +"") # :nodoc: @indent = indent @commands = [] end # Compose an inspect string for the given node. + #-- + #: (node node) -> String def self.compose(node) visitor = new node.accept(visitor) @@ -37,7 +47,9 @@ module Prism end # Compose the final string. - def compose + #-- + #: () -> String + def compose # :nodoc: buffer = +"" replace = nil @@ -66,8 +78,8 @@ module Prism end <%- nodes.each do |node| -%> - # Inspect a <%= node.name %> node. - def visit_<%= node.human %>(node) + #: (<%= node.name %> node) -> void + def visit_<%= node.human %>(node) # :nodoc: commands << [inspect_node(<%= node.name.inspect %>, node), indent] <%- (fields = [node.flags || Prism::Template::Flags.empty, *node.fields]).each_with_index do |field, index| -%> <%- pointer = index == fields.length - 1 ? "└── " : "├── " -%> @@ -114,13 +126,17 @@ module Prism private # Compose a header for the given node. - def inspect_node(name, node) + #-- + #: (String name, node node) -> String + def inspect_node(name, node) # :nodoc: location = node.location "@ #{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. - def inspect_location(location) + #-- + #: (Location? location) -> String + def inspect_location(location) # :nodoc: if location "(#{location.start_line},#{location.start_column})-(#{location.end_line},#{location.end_column}) = #{location.slice.inspect}" else diff --git a/templates/lib/prism/mutation_compiler.rb.erb b/templates/lib/prism/mutation_compiler.rb.erb index 565ee4e315..2d555048d2 100644 --- a/templates/lib/prism/mutation_compiler.rb.erb +++ b/templates/lib/prism/mutation_compiler.rb.erb @@ -1,3 +1,6 @@ +#-- +# rbs_inline: enabled + module Prism # This visitor walks through the tree and copies each node as it is being # visited. This is useful for consumers that want to mutate the tree, as you @@ -5,8 +8,8 @@ module Prism class MutationCompiler < Compiler <%- nodes.each_with_index do |node, index| -%> <%= "\n" if index != 0 -%> - # Copy a <%= node.name %> node - def visit_<%= node.human %>(node) + #: (<%= node.name %>) -> node? + def visit_<%= node.human %>(node) # :nodoc: <%- fields = node.fields.select { |field| [Prism::Template::NodeField, Prism::Template::OptionalNodeField, Prism::Template::NodeListField].include?(field.class) } -%> <%- if fields.any? -%> node.copy(<%= fields.map { |field| "#{field.name}: #{field.is_a?(Prism::Template::NodeListField) ? "visit_all" : "visit"}(node.#{field.name})" }.join(", ") %>) diff --git a/templates/lib/prism/node.rb.erb b/templates/lib/prism/node.rb.erb index d14a06961a..fb13051aba 100644 --- a/templates/lib/prism/node.rb.erb +++ b/templates/lib/prism/node.rb.erb @@ -1,24 +1,49 @@ +#-- +# rbs_inline: enabled + module Prism + # @rbs! + # interface _Repository + # def enter: (Integer node_id, Symbol field_name) -> Relocation::Entry + # end + # + # interface _Node + # def deconstruct: () -> Array[Prism::node?] + # def inspect: () -> String + # end + # + # type node = Node & _Node + # This represents a node in the tree. It is the parent class of all of the # various node types. class Node # A pointer to the source that this node was created from. - attr_reader :source + # :stopdoc: + attr_reader :source #: Source private :source + # :startdoc: # 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 + attr_reader :node_id #: Integer + + # The location associated with this node. For lazily loading Location + # objects, we keep it as a packed integer until it is accessed. + # @rbs @location: Location | Integer # Save this node using a saved source so that it can be retrieved later. + #-- + #: (_Repository repository) -> Relocation::Entry def save(repository) repository.enter(node_id, :itself) end # A Location instance that represents the location of this node in the # source. + #-- + #: () -> Location def location location = @location return location if location.is_a?(Location) @@ -26,104 +51,151 @@ module Prism end # Save the location using a saved source so that it can be retrieved later. + #-- + #: (_Repository repository) -> Relocation::Entry def save_location(repository) repository.enter(node_id, :location) end - # Delegates to the start_line of the associated location object. + # -------------------------------------------------------------------------- + # :section: Location Delegators + # These methods provide convenient access to the underlying Location object. + # -------------------------------------------------------------------------- + + # Delegates to [`start_line`](rdoc-ref:Location#start_line) of the associated location object. + #-- + #: () -> Integer def start_line location.start_line end - # Delegates to the end_line of the associated location object. + # Delegates to [`end_line`](rdoc-ref:Location#end_line) of the associated location object. + #-- + #: () -> Integer def end_line location.end_line end - # The start offset of the node in the source. This method is effectively a - # delegate method to the location object. + # Delegates to [`start_offset`](rdoc-ref:Location#start_offset) of the associated location object. + #-- + #: () -> Integer def start_offset location = @location location.is_a?(Location) ? location.start_offset : location >> 32 end - # The end offset of the node in the source. This method is effectively a - # delegate method to the location object. + # Delegates to [`end_offset`](rdoc-ref:Location#end_offset) of the associated location object. + #-- + #: () -> Integer def end_offset location = @location location.is_a?(Location) ? location.end_offset : ((location >> 32) + (location & 0xFFFFFFFF)) end - # Delegates to the start_character_offset of the associated location object. + # Delegates to [`start_character_offset`](rdoc-ref:Location#start_character_offset) + # of the associated location object. + #-- + #: () -> Integer def start_character_offset location.start_character_offset end - # Delegates to the end_character_offset of the associated location object. + # Delegates to [`end_character_offset`](rdoc-ref:Location#end_character_offset) + # of the associated location object. + #-- + #: () -> Integer def end_character_offset location.end_character_offset end - # Delegates to the cached_start_code_units_offset of the associated location - # object. + # Delegates to [`cached_start_code_units_offset`](rdoc-ref:Location#cached_start_code_units_offset) + # of the associated location object. + #-- + #: (_CodeUnitsCache cache) -> Integer def cached_start_code_units_offset(cache) location.cached_start_code_units_offset(cache) end - # Delegates to the cached_end_code_units_offset of the associated location - # object. + # Delegates to [`cached_end_code_units_offset`](rdoc-ref:Location#cached_end_code_units_offset) + # of the associated location object. + #-- + #: (_CodeUnitsCache cache) -> Integer def cached_end_code_units_offset(cache) location.cached_end_code_units_offset(cache) end - # Delegates to the start_column of the associated location object. + # Delegates to [`start_column`](rdoc-ref:Location#start_column) of the associated location object. + #-- + #: () -> Integer def start_column location.start_column end - # Delegates to the end_column of the associated location object. + # Delegates to [`end_column`](rdoc-ref:Location#end_column) of the associated location object. + #-- + #: () -> Integer def end_column location.end_column end - # Delegates to the start_character_column of the associated location object. + # Delegates to [`start_character_column`](rdoc-ref:Location#start_character_column) + # of the associated location object. + #-- + #: () -> Integer def start_character_column location.start_character_column end - # Delegates to the end_character_column of the associated location object. + # Delegates to [`end_character_column`](rdoc-ref:Location#end_character_column) + # of the associated location object. + #-- + #: () -> Integer def end_character_column location.end_character_column end - # Delegates to the cached_start_code_units_column of the associated location - # object. + # Delegates to [`cached_start_code_units_column`](rdoc-ref:Location#cached_start_code_units_column) + # of the associated location object. + #-- + #: (_CodeUnitsCache cache) -> Integer def cached_start_code_units_column(cache) location.cached_start_code_units_column(cache) end - # Delegates to the cached_end_code_units_column of the associated location - # object. + # Delegates to [`cached_end_code_units_column`](rdoc-ref:Location#cached_end_code_units_column) + # of the associated location object. + #-- + #: (_CodeUnitsCache cache) -> Integer def cached_end_code_units_column(cache) location.cached_end_code_units_column(cache) end - # Delegates to the leading_comments of the associated location object. + # Delegates to [`leading_comments`](rdoc-ref:Location#leading_comments) of the associated location object. + #-- + #: () -> Array[Comment] def leading_comments location.leading_comments end - # Delegates to the trailing_comments of the associated location object. + # Delegates to [`trailing_comments`](rdoc-ref:Location#trailing_comments) of the associated location object. + #-- + #: () -> Array[Comment] def trailing_comments location.trailing_comments end - # Delegates to the comments of the associated location object. + # Delegates to [`comments`](rdoc-ref:Location#comments) of the associated location object. + #-- + #: () -> Array[Comment] def comments location.comments end + # :section: + # Returns all of the lines of the source code associated with this node. + #-- + #: () -> Array[String] def source_lines location.source_lines end @@ -133,6 +205,8 @@ module Prism alias script_lines source_lines # Slice the location of the node from the source. + #-- + #: () -> String def slice location.slice end @@ -140,28 +214,38 @@ module Prism # Slice the location of the node from the source, starting at the beginning # of the line that the location starts on, ending at the end of the line # that the location ends on. + #-- + #: () -> String def slice_lines 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 + # :stopdoc: + attr_reader :flags #: Integer protected :flags + # :startdoc: # Returns true if the node has the newline flag set. + #-- + #: () -> bool def newline? flags.anybits?(NodeFlags::NEWLINE) end # Returns true if the node has the static literal flag set. + #-- + #: () -> bool 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) + #-- + #: (PP q) -> void + def pretty_print(q) # :nodoc: q.seplist(inspect.chomp.each_line, -> { q.breakable }) do |line| q.text(line.chomp) end @@ -169,6 +253,8 @@ module Prism end # Convert this node into a graphviz dot graph string. + #-- + #: () -> String def to_dot # @type self: node DotVisitor.new.tap { |visitor| accept(visitor) }.to_dot @@ -180,9 +266,11 @@ module Prism # # Important to note is that the column given to this method should be in # bytes, as opposed to characters or code units. + #-- + #: (Integer line, Integer column) -> Array[node] def tunnel(line, column) - queue = [self] #: Array[Prism::node] - result = [] #: Array[Prism::node] + queue = [self] #: Array[node] + result = [] #: Array[node] offset = source.byte_offset(line, column) while (node = queue.shift) @@ -204,9 +292,10 @@ module Prism # particular condition. # # node.breadth_first_search { |node| node.node_id == node_id } - # - def breadth_first_search(&block) - queue = [self] #: Array[Prism::node] + #-- + #: () { (node) -> bool } -> node? + def breadth_first_search(&blk) + queue = [self] #: Array[node] while (node = queue.shift) return node if yield node @@ -222,8 +311,9 @@ module Prism # particular condition. # # node.breadth_first_search_all { |node| node.is_a?(Prism::CallNode) } - # - def breadth_first_search_all(&block) + #-- + #: () { (node) -> bool } -> Array[node] + def breadth_first_search_all(&blk) queue = [self] #: Array[Prism::node] results = [] #: Array[Prism::node] @@ -239,6 +329,8 @@ module Prism # 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. + #-- + #: () -> Array[Reflection::Field] def self.fields # This method should only be called on subclasses of Node, not Node # itself. @@ -248,19 +340,22 @@ module Prism end # -------------------------------------------------------------------------- - # :section: Node interface - # These methods are effectively abstract methods that must be implemented by - # the various subclasses of Node. They are here to make it easier to work - # with typecheckers. + # :section: Node Interface + # These methods are effectively abstract methods that are implemented by + # the various subclasses of Node. # -------------------------------------------------------------------------- # Accepts a visitor and calls back into the specialized visit function. + #-- + #: (_Visitor visitor) -> untyped def accept(visitor) raise NoMethodError, "undefined method `accept' for #{inspect}" end # Returns an array of child nodes, including `nil`s in the place of optional # nodes that were not present. + #-- + #: () -> Array[node?] def child_nodes raise NoMethodError, "undefined method `child_nodes' for #{inspect}" end @@ -270,23 +365,32 @@ module Prism # With a block given, yields each child node. Without a block, returns # an enumerator that contains each child node. Excludes any `nil`s in # the place of optional nodes that were not present. - def each_child_node + #-- + #: () -> Enumerator[node, void] + #: () { (node) -> void } -> void + def each_child_node(&blk) raise NoMethodError, "undefined method `each_child_node' for #{inspect}" end # Returns an array of child nodes, excluding any `nil`s in the place of # optional nodes that were not present. + #-- + #: () -> Array[node] def compact_child_nodes raise NoMethodError, "undefined method `compact_child_nodes' for #{inspect}" end # Returns an array of child nodes and locations that could potentially have # comments attached to them. + #-- + #: () -> Array[node | Location] def comment_targets raise NoMethodError, "undefined method `comment_targets' for #{inspect}" end # Returns a string representation of the node. + #-- + #: () -> String def inspect raise NoMethodError, "undefined method `inspect' for #{inspect}" end @@ -303,6 +407,8 @@ module Prism # 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. + #-- + #: () -> Symbol def type raise NoMethodError, "undefined method `type' for #{inspect}" end @@ -311,6 +417,8 @@ module Prism # 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. + #-- + #: () -> Symbol def self.type raise NoMethodError, "undefined method `type' for #{inspect}" end @@ -321,7 +429,13 @@ module Prism #<%= line %> <%- end -%> class <%= node.name -%> < Node + <%- node.fields.each do |field| -%> + # @rbs @<%= field.name %>: <%= field.rbs_class %> + <%- end -%> + # Initialize a new <%= node.name %> node. + #-- + #: (Source source, Integer node_id, Location location, Integer flags, <%= node.fields.map { |field| "#{field.rbs_class} #{field.name}" }.join(", ") %>) -> void def initialize(<%= ["source", "node_id", "location", "flags", *node.fields.map(&:name)].join(", ") %>) @source = source @node_id = node_id @@ -335,12 +449,27 @@ module Prism <%- end -%> end - # def accept: (Visitor visitor) -> void + # --------- + # :section: Repository + # Methods related to Relocation. + # --------- + + # ---------------------------------------------------------------------------------- + # :section: Node Interface + # These methods are present on all subclasses of Node. + # Read the [node interface docs](Node.html#node-interface) for more information. + # ---------------------------------------------------------------------------------- + + # See Node.accept. + #-- + #: (_Visitor visitor) -> untyped def accept(visitor) visitor.visit_<%= node.human %>(self) end - # def child_nodes: () -> Array[Node?] + # See Node.child_nodes. + #-- + #: () -> Array[node?] def child_nodes [<%= node.fields.map { |field| case field @@ -350,8 +479,11 @@ module Prism }.compact.join(", ") %>] end - # def each_child_node: () { (Prism::node) -> void } -> void | () -> Enumerator[Prism::node] - def each_child_node + # See Node.each_child_node. + #-- + #: () -> Enumerator[node, void] + #: () { (node) -> void } -> void + def each_child_node(&blk) return to_enum(:each_child_node) unless block_given? <%- node.fields.each do |field| -%> @@ -359,14 +491,16 @@ module Prism <%- when Prism::Template::NodeField -%> yield <%= field.name %> <%- when Prism::Template::OptionalNodeField -%> - yield <%= field.name %> if <%= field.name %> + if (<%= field.name %> = self.<%= field.name %>); yield <%= field.name %>; end <%- when Prism::Template::NodeListField -%> <%= field.name %>.each { |node| yield node } <%- end -%> <%- end -%> end - # def compact_child_nodes: () -> Array[Node] + # See Node.compact_child_nodes. + #-- + #: () -> Array[node] def compact_child_nodes <%- if node.fields.any? { |field| field.is_a?(Prism::Template::OptionalNodeField) } -%> compact = [] #: Array[Prism::node] @@ -375,7 +509,7 @@ module Prism <%- when Prism::Template::NodeField -%> compact << <%= field.name %> <%- when Prism::Template::OptionalNodeField -%> - compact << <%= field.name %> if <%= field.name %> + if (<%= field.name %> = self.<%= field.name %>); compact << <%= field.name %>; end <%- when Prism::Template::NodeListField -%> compact.concat(<%= field.name %>) <%- end -%> @@ -391,7 +525,9 @@ module Prism <%- end -%> end - # def comment_targets: () -> Array[Node | Location] + # See Node.comment_targets. + #-- + #: () -> Array[node | Location] def comment_targets [<%= node.fields.map { |field| case field @@ -401,50 +537,101 @@ module Prism }.compact.join(", ") %>] #: Array[Prism::node | Location] end - # def copy: (<%= (["?node_id: Integer", "?location: Location", "?flags: Integer"] + node.fields.map { |field| "?#{field.name}: #{field.rbs_class}" }).join(", ") %>) -> <%= node.name %> + # :call-seq: + # copy(**fields) -> <%= node.name %> + # + # Creates a copy of self with the given fields, using self as the template. + #-- + #: (?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[Node?] alias deconstruct child_nodes - # 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) + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys(keys) # :nodoc: { <%= (["node_id: node_id", "location: location"] + node.fields.map { |field| "#{field.name}: #{field.name}" }).join(", ") %> } end + + # See `Node#type`. + #-- + #: () -> :<%= node.human %> + def type + :<%= node.human %> + end + + # See `Node.type`. + #-- + #: () -> :<%= node.human %> + def self.type + :<%= node.human %> + end + + #: () -> String + def inspect # :nodoc: + InspectVisitor.compose(self) + end + + # :section: + <%- if (node_flags = node.flags) -%> <%- node_flags.values.each do |value| -%> - - # def <%= value.name.downcase %>?: () -> bool + # :category: Flags + # <%= value.comment %> + #-- + #: () -> bool def <%= value.name.downcase %>? flags.anybits?(<%= node_flags.name %>::<%= value.name %>) end + <%- end -%> <%- end -%> <%- node.fields.each do |field| -%> - + <%- case field -%> + <%- when Prism::Template::LocationField -%> + # :category: Locations + # :call-seq: + # <%= field.name %> -> <%= field.call_seq_type %> + # <%- if field.comment.nil? -%> - # attr_reader <%= field.name %>: <%= field.rbs_class %> + # Returns the Location represented by `<%= field.name %>`. <%- else -%> <%- field.each_comment_line do |line| -%> #<%= line %> <%- end -%> <%- end -%> - <%- case field -%> - <%- when Prism::Template::LocationField -%> + #-- + #: () -> Location def <%= field.name %> location = @<%= field.name %> return location if location.is_a?(Location) @<%= field.name %> = Location.new(source, location >> 32, location & 0xFFFFFFFF) end + # :category: Repository # Save the <%= field.name %> location using the given saved source so that # it can be retrieved later. + #-- + #: (_Repository repository) -> Relocation::Entry def save_<%= field.name %>(repository) repository.enter(node_id, :<%= field.name %>) end + <%- when Prism::Template::OptionalLocationField -%> + # :category: Locations + # :call-seq: + # <%= field.name %> -> <%= field.call_seq_type %> + # + <%- if field.comment.nil? -%> + # Returns the Location represented by `<%= field.name %>`. + <%- else -%> + <%- field.each_comment_line do |line| -%> + #<%= line %> + <%- end -%> + <%- end -%> + #-- + #: () -> Location? def <%= field.name %> location = @<%= field.name %> case location @@ -457,54 +644,69 @@ module Prism end end + # :category: Repository # Save the <%= field.name %> location using the given saved source so that # it can be retrieved later. + #-- + #: (_Repository repository) -> Relocation::Entry? def save_<%= field.name %>(repository) repository.enter(node_id, :<%= field.name %>) unless @<%= field.name %>.nil? end <%- else -%> - attr_reader :<%= field.name %> + # :call-seq: + # <%= field.name %> -> <%= field.call_seq_type %> + # + <%- if field.comment.nil? -%> + # Returns the `<%= field.name %>` attribute. + <%- else -%> + <%- field.each_comment_line do |line| -%> + #<%= line %> + <%- end -%> + <%- end -%> + #-- + #: () -> <%= field.rbs_class %> + def <%= field.name %> + @<%= field.name %> + end + <%- end -%> <%- end -%> + # :section: Slicing + <%- node.fields.each do |field| -%> <%- case field -%> <%- when Prism::Template::LocationField -%> <%- 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 + # :call-seq: + # <%= field.name.delete_suffix("_loc") %> -> String + # + # Slice the location of <%= field.name %> from the source. + #-- + #: () -> String def <%= field.name.delete_suffix("_loc") %> <%= field.name %>.slice end + <%- when Prism::Template::OptionalLocationField -%> <%- 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? + # :call-seq: + # <%= field.name.delete_suffix("_loc") %> -> String | nil + # + # Slice the location of <%= field.name %> from the source. + #-- + #: () -> String? def <%= field.name.delete_suffix("_loc") %> <%= field.name %>&.slice end + <%- end -%> <%- end -%> + # :section: - # def inspect -> String - def inspect - InspectVisitor.compose(self) - end - - # Return a symbol representation of this node type. See `Node#type`. - def type - :<%= node.human %> - end - - # Return a symbol representation of this node type. See `Node::type`. - def self.type - :<%= node.human %> - end - - # Implements case-equality for the node. This is effectively == but without - # comparing the value of locations. Locations are checked only for presence. - def ===(other) + #: (untyped other) -> boolish + def ===(other) # :nodoc: 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) -%> diff --git a/templates/lib/prism/reflection.rb.erb b/templates/lib/prism/reflection.rb.erb index 6c8b2f4d25..0012f120b2 100644 --- a/templates/lib/prism/reflection.rb.erb +++ b/templates/lib/prism/reflection.rb.erb @@ -1,3 +1,6 @@ +#-- +# rbs_inline: enabled + module Prism # The Reflection module provides the ability to reflect on the structure of # the syntax tree itself, as opposed to looking at a single syntax tree. This @@ -7,9 +10,11 @@ module Prism # for all other field types. class Field # The name of the field. - attr_reader :name + attr_reader :name #: Symbol # Initializes the field with the given name. + #-- + #: (Symbol name) -> void def initialize(name) @name = name end @@ -83,9 +88,11 @@ module Prism # the bitset should be accessed through their query methods. class FlagsField < Field # The names of the flags in the bitset. - attr_reader :flags + attr_reader :flags #: Array[Symbol] # Initializes the flags field with the given name and flags. + #-- + #: (Symbol name, Array[Symbol] flags) -> void def initialize(name, flags) super(name) @flags = flags @@ -93,6 +100,8 @@ module Prism end # Returns the fields for the given node. + #-- + #: (singleton(Node) node) -> Array[Field] def self.fields_for(node) case node.type <%- nodes.each do |node| -%> diff --git a/templates/lib/prism/serialize.rb.erb b/templates/lib/prism/serialize.rb.erb index 2275d685ca..a676f957af 100644 --- a/templates/lib/prism/serialize.rb.erb +++ b/templates/lib/prism/serialize.rb.erb @@ -1,9 +1,12 @@ +#-- +# rbs_inline: enabled + require "stringio" require_relative "polyfill/unpack1" module Prism # A module responsible for deserializing parse results. - module Serialize + module Serialize # :nodoc: # The major version of prism that we are expecting to find in the serialized # strings. MAJOR_VERSION = 1 @@ -20,9 +23,11 @@ module Prism # # The formatting of the source of this method is purposeful to illustrate # the structure of the serialized data. + #-- + #: (String input, String serialized, bool freeze) -> ParseResult def self.load_parse(input, serialized, freeze) input = input.dup - source = Source.for(input) + source = Source.for(input, 1, []) loader = Loader.new(source, serialized) loader.load_header @@ -38,16 +43,17 @@ module Prism data_loc = loader.load_optional_location_object(freeze) errors = loader.load_errors(encoding, freeze) warnings = loader.load_warnings(encoding, freeze) + continuable = loader.load_bool cpool_base = loader.load_uint32 cpool_size = loader.load_varuint - constant_pool = ConstantPool.new(input, serialized, cpool_base, cpool_size) + constant_pool = ConstantPool.new(serialized, cpool_base, cpool_size) - node = loader.load_node(constant_pool, encoding, freeze) + node = loader.load_node(constant_pool, encoding, freeze) #: ProgramNode loader.load_constant_pool(constant_pool) raise unless loader.eof? - result = ParseResult.new(node, comments, magic_comments, data_loc, errors, warnings, source) + result = ParseResult.new(node, comments, magic_comments, data_loc, errors, warnings, continuable, source) result.freeze if freeze input.force_encoding(encoding) @@ -73,8 +79,10 @@ module Prism # # The formatting of the source of this method is purposeful to illustrate # the structure of the serialized data. + #-- + #: (String input, String serialized, bool freeze) -> LexResult def self.load_lex(input, serialized, freeze) - source = Source.for(input) + source = Source.for(input, 1, []) loader = Loader.new(source, serialized) tokens = loader.load_tokens @@ -90,9 +98,10 @@ module Prism data_loc = loader.load_optional_location_object(freeze) errors = loader.load_errors(encoding, freeze) warnings = loader.load_warnings(encoding, freeze) + continuable = loader.load_bool raise unless loader.eof? - result = LexResult.new(tokens, comments, magic_comments, data_loc, errors, warnings, source) + result = LexResult.new(tokens, comments, magic_comments, data_loc, errors, warnings, continuable, source) tokens.each do |token| token[0].value.force_encoding(encoding) @@ -117,8 +126,10 @@ module Prism # # The formatting of the source of this method is purposeful to illustrate # the structure of the serialized data. + #-- + #: (String input, String serialized, bool freeze) -> Array[Comment] def self.load_parse_comments(input, serialized, freeze) - source = Source.for(input) + source = Source.for(input, 1, []) loader = Loader.new(source, serialized) loader.load_header @@ -139,8 +150,10 @@ module Prism # # The formatting of the source of this method is purposeful to illustrate # the structure of the serialized data. + #-- + #: (String input, String serialized, bool freeze) -> ParseLexResult def self.load_parse_lex(input, serialized, freeze) - source = Source.for(input) + source = Source.for(input, 1, []) loader = Loader.new(source, serialized) tokens = loader.load_tokens @@ -157,17 +170,18 @@ module Prism data_loc = loader.load_optional_location_object(freeze) errors = loader.load_errors(encoding, freeze) warnings = loader.load_warnings(encoding, freeze) + continuable = loader.load_bool cpool_base = loader.load_uint32 cpool_size = loader.load_varuint - constant_pool = ConstantPool.new(input, serialized, cpool_base, cpool_size) + constant_pool = ConstantPool.new(serialized, cpool_base, cpool_size) - node = loader.load_node(constant_pool, encoding, freeze) + node = loader.load_node(constant_pool, encoding, freeze) #: ProgramNode loader.load_constant_pool(constant_pool) raise unless loader.eof? - value = [node, tokens] - result = ParseLexResult.new(value, comments, magic_comments, data_loc, errors, warnings, source) + value = [node, tokens] #: [ProgramNode, Array[[Token, Integer]]] + result = ParseLexResult.new(value, comments, magic_comments, data_loc, errors, warnings, continuable, source) tokens.each do |token| token[0].value.force_encoding(encoding) @@ -189,34 +203,36 @@ module Prism end class ConstantPool # :nodoc: - attr_reader :size + attr_reader :size #: Integer + + # @rbs @serialized: String + # @rbs @base: Integer + # @rbs @pool: Array[Symbol?] - def initialize(input, serialized, base, size) - @input = input + #: (String serialized, Integer base, Integer size) -> void + def initialize(serialized, base, size) @serialized = serialized @base = base @size = size @pool = Array.new(size, nil) end + #: (Integer index, Encoding encoding) -> Symbol def get(index, encoding) @pool[index] ||= begin offset = @base + index * 8 - start = @serialized.unpack1("L", offset: offset) - length = @serialized.unpack1("L", offset: offset + 4) + start = @serialized.unpack1("L", offset: offset) #: Integer + length = @serialized.unpack1("L", offset: offset + 4) #: Integer - if start.nobits?(1 << 31) - @input.byteslice(start, length).force_encoding(encoding).to_sym - else - @serialized.byteslice(start & ((1 << 31) - 1), length).force_encoding(encoding).to_sym - end + (@serialized.byteslice(start, length) or raise).force_encoding(encoding).to_sym end end end if RUBY_ENGINE == "truffleruby" # StringIO is synchronized and that adds a high overhead on TruffleRuby. + # @rbs skip class FastStringIO # :nodoc: attr_accessor :pos @@ -246,8 +262,11 @@ module Prism end class Loader # :nodoc: - attr_reader :input, :io, :source + attr_reader :input #: String + attr_reader :io #: StringIO + attr_reader :source #: Source + #: (Source source, String serialized) -> void def initialize(source, serialized) @input = source.source.dup raise unless serialized.encoding == Encoding::BINARY @@ -256,40 +275,46 @@ module Prism define_load_node_lambdas if RUBY_ENGINE != "ruby" end + #: () -> bool def eof? io.getbyte io.eof? end + #: (ConstantPool constant_pool) -> void def load_constant_pool(constant_pool) trailer = 0 constant_pool.size.times do |index| - start, length = io.read(8).unpack("L2") - trailer += length if start.anybits?(1 << 31) + length = (io.read(8) or raise).unpack1("L", offset: 4) #: Integer + trailer += length end io.read(trailer) end + #: () -> void def load_header raise "Invalid serialization" if io.read(5) != "PRISM" - raise "Invalid serialization" if io.read(3).unpack("C3") != [MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION] + raise "Invalid serialization" if (io.read(3) or raise).unpack("C3") != [MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION] raise "Invalid serialization (location fields must be included but are not)" if io.getbyte != 0 end + #: () -> Encoding def load_encoding - encoding = Encoding.find(io.read(load_varuint)) + encoding = Encoding.find((io.read(load_varuint) or raise)) or raise @input = input.force_encoding(encoding).freeze encoding end + #: (bool freeze) -> Array[Integer] def load_line_offsets(freeze) offsets = Array.new(load_varuint) { load_varuint } offsets.freeze if freeze offsets end + #: (bool freeze) -> Array[Comment] def load_comments(freeze) comments = Array.new(load_varuint) do @@ -297,6 +322,7 @@ module Prism case load_varuint when 0 then InlineComment.new(load_location_object(freeze)) when 1 then EmbDocComment.new(load_location_object(freeze)) + else raise end comment.freeze if freeze @@ -307,6 +333,7 @@ module Prism comments end + #: (bool freeze) -> Array[MagicComment] def load_magic_comments(freeze) magic_comments = Array.new(load_varuint) do @@ -331,10 +358,11 @@ module Prism <%- warnings.each do |warning| -%> <%= warning.name.downcase.to_sym.inspect %>, <%- end -%> - ].freeze + ].freeze #: Array[Symbol] private_constant :DIAGNOSTIC_TYPES + #: () -> Symbol def load_error_level level = io.getbyte @@ -350,13 +378,14 @@ module Prism end end + #: (Encoding encoding, bool freeze) -> Array[ParseError] def load_errors(encoding, freeze) errors = Array.new(load_varuint) do error = ParseError.new( DIAGNOSTIC_TYPES.fetch(load_varuint), - load_embedded_string(encoding), + load_string(encoding), load_location_object(freeze), load_error_level ) @@ -369,6 +398,7 @@ module Prism errors end + #: () -> Symbol def load_warning_level level = io.getbyte @@ -382,13 +412,14 @@ module Prism end end + #: (Encoding encoding, bool freeze) -> Array[ParseWarning] def load_warnings(encoding, freeze) warnings = Array.new(load_varuint) do warning = ParseWarning.new( DIAGNOSTIC_TYPES.fetch(load_varuint), - load_embedded_string(encoding), + load_string(encoding), load_location_object(freeze), load_warning_level ) @@ -401,15 +432,15 @@ module Prism warnings end + #: () -> Array[[Token, Integer]] def load_tokens - tokens = [] + tokens = [] #: Array[[Token, Integer]] while (type = TOKEN_TYPES.fetch(load_varuint)) - start = load_varuint - length = load_varuint + location = load_location_object(false) + lex_state = load_varuint - location = Location.new(@source, start, length) token = Token.new(@source, type, location.slice, location) tokens << [token, lex_state] @@ -420,25 +451,29 @@ module Prism # variable-length integer using https://en.wikipedia.org/wiki/LEB128 # This is also what protobuf uses: https://protobuf.dev/programming-guides/encoding/#varints + #-- + #: () -> Integer def load_varuint - n = io.getbyte + n = (io.getbyte or raise) if n < 128 n else n -= 128 shift = 0 - while (b = io.getbyte) >= 128 + while (b = (io.getbyte or raise)) >= 128 n += (b - 128) << (shift += 7) end n + (b << (shift + 7)) end end + #: () -> Integer def load_varsint n = load_varuint (n >> 1) ^ (-(n & 1)) end + #: () -> Integer def load_integer negative = io.getbyte != 0 length = load_varuint @@ -450,14 +485,22 @@ module Prism value end + #: () -> Float def load_double - io.read(8).unpack1("D") + (io.read(8) or raise).unpack1("D") #: Float end + #: () -> bool + def load_bool + (io.getbyte or raise) != 0 + end + + #: () -> Integer def load_uint32 - io.read(4).unpack1("L") + (io.read(4) or raise).unpack1("L") #: Integer end + #: (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node? def load_optional_node(constant_pool, encoding, freeze) if io.getbyte != 0 io.pos -= 1 @@ -465,90 +508,121 @@ module Prism end end - def load_embedded_string(encoding) - io.read(load_varuint).force_encoding(encoding).freeze - end - + #: (Encoding encoding) -> String def load_string(encoding) - case (type = io.getbyte) - when 1 - input.byteslice(load_varuint, load_varuint).force_encoding(encoding).freeze - when 2 - load_embedded_string(encoding) - else - raise "Unknown serialized string type: #{type}" - end + (io.read(load_varuint) or raise).force_encoding(encoding).freeze end + #: (bool freeze) -> Location def load_location_object(freeze) location = Location.new(source, load_varuint, load_varuint) location.freeze if freeze location end + # Load a location object from the serialized data. Note that we are lying + # about the signature a bit here, because we sometimes load it as a packed + # integer instead of an object. + #-- + #: (bool freeze) -> Location def load_location(freeze) return load_location_object(freeze) if freeze - (load_varuint << 32) | load_varuint + (load_varuint << 32) | load_varuint #: Location end + # Load an optional location object from the serialized data if it is + # present. Note that we are lying about the signature a bit here, because + # we sometimes load it as a packed integer instead of an object. + #-- + #: (bool freeze) -> Location? def load_optional_location(freeze) load_location(freeze) if io.getbyte != 0 end + #: (bool freeze) -> Location? def load_optional_location_object(freeze) load_location_object(freeze) if io.getbyte != 0 end + #: (ConstantPool constant_pool, Encoding encoding) -> Symbol def load_constant(constant_pool, encoding) index = load_varuint constant_pool.get(index - 1, encoding) end + #: (ConstantPool constant_pool, Encoding encoding) -> Symbol? def load_optional_constant(constant_pool, encoding) index = load_varuint constant_pool.get(index - 1, encoding) if index != 0 end if RUBY_ENGINE == "ruby" + #: (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node def load_node(constant_pool, encoding, freeze) type = io.getbyte node_id = load_varuint - location = load_location(freeze) - value = case type - <%- nodes.each_with_index do |node, index| -%> - when <%= index + 1 %> then - <%- if node.needs_serialized_length? -%> - load_uint32 - <%- end -%> - <%= node.name %>.new(<%= ["source", "node_id", "location", "load_varuint", *node.fields.map { |field| - case field - when Prism::Template::NodeField then "load_node(constant_pool, encoding, freeze)" - when Prism::Template::OptionalNodeField then "load_optional_node(constant_pool, encoding, freeze)" - when Prism::Template::StringField then "load_string(encoding)" - when Prism::Template::NodeListField then "Array.new(load_varuint) { load_node(constant_pool, encoding, freeze) }.tap { |nodes| nodes.freeze if freeze }" - when Prism::Template::ConstantField then "load_constant(constant_pool, encoding)" - when Prism::Template::OptionalConstantField then "load_optional_constant(constant_pool, encoding)" - when Prism::Template::ConstantListField then "Array.new(load_varuint) { load_constant(constant_pool, encoding) }.tap { |constants| constants.freeze if freeze }" - when Prism::Template::LocationField then "load_location(freeze)" - when Prism::Template::OptionalLocationField then "load_optional_location(freeze)" - when Prism::Template::UInt8Field then "io.getbyte" - when Prism::Template::UInt32Field then "load_varuint" - when Prism::Template::IntegerField then "load_integer" - when Prism::Template::DoubleField then "load_double" - else raise - end - }].join(", ") -%>) + location = load_location(freeze) #: Location + value = + case type + <%- nodes.each_with_index do |node, index| -%> + when <%= index + 1 %> + <%- if node.needs_serialized_length? -%> + load_uint32 + <%- end -%> + <%= node.name %>.new( + source, + node_id, + location, + load_varuint, + <%- node.fields.each do |field| -%> + <%- case field -%> + <%- when Prism::Template::NodeField -%> + load_node(constant_pool, encoding, freeze), #: <%= field.rbs_class %> + <%- when Prism::Template::OptionalNodeField -%> + load_optional_node(constant_pool, encoding, freeze), #: <%= field.rbs_class %> + <%- when Prism::Template::StringField -%> + load_string(encoding), + <%- when Prism::Template::NodeListField -%> + Array.new(load_varuint) do + load_node(constant_pool, encoding, freeze) #: <%= field.element_rbs_class %> + end.tap { |nodes| nodes.freeze if freeze }, + <%- when Prism::Template::ConstantField -%> + load_constant(constant_pool, encoding), + <%- when Prism::Template::OptionalConstantField -%> + load_optional_constant(constant_pool, encoding), + <%- when Prism::Template::ConstantListField -%> + Array.new(load_varuint) { load_constant(constant_pool, encoding) }.tap { |constants| constants.freeze if freeze }, + <%- when Prism::Template::LocationField -%> + load_location(freeze), + <%- when Prism::Template::OptionalLocationField -%> + load_optional_location(freeze), + <%- when Prism::Template::UInt8Field -%> + (io.getbyte or raise), + <%- when Prism::Template::UInt32Field -%> + load_varuint, + <%- when Prism::Template::IntegerField -%> + load_integer, + <%- when Prism::Template::DoubleField -%> + load_double, + <%- else raise -%> + <%- end -%> + <%- end -%> + ) <%- end -%> - end + else + raise "Unknown node type: #{type}" + end value.freeze if freeze value end else + # @rbs skip def load_node(constant_pool, encoding, freeze) - @load_node_lambdas[io.getbyte].call(constant_pool, encoding, freeze) + @load_node_lambdas[(io.getbyte or raise)].call(constant_pool, encoding, freeze) end + # @rbs skip def define_load_node_lambdas @load_node_lambdas = [ nil, @@ -559,24 +633,46 @@ module Prism <%- if node.needs_serialized_length? -%> load_uint32 <%- end -%> - value = <%= node.name %>.new(<%= ["source", "node_id", "location", "load_varuint", *node.fields.map { |field| - case field - when Prism::Template::NodeField then "load_node(constant_pool, encoding, freeze)" - when Prism::Template::OptionalNodeField then "load_optional_node(constant_pool, encoding, freeze)" - when Prism::Template::StringField then "load_string(encoding)" - when Prism::Template::NodeListField then "Array.new(load_varuint) { load_node(constant_pool, encoding, freeze) }" - when Prism::Template::ConstantField then "load_constant(constant_pool, encoding)" - when Prism::Template::OptionalConstantField then "load_optional_constant(constant_pool, encoding)" - when Prism::Template::ConstantListField then "Array.new(load_varuint) { load_constant(constant_pool, encoding) }" - when Prism::Template::LocationField then "load_location(freeze)" - when Prism::Template::OptionalLocationField then "load_optional_location(freeze)" - when Prism::Template::UInt8Field then "io.getbyte" - when Prism::Template::UInt32Field then "load_varuint" - when Prism::Template::IntegerField then "load_integer" - when Prism::Template::DoubleField then "load_double" - else raise - end - }].join(", ") -%>) + value = + <%= node.name %>.new( + source, + node_id, + location, + load_varuint, + <%- node.fields.map do |field| -%> + <%- case field -%> + <%- when Prism::Template::NodeField -%> + load_node(constant_pool, encoding, freeze), #: <%= field.rbs_class %> + <%- when Prism::Template::OptionalNodeField -%> + load_optional_node(constant_pool, encoding, freeze), #: <%= field.rbs_class %> + <%- when Prism::Template::StringField -%> + load_string(encoding), + <%- when Prism::Template::NodeListField -%> + Array.new(load_varuint) do + load_node(constant_pool, encoding, freeze) #: <%= field.element_rbs_class %> + end, + <%- when Prism::Template::ConstantField -%> + load_constant(constant_pool, encoding), + <%- when Prism::Template::OptionalConstantField -%> + load_optional_constant(constant_pool, encoding), + <%- when Prism::Template::ConstantListField -%> + Array.new(load_varuint) { load_constant(constant_pool, encoding) }, + <%- when Prism::Template::LocationField -%> + load_location(freeze), + <%- when Prism::Template::OptionalLocationField -%> + load_optional_location(freeze), + <%- when Prism::Template::UInt8Field -%> + (io.getbyte or raise), + <%- when Prism::Template::UInt32Field -%> + load_varuint, + <%- when Prism::Template::IntegerField -%> + load_integer, + <%- when Prism::Template::DoubleField -%> + load_double, + <%- else raise -%> + <%- end -%> + <%- end -%> + ) value.freeze if freeze value }, @@ -584,6 +680,10 @@ module Prism ] end end + + # @rbs! + # @load_node_lambdas: Array[Proc] + # def define_load_node_lambdas: () -> void end # The token types that can be indexed by their enum values. @@ -592,7 +692,7 @@ module Prism <%- tokens.each do |token| -%> <%= token.name.to_sym.inspect %>, <%- end -%> - ].freeze + ].freeze #: Array[Symbol?] private_constant :MAJOR_VERSION, :MINOR_VERSION, :PATCH_VERSION private_constant :ConstantPool, :FastStringIO, :Loader, :TOKEN_TYPES diff --git a/templates/lib/prism/visitor.rb.erb b/templates/lib/prism/visitor.rb.erb index 76f907724f..f23e87d99e 100644 --- a/templates/lib/prism/visitor.rb.erb +++ b/templates/lib/prism/visitor.rb.erb @@ -1,4 +1,14 @@ +#-- +# rbs_inline: enabled + module Prism + # @rbs! + # interface _Visitor + # <% nodes.each do |node| %> + # def visit_<%= node.human %>: (<%= node.name %>) -> void + # <% end %> + # end + # A class that knows how to walk down the tree. None of the individual visit # methods are implemented on this visitor, so it forces the consumer to # implement each one that they need. For a default implementation that @@ -6,18 +16,24 @@ module Prism class BasicVisitor # Calls `accept` on the given node if it is not `nil`, which in turn should # call back into this visitor by calling the appropriate `visit_*` method. + #-- + #: (node? node) -> void def visit(node) # @type self: _Visitor node&.accept(self) end # Visits each node in `nodes` by calling `accept` on each one. + #-- + #: (Array[node?] nodes) -> void def visit_all(nodes) # @type self: _Visitor nodes.each { |node| node&.accept(self) } end # Visits the child nodes of `node` by calling `accept` on each one. + #-- + #: (node node) -> void def visit_child_nodes(node) # @type self: _Visitor node.each_child_node { |node| node.accept(self) } @@ -47,6 +63,8 @@ module Prism <%- nodes.each_with_index do |node, index| -%> <%= "\n" if index != 0 -%> # Visit a <%= node.name %> node + #-- + #: (<%= node.name %> node) -> void def visit_<%= node.human %>(node) node.each_child_node { |node| node.accept(self) } end diff --git a/templates/rbi/prism/dsl.rbi.erb b/templates/rbi/prism/dsl.rbi.erb deleted file mode 100644 index 76a39c5051..0000000000 --- a/templates/rbi/prism/dsl.rbi.erb +++ /dev/null @@ -1,68 +0,0 @@ -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 deleted file mode 100644 index 0c89b4524c..0000000000 --- a/templates/rbi/prism/node.rbi.erb +++ /dev/null @@ -1,167 +0,0 @@ -class Prism::Node - abstract! - - 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 - - sig { returns(Integer) } - def end_offset; end - - sig { returns(T::Array[String]) } - def source_lines; end - - sig { returns(T::Array[String]) } - def script_lines; end - - sig { returns(String) } - def slice; end - - sig { returns(String) } - def slice_lines; end - - sig { params(q: T.untyped).void } - def pretty_print(q); end - - sig { returns(String) } - def to_dot; end - - 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 { params(block: T.proc.params(node: Prism::Node).returns(T::Boolean)).returns(T::Array[Prism::Node]) } - def breadth_first_search_all(&block); end - - sig { abstract.params(visitor: Prism::Visitor).returns(T.untyped) } - def accept(visitor); end - - sig { abstract.returns(T::Array[T.nilable(Prism::Node)]) } - def child_nodes; end - - sig { abstract.returns(T::Array[T.nilable(Prism::Node)]) } - def deconstruct; end - - sig { abstract.returns(T::Array[Prism::Node]) } - def compact_child_nodes; end - - sig { abstract.returns(T::Array[T.any(Prism::Node, Prism::Location)]) } - def comment_targets; end - - sig { abstract.returns(T::Array[Prism::Reflection::Field]) } - def fields; end - - sig { abstract.returns(Symbol) } - def type; end - - sig { abstract.returns(String) } - def inspect; end -end -<%- nodes.each do |node| -%> - -<%- node.each_comment_line do |line| -%> -#<%= 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_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 - - sig { override.returns(T::Array[T.nilable(Prism::Node)]) } - def child_nodes; end - - sig { override.returns(T::Array[T.nilable(Prism::Node)]) } - def deconstruct; end - - sig { override.returns(T::Array[Prism::Node]) } - def compact_child_nodes; end - - sig { override.returns(T::Array[T.any(Prism::Node, Prism::Location)]) } - def comment_targets; 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 - <%- node.fields.each do |field| -%> - <%- case field -%> - <%- when Prism::Template::LocationField -%> - <%- raise unless field.name.end_with?("_loc") -%> - <%- next if node.fields.any? { |other| other.name == field.name.delete_suffix("_loc") } -%> - - sig { returns(String) } - def <%= field.name.delete_suffix("_loc") %>; end - <%- when Prism::Template::OptionalLocationField -%> - <%- raise unless field.name.end_with?("_loc") -%> - <%- next if node.fields.any? { |other| other.name == field.name.delete_suffix("_loc") } -%> - - sig { returns(T.nilable(String)) } - def <%= field.name.delete_suffix("_loc") %>; end - <%- end -%> - <%- end -%> - - sig { override.returns(T::Array[Prism::Reflection::Field]) } - def fields; end - - sig { override.returns(String) } - def inspect; end - - sig { override.returns(Symbol) } - def type; end -end -<%- end -%> -<%- flags.each do |flag| -%> - -# <%= flag.comment %> -module Prism::<%= flag.name %> - <%- flag.values.each_with_index do |value, index| -%> - # <%= value.comment %> - <%= 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/rbi/prism/visitor.rbi.erb b/templates/rbi/prism/visitor.rbi.erb deleted file mode 100644 index dd42432186..0000000000 --- a/templates/rbi/prism/visitor.rbi.erb +++ /dev/null @@ -1,18 +0,0 @@ -class Prism::BasicVisitor - sig { params(node: T.nilable(Prism::Node)).void } - def visit(node); end - - sig { params(nodes: T::Array[T.nilable(Prism::Node)]).void } - def visit_all(nodes); end - - sig { params(node: Prism::Node).void } - def visit_child_nodes(node); end -end - -class Prism::Visitor < Prism::BasicVisitor - <%- nodes.each_with_index do |node, index| -%> -<%= "\n" if index != 0 -%> - sig { params(node: Prism::<%= node.name %>).void } - def visit_<%= node.human %>(node); end - <%- end -%> -end diff --git a/templates/sig/prism.rbs.erb b/templates/sig/prism.rbs.erb deleted file mode 100644 index ee35feccb8..0000000000 --- a/templates/sig/prism.rbs.erb +++ /dev/null @@ -1,92 +0,0 @@ -module Prism - BACKEND: :CEXT | :FFI - VERSION: String - - class CurrentVersionError < ArgumentError - def initialize: (String version) -> void - end - - # Methods taking a Ruby source code string: - <%- - { - parse: "ParseResult", - profile: "nil", - lex: "LexResult", - lex_compat: "LexCompat::Result", - parse_lex: "ParseLexResult", - dump: "String", - parse_comments: "Array[comment]", - parse_success?: "bool", - parse_failure?: "bool", - }.each do |method, return_type| - -%> - - def self.<%= method %>: ( - String source, - ?command_line: String, - ?encoding: Encoding | false, - ?filepath: String, - ?freeze: bool, - ?frozen_string_literal: bool, - ?line: Integer, - ?main_script: bool, - ?partial_script: bool, - ?scopes: Array[Array[Symbol]], - ?version: String - ) -> <%= return_type %> - <%- end -%> - - def self.load: ( - String source, - String serialized, - ?bool freeze - ) -> ParseResult - - # Methods taking a path to a Ruby file: - <%- - { - parse_file: "ParseResult", - profile_file: "nil", - lex_file: "LexResult", - parse_lex_file: "ParseLexResult", - dump_file: "String", - parse_file_comments: "Array[comment]", - parse_file_success?: "bool", - parse_file_failure?: "bool", - }.each do |method, return_type| - -%> - - def self.<%= method %>: ( - String filepath, - ?command_line: String, - ?encoding: Encoding | false, - ?freeze: bool, - ?frozen_string_literal: bool, - ?line: Integer, - ?main_script: bool, - ?partial_script: bool, - ?scopes: Array[Array[Symbol]], - ?version: String - ) -> <%= return_type %> - <%- end -%> - - interface _Stream - def gets: (?Integer integer) -> (String | nil) - end - - def self.parse_stream: ( - _Stream stream, - ?command_line: String, - ?encoding: Encoding | false, - ?filepath: String, - ?freeze: bool, - ?frozen_string_literal: bool, - ?line: Integer, - ?main_script: bool, - ?partial_script: bool, - ?scopes: Array[Array[Symbol]], - ?version: String - ) -> ParseResult - - def self.scope: (?locals: Array[Symbol], ?forwarding: Array[Symbol]) -> Scope -end diff --git a/templates/sig/prism/_private/dot_visitor.rbs.erb b/templates/sig/prism/_private/dot_visitor.rbs.erb deleted file mode 100644 index 4b380ecc97..0000000000 --- a/templates/sig/prism/_private/dot_visitor.rbs.erb +++ /dev/null @@ -1,45 +0,0 @@ -module Prism - class DotVisitor < Visitor - class Field - attr_reader name: String - attr_reader value: String? - attr_reader port: bool - - def initialize: (String name, String? value, bool port) -> void - def to_dot: () -> String - end - - class Table - attr_reader name: String - attr_reader fields: Array[Field] - - def initialize: (String name) -> void - def field: (String name, ?String? value, ?port: bool) -> void - def to_dot: () -> String - end - - class Digraph - attr_reader nodes: Array[String] - attr_reader waypoints: Array[String] - attr_reader edges: Array[String] - - def initialize: () -> void - def node: (String value) -> void - def waypoint: (String value) -> void - def edge: (String value) -> void - - def to_dot: () -> String - end - - attr_reader digraph: Digraph - - private - - def node_id: (Prism::node node) -> String - def location_inspect: (Location location) -> String - - <%- flags.each do |flag| -%> - 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 deleted file mode 100644 index 401467c0d8..0000000000 --- a/templates/sig/prism/dsl.rbs.erb +++ /dev/null @@ -1,31 +0,0 @@ -module Prism - module DSL - def source: (String string) -> Source - - 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| -%> - - 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/mutation_compiler.rbs.erb b/templates/sig/prism/mutation_compiler.rbs.erb deleted file mode 100644 index 303269ba49..0000000000 --- a/templates/sig/prism/mutation_compiler.rbs.erb +++ /dev/null @@ -1,7 +0,0 @@ -module Prism - class MutationCompiler < Compiler - <%- nodes.each do |node| -%> - def visit_<%= node.human %>: (<%= node.name %>) -> node? - <%- end -%> - end -end diff --git a/templates/sig/prism/node.rbs.erb b/templates/sig/prism/node.rbs.erb deleted file mode 100644 index 138edc11f4..0000000000 --- a/templates/sig/prism/node.rbs.erb +++ /dev/null @@ -1,136 +0,0 @@ -module Prism - class Node - 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 accept: (_Visitor) -> void - def child_nodes: () -> Array[Prism::node?] - def comment_targets: () -> Array[Prism::node | Location] - def compact_child_nodes: () -> Array[Prism::node] - def each_child_node: () { (Prism::node) -> void } -> void | () -> Enumerator[Prism::node] - def self.fields: () -> Array[Prism::Reflection::Field] - def type: () -> Symbol - def self.type: () -> Symbol - - def source_lines: () -> Array[String] - alias script_lines source_lines - def slice: () -> String - def slice_lines: () -> String - 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? - alias find breadth_first_search - def breadth_first_search_all: () { (Prism::node) -> bool } -> Array[Prism::node] - alias find_all breadth_first_search_all - def newline!: (Array[untyped]) -> void - - def save: (_Repository repository) -> void - def save_location: (_Repository repository) -> void - - def leading_comments: () -> Array[comment] - def trailing_comments: () -> Array[comment] - def comments: () -> Array[comment] - - def start_offset: () -> Integer - 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 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 - end - - # Methods implemented by every subclass of Node - interface _Node - def deconstruct: () -> Array[Prism::node?] - def inspect: () -> String - end - - type node = Node & _Node - - interface _Repository - def enter: (Integer node_id, Symbol field_name) -> void - end - - <%- nodes.each do |node| -%> - - <%- node.each_comment_line do |line| -%> - #<%= line %> - <%- 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 -%> - <%- if (locations = node.fields.select { |field| field.is_a?(Prism::Template::LocationField) || field.is_a?(Prism::Template::OptionalLocationField) }) -%> - - <%- locations.each do |field| -%> - def save_<%= field.name %>: (_Repository repository) -> void - <%- end -%> - <%- end -%> - - 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 -%> - <%- 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::OptionalLocationField -%> - <%- 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? - <%- end -%> - <%- end -%> - def type: () -> :<%= node.human %> - | ... - def self.type: () -> :<%= node.human %> - end - <%- end -%> - <%- flags.each do |flag| -%> - - # <%= flag.comment %> - module <%= flag.name %> - <%- flag.values.each do |value| -%> - # <%= value.comment %> - <%= value.name %>: Integer - <%- end -%> - end - <%- end -%> - - # The flags that are common to all nodes. - module NodeFlags - NEWLINE: Integer - STATIC_LITERAL: Integer - end -end diff --git a/templates/sig/prism/visitor.rbs.erb b/templates/sig/prism/visitor.rbs.erb deleted file mode 100644 index 2e8de030f6..0000000000 --- a/templates/sig/prism/visitor.rbs.erb +++ /dev/null @@ -1,17 +0,0 @@ -module Prism - class BasicVisitor - def visit: (Prism::node?) -> void - def visit_all: (Array[Prism::node?]) -> void - def visit_child_nodes: (Prism::node) -> void - end - - interface _Visitor - <%- nodes.each do |node| -%> - def visit_<%= node.human %>: (<%= node.name %>) -> void - <%- end -%> - end - - class Visitor < BasicVisitor - include _Visitor - end -end diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index 88f8525f80..8fa47590c0 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -102,6 +102,8 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_ARGUMENT_FORWARDING_UNBOUND] = { "unexpected `...` in an non-parenthesized call", 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_ELLIPSES_LAMBDA] = { "unexpected ... in lambda argument", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK] = { "unexpected ... in block argument", 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 }, @@ -146,6 +148,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_DEF_ENDLESS] = { "could not parse the endless method body", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_ENDLESS_PARAMETERS] = { "could not parse the endless method parameters", PM_ERROR_LEVEL_SYNTAX }, [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_ENDLESS_DO_BLOCK] = { "unexpected `do` for block 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] = { "unexpected %s; expected a `)` to close the parameters", PM_ERROR_LEVEL_SYNTAX }, @@ -327,13 +330,15 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_PATTERN_TERM_PAREN] = { "expected a `)` to close the pattern expression", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PIPEPIPEEQ_MULTI_ASSIGN] = { "unexpected `||=` in a multiple assignment", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_REGEXP_ENCODING_OPTION_MISMATCH] = { "regexp encoding option '%c' differs from source encoding '%s'", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_REGEXP_ESCAPED_NON_ASCII_IN_UTF8] = { "escaped non ASCII character in UTF-8 regexp: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, [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_CHAR_PROPERTY] = { "invalid character property name {%.*s}: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_REGEXP_INVALID_UNICODE_RANGE] = { "invalid Unicode range: /%.*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_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_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 }, [PM_ERR_RESCUE_MODIFIER_VALUE] = { "expected a value after the `rescue` modifier", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_RESCUE_TERM] = { "expected a closing delimiter for the `rescue` clause", PM_ERROR_LEVEL_SYNTAX }, @@ -488,7 +493,7 @@ pm_diagnostic_list_append_format(pm_list_t *list, uint32_t start, uint32_t lengt size_t message_length = (size_t) (result + 1); char *message = (char *) xmalloc(message_length); if (message == NULL) { - xfree(diagnostic); + xfree_sized(diagnostic, sizeof(pm_diagnostic_t)); return false; } @@ -519,7 +524,7 @@ pm_diagnostic_list_free(pm_list_t *list) { pm_diagnostic_t *next = (pm_diagnostic_t *) node->node.next; if (node->owned) xfree((void *) node->message); - xfree(node); + xfree_sized(node, sizeof(pm_diagnostic_t)); node = next; } diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index f1709a0249..df59545129 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -3,146 +3,73 @@ /** * 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 - * the list to be twice as large as it was before. If the reallocation fails, - * this function returns false, otherwise it returns true. + * capacity in the list, this function does nothing. Otherwise it allocates a + * new array from the arena (abandon-and-copy strategy) and copies the existing + * data into it. */ -static bool -pm_node_list_grow(pm_node_list_t *list, size_t size) { +static void +pm_node_list_grow(pm_arena_t *arena, pm_node_list_t *list, size_t size) { size_t requested_size = list->size + size; - // If the requested size caused overflow, return false. - if (requested_size < list->size) return false; + // Guard against overflow on the addition. + if (requested_size < list->size) abort(); - // If the requested size is within the existing capacity, return true. - if (requested_size < list->capacity) return true; + // If the requested size is within the existing capacity, return. + if (requested_size <= list->capacity) return; - // Otherwise, reallocate the list to be twice as large as it was before. + // Otherwise, compute the next capacity by doubling. size_t next_capacity = list->capacity == 0 ? 4 : list->capacity * 2; - // If multiplying by 2 caused overflow, return false. - if (next_capacity < list->capacity) return false; - - // If we didn't get enough by doubling, keep doubling until we do. + // Guard against overflow on the doubling. while (requested_size > next_capacity) { - size_t double_capacity = next_capacity * 2; - - // Ensure we didn't overflow by multiplying by 2. - if (double_capacity < next_capacity) return false; - next_capacity = double_capacity; + if (next_capacity == 0) abort(); + next_capacity *= 2; } - pm_node_t **nodes = (pm_node_t **) xrealloc(list->nodes, sizeof(pm_node_t *) * next_capacity); - if (nodes == NULL) return false; + // Allocate a new array from the arena (old array is abandoned). + pm_node_t **nodes = (pm_node_t **) pm_arena_alloc(arena, sizeof(pm_node_t *) * next_capacity, PRISM_ALIGNOF(pm_node_t *)); + + // Copy old data into the new array. + if (list->size > 0) { + memcpy(nodes, list->nodes, list->size * sizeof(pm_node_t *)); + } list->nodes = nodes; list->capacity = next_capacity; - return true; } /** * Append a new node onto the end of the node list. */ void -pm_node_list_append(pm_node_list_t *list, pm_node_t *node) { - if (pm_node_list_grow(list, 1)) { - list->nodes[list->size++] = node; - } +pm_node_list_append(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) { + pm_node_list_grow(arena, list, 1); + list->nodes[list->size++] = node; } /** * Prepend a new node onto the beginning of the node list. */ void -pm_node_list_prepend(pm_node_list_t *list, pm_node_t *node) { - if (pm_node_list_grow(list, 1)) { - memmove(list->nodes + 1, list->nodes, list->size * sizeof(pm_node_t *)); - list->nodes[0] = node; - list->size++; - } +pm_node_list_prepend(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) { + pm_node_list_grow(arena, list, 1); + memmove(list->nodes + 1, list->nodes, list->size * sizeof(pm_node_t *)); + list->nodes[0] = node; + list->size++; } /** * Concatenate the given node list onto the end of the other node list. */ void -pm_node_list_concat(pm_node_list_t *list, pm_node_list_t *other) { - if (other->size > 0 && pm_node_list_grow(list, other->size)) { +pm_node_list_concat(pm_arena_t *arena, pm_node_list_t *list, pm_node_list_t *other) { + if (other->size > 0) { + pm_node_list_grow(arena, list, other->size); memcpy(list->nodes + list->size, other->nodes, other->size * sizeof(pm_node_t *)); list->size += other->size; } } -/** - * Free the internal memory associated with the given node list. - */ -void -pm_node_list_free(pm_node_list_t *list) { - if (list->capacity > 0) { - xfree(list->nodes); - *list = (pm_node_list_t) { 0 }; - } -} - -PRISM_EXPORTED_FUNCTION void -pm_node_destroy(pm_parser_t *parser, pm_node_t *node); - -/** - * Destroy the nodes that are contained within the given node list. - */ -static void -pm_node_list_destroy(pm_parser_t *parser, pm_node_list_t *list) { - pm_node_t *node; - PM_NODE_LIST_FOREACH(list, index, node) pm_node_destroy(parser, node); - pm_node_list_free(list); -} - -/** - * Deallocate the space for a pm_node_t. Similarly to pm_node_alloc, we're not - * using the parser argument, but it's there to allow for the future possibility - * of pre-allocating larger memory pools. - */ -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 %> "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::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::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 -%> - if (cast-><%= field.name %> != NULL) { - pm_node_destroy(parser, (pm_node_t *)cast-><%= field.name %>); - } - <%- when Prism::Template::StringField -%> - pm_string_free(&cast-><%= field.name %>); - <%- when Prism::Template::NodeListField -%> - pm_node_list_destroy(parser, &cast-><%= field.name %>); - <%- when Prism::Template::ConstantListField -%> - pm_constant_id_list_free(&cast-><%= field.name %>); - <%- when Prism::Template::IntegerField -%> - pm_integer_free(&cast-><%= field.name %>); - <%- else -%> - <%- raise -%> - <%- end -%> - <%- end -%> - break; - } - <%- end -%> -#line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" - default: - assert(false && "unreachable"); - break; - } - xfree(node); -} - /** * Returns a string representation of the given node type. */ @@ -246,7 +173,11 @@ pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *no // Dump the <%= field.name %> field pm_buffer_append_byte(buffer, ','); + <%- if field.is_a?(Prism::Template::Flags) -%> + pm_buffer_append_string(buffer, "\"flags\":", 8); + <%- else -%> pm_buffer_append_string(buffer, "\"<%= field.name %>\":", <%= field.name.bytesize + 3 %>); + <%- end -%> <%- case field -%> <%- when Prism::Template::NodeField -%> pm_dump_json(buffer, parser, (const pm_node_t *) cast-><%= field.name %>); diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index 74c0f6dbdf..44423ca42b 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -12,8 +12,8 @@ void pm_prettyprint(void) {} static inline void prettyprint_location(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_location_t *location) { - pm_line_column_t start = pm_newline_list_line_column(&parser->newline_list, location->start, parser->start_line); - pm_line_column_t end = pm_newline_list_line_column(&parser->newline_list, location->start + location->length, parser->start_line); + pm_line_column_t start = pm_line_offset_list_line_column(&parser->line_offsets, location->start, parser->start_line); + pm_line_column_t end = pm_line_offset_list_line_column(&parser->line_offsets, location->start + location->length, parser->start_line); pm_buffer_append_format(output_buffer, "(%" PRIi32 ",%" PRIu32 ")-(%" PRIi32 ",%" PRIu32 ")", start.line, start.column, end.line, end.column); } diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 958b0fd7cf..78e4f34893 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -26,28 +26,10 @@ pm_serialize_location(const pm_location_t *location, pm_buffer_t *buffer) { } static void -pm_serialize_string(const pm_parser_t *parser, const pm_string_t *string, pm_buffer_t *buffer) { - switch (string->type) { - case PM_STRING_SHARED: { - pm_buffer_append_byte(buffer, 1); - pm_buffer_append_varuint(buffer, pm_ptrdifft_to_u32(pm_string_source(string) - parser->start)); - pm_buffer_append_varuint(buffer, pm_sizet_to_u32(pm_string_length(string))); - break; - } - case PM_STRING_OWNED: - case PM_STRING_CONSTANT: { - uint32_t length = pm_sizet_to_u32(pm_string_length(string)); - pm_buffer_append_byte(buffer, 2); - pm_buffer_append_varuint(buffer, length); - pm_buffer_append_bytes(buffer, pm_string_source(string), length); - break; - } -#ifdef PRISM_HAS_MMAP - case PM_STRING_MAPPED: - assert(false && "Cannot serialize mapped strings."); - break; -#endif - } +pm_serialize_string(const pm_string_t *string, pm_buffer_t *buffer) { + uint32_t length = pm_sizet_to_u32(pm_string_length(string)); + pm_buffer_append_varuint(buffer, length); + pm_buffer_append_bytes(buffer, pm_string_source(string), length); } static void @@ -68,8 +50,6 @@ static void pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { pm_buffer_append_byte(buffer, (uint8_t) PM_NODE_TYPE(node)); - size_t offset = buffer->length; - <%- if Prism::Template::INCLUDE_NODE_ID -%> pm_buffer_append_varuint(buffer, node->node_id); <%- end -%> @@ -102,7 +82,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { pm_serialize_node(parser, (pm_node_t *)((pm_<%= node.human %>_t *)node)-><%= field.name %>, buffer); } <%- when Prism::Template::StringField -%> - pm_serialize_string(parser, &((pm_<%= node.human %>_t *)node)-><%= field.name %>, buffer); + pm_serialize_string(&((pm_<%= node.human %>_t *)node)-><%= field.name %>, buffer); <%- when Prism::Template::NodeListField -%> uint32_t <%= field.name %>_size = pm_sizet_to_u32(((pm_<%= node.human %>_t *)node)-><%= field.name %>.size); pm_buffer_append_varuint(buffer, <%= field.name %>_size); @@ -144,7 +124,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { <%- end -%> <%- if node.needs_serialized_length? -%> // serialize length - uint32_t length = pm_sizet_to_u32(buffer->length - offset - sizeof(uint32_t)); + uint32_t length = pm_sizet_to_u32(buffer->length - length_offset); memcpy(buffer->value + length_offset, &length, sizeof(uint32_t)); <%- end -%> break; @@ -154,7 +134,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } static void -pm_serialize_newline_list(pm_newline_list_t *list, pm_buffer_t *buffer) { +pm_serialize_line_offset_list(pm_line_offset_list_t *list, pm_buffer_t *buffer) { uint32_t size = pm_sizet_to_u32(list->size); pm_buffer_append_varuint(buffer, size); @@ -257,7 +237,7 @@ static void pm_serialize_metadata(pm_parser_t *parser, pm_buffer_t *buffer) { pm_serialize_encoding(parser->encoding, buffer); pm_buffer_append_varsint(buffer, parser->start_line); - pm_serialize_newline_list(&parser->newline_list, buffer); + pm_serialize_line_offset_list(&parser->line_offsets, buffer); <%- unless Prism::Template::SERIALIZE_ONLY_SEMANTICS_FIELDS -%> pm_serialize_comment_list(&parser->comment_list, buffer); <%- end -%> @@ -265,6 +245,7 @@ pm_serialize_metadata(pm_parser_t *parser, pm_buffer_t *buffer) { pm_serialize_data_loc(parser, buffer); pm_serialize_diagnostic_list(&parser->error_list, buffer); pm_serialize_diagnostic_list(&parser->warning_list, buffer); + pm_buffer_append_byte(buffer, (uint8_t) parser->continuable); } #line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" @@ -304,28 +285,12 @@ pm_serialize_content(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) pm_constant_t *constant = &parser->constant_pool.constants[bucket->id - 1]; size_t buffer_offset = offset + ((((size_t)bucket->id) - 1) * 8); - if (bucket->type == PM_CONSTANT_POOL_BUCKET_OWNED || bucket->type == PM_CONSTANT_POOL_BUCKET_CONSTANT) { - // Since this is an owned or constant constant, we are going to - // write its contents into the buffer after the constant pool. - // So effectively in place of the source offset, we have a - // buffer offset. We will add a leading 1 to indicate that this - // is a buffer offset. - uint32_t content_offset = pm_sizet_to_u32(buffer->length); - uint32_t owned_mask = 1U << 31; + // Write the constant contents into the buffer after the constant + // pool. In place of the source offset, we store a buffer offset. + uint32_t content_offset = pm_sizet_to_u32(buffer->length); + memcpy(buffer->value + buffer_offset, &content_offset, 4); + pm_buffer_append_bytes(buffer, constant->start, constant->length); - assert(content_offset < owned_mask); - content_offset |= owned_mask; - - memcpy(buffer->value + buffer_offset, &content_offset, 4); - pm_buffer_append_bytes(buffer, constant->start, constant->length); - } else { - // Since this is a shared constant, we are going to write its - // source offset directly into the buffer. - uint32_t source_offset = pm_ptrdifft_to_u32(constant->start - parser->start); - memcpy(buffer->value + buffer_offset, &source_offset, 4); - } - - // Now we can write the length of the constant into the buffer. uint32_t constant_length = pm_sizet_to_u32(constant->length); memcpy(buffer->value + buffer_offset + 4, &constant_length, 4); } @@ -350,8 +315,9 @@ pm_serialize_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const pm_options_t options = { 0 }; pm_options_read(&options, data); + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, source, size, &options); + pm_parser_init(&arena, &parser, source, size, &options); pm_lex_callback_t lex_callback = (pm_lex_callback_t) { .data = (void *) buffer, @@ -359,15 +325,15 @@ pm_serialize_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const }; parser.lex_callback = &lex_callback; - pm_node_t *node = pm_parse(&parser); + pm_parse(&parser); // Append 0 to mark end of tokens. pm_buffer_append_byte(buffer, 0); pm_serialize_metadata(&parser, buffer); - pm_node_destroy(&parser, node); pm_parser_free(&parser); + pm_arena_free(&arena); pm_options_free(&options); } @@ -380,8 +346,9 @@ pm_serialize_parse_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, pm_options_t options = { 0 }; pm_options_read(&options, data); + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, source, size, &options); + pm_parser_init(&arena, &parser, source, size, &options); pm_lex_callback_t lex_callback = (pm_lex_callback_t) { .data = (void *) buffer, @@ -394,8 +361,8 @@ pm_serialize_parse_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, pm_buffer_append_byte(buffer, 0); pm_serialize(&parser, node, buffer); - pm_node_destroy(&parser, node); pm_parser_free(&parser); + pm_arena_free(&arena); pm_options_free(&options); } diff --git a/templates/src/token_type.c.erb b/templates/src/token_type.c.erb index 5c6f271310..94e41ec4ba 100644 --- a/templates/src/token_type.c.erb +++ b/templates/src/token_type.c.erb @@ -167,6 +167,8 @@ pm_token_type_human(pm_token_type_t token_type) { return "'defined?'"; case PM_TOKEN_KEYWORD_DO: return "'do'"; + case PM_TOKEN_KEYWORD_DO_BLOCK: + return "'do'"; case PM_TOKEN_KEYWORD_DO_LOOP: return "'do'"; case PM_TOKEN_KEYWORD_ELSE: diff --git a/templates/template.rb b/templates/template.rb index aca626b5eb..70fa17c83d 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -6,7 +6,7 @@ require "yaml" module Prism - module Template + module Template # :nodoc: all 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) @@ -105,6 +105,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 + # The C type to use for this field as a function parameter. + def c_param + "struct #{c_type} *#{name}" + end + def initialize(kind:, **options) @kind = kind super(**options) @@ -150,19 +155,19 @@ def rbs_class if specific_kind specific_kind elsif union_kind - union_kind.join(" | ") + "(#{union_kind.join(" | ")})" else "Prism::node" end end - def rbi_class + def call_seq_type if specific_kind - "Prism::#{specific_kind}" + specific_kind elsif union_kind - "T.any(#{union_kind.map { |kind| "Prism::#{kind}" }.join(", ")})" + union_kind.join(" | ") else - "Prism::Node" + "Node" end end @@ -182,19 +187,19 @@ def rbs_class if specific_kind "#{specific_kind}?" elsif union_kind - [*union_kind, "nil"].join(" | ") + "(#{union_kind.join(" | ")})?" else "Prism::node?" end end - def rbi_class + def call_seq_type if specific_kind - "T.nilable(Prism::#{specific_kind})" + "#{specific_kind} | nil" elsif union_kind - "T.nilable(T.any(#{union_kind.map { |kind| "Prism::#{kind}" }.join(", ")}))" + [*union_kind, "nil"].join(" | ") else - "T.nilable(Prism::Node)" + "Node | nil" end end @@ -210,23 +215,31 @@ def check_field_kind # This represents a field on a node that is a list of nodes. We pass them as # references and store them directly on the struct. class NodeListField < NodeKindField - def rbs_class + def c_param + "pm_node_list_t #{name}" + end + + def element_rbs_class if specific_kind - "Array[#{specific_kind}]" + "#{specific_kind}" elsif union_kind - "Array[#{union_kind.join(" | ")}]" + "#{union_kind.join(" | ")}" else - "Array[Prism::node]" + "Prism::node" end end - def rbi_class + def rbs_class + "Array[#{element_rbs_class}]" + end + + def call_seq_type if specific_kind - "T::Array[Prism::#{specific_kind}]" + "Array[#{specific_kind}]" elsif union_kind - "T::Array[T.any(#{union_kind.map { |kind| "Prism::#{kind}" }.join(", ")})]" + "Array[#{union_kind.join(" | ")}]" else - "T::Array[Prism::Node]" + "Array[Node]" end end @@ -246,11 +259,15 @@ def check_field_kind # This represents a field on a node that is the ID of a string interned # through the parser's constant pool. class ConstantField < Field + def c_param + "pm_constant_id_t #{name}" + end + def rbs_class "Symbol" end - def rbi_class + def call_seq_type "Symbol" end @@ -262,12 +279,16 @@ def java_type # This represents a field on a node that is the ID of a string interned # through the parser's constant pool and can be optionally null. class OptionalConstantField < Field + def c_param + "pm_constant_id_t #{name}" + end + def rbs_class "Symbol?" end - def rbi_class - "T.nilable(Symbol)" + def call_seq_type + "Symbol | nil" end def java_type @@ -278,12 +299,16 @@ def java_type # This represents a field on a node that is a list of IDs that are associated # with strings interned through the parser's constant pool. class ConstantListField < Field + def c_param + "pm_constant_id_list_t #{name}" + end + def rbs_class "Array[Symbol]" end - def rbi_class - "T::Array[Symbol]" + def call_seq_type + "Array[Symbol]" end def java_type @@ -293,11 +318,15 @@ def java_type # This represents a field on a node that is a string. class StringField < Field + def c_param + "pm_string_t #{name}" + end + def rbs_class "String" end - def rbi_class + def call_seq_type "String" end @@ -308,6 +337,10 @@ def java_type # This represents a field on a node that is a location. class LocationField < Field + def c_param + "pm_location_t #{name}" + end + def semantic_field? false end @@ -316,8 +349,8 @@ def rbs_class "Location" end - def rbi_class - "Prism::Location" + def call_seq_type + "Location" end def java_type @@ -327,6 +360,10 @@ def java_type # This represents a field on a node that is a location that is optional. class OptionalLocationField < Field + def c_param + "pm_location_t #{name}" + end + def semantic_field? false end @@ -335,8 +372,8 @@ def rbs_class "Location?" end - def rbi_class - "T.nilable(Prism::Location)" + def call_seq_type + "Location | nil" end def java_type @@ -346,11 +383,15 @@ def java_type # This represents an integer field. class UInt8Field < Field + def c_param + "uint8_t #{name}" + end + def rbs_class "Integer" end - def rbi_class + def call_seq_type "Integer" end @@ -361,11 +402,15 @@ def java_type # This represents an integer field. class UInt32Field < Field + def c_param + "uint32_t #{name}" + end + def rbs_class "Integer" end - def rbi_class + def call_seq_type "Integer" end @@ -377,11 +422,15 @@ def java_type # This represents an arbitrarily-sized integer. When it gets to Ruby it will # be an Integer. class IntegerField < Field + def c_param + "pm_integer_t #{name}" + end + def rbs_class "Integer" end - def rbi_class + def call_seq_type "Integer" end @@ -393,11 +442,15 @@ def java_type # This represents a double-precision floating point number. When it gets to # Ruby it will be a Float. class DoubleField < Field + def c_param + "double #{name}" + end + def rbs_class "Float" end - def rbi_class + def call_seq_type "Float" end @@ -555,8 +608,7 @@ def render(name, write_to: nil) extension = File.extname(filepath.gsub(".erb", "")) heading = - case extension - when ".rb" + if extension == ".rb" <<~HEADING # frozen_string_literal: true # :markup: markdown @@ -569,29 +621,9 @@ def render(name, write_to: nil) ++ =end - HEADING - when ".rbs" - <<~HEADING - # This file is generated by the templates/template.rb script and should not be - # modified manually. See #{filepath} - # if you are looking to modify the template - - HEADING - when ".rbi" - <<~HEADING - # typed: strict - - =begin - This file is generated by the templates/template.rb script and should not be - modified manually. See #{filepath} - if you are looking to modify the template - =end - HEADING else <<~HEADING - /* :markup: markdown */ - /*----------------------------------------------------------------------------*/ /* This file is generated by the templates/template.rb script and should not */ /* be modified manually. See */ @@ -653,12 +685,13 @@ def locals "ext/prism/api_node.c", "include/prism/ast.h", "include/prism/diagnostic.h", + "include/prism/node_new.h", "javascript/src/deserialize.js", "javascript/src/nodes.js", "javascript/src/visitor.js", - "java/org/prism/Loader.java", - "java/org/prism/Nodes.java", - "java/org/prism/AbstractNodeVisitor.java", + "java/org/ruby_lang/prism/Loader.java", + "java/org/ruby_lang/prism/Nodes.java", + "java/org/ruby_lang/prism/AbstractNodeVisitor.java", "lib/prism/compiler.rb", "lib/prism/dispatcher.rb", "lib/prism/dot_visitor.rb", @@ -673,16 +706,7 @@ def locals "src/node.c", "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", - "sig/prism/dsl.rbs", - "sig/prism/mutation_compiler.rbs", - "sig/prism/node.rbs", - "sig/prism/visitor.rbs", - "sig/prism/_private/dot_visitor.rbs" + "src/token_type.c" ] end end diff --git a/test/prism/api/parse_stream_test.rb b/test/prism/api/parse_stream_test.rb index 1c068c617c..3bc86fbd61 100644 --- a/test/prism/api/parse_stream_test.rb +++ b/test/prism/api/parse_stream_test.rb @@ -30,16 +30,28 @@ def test_multi_read end def test___END__ - io = StringIO.new("1 + 2\n3 + 4\n__END__\n5 + 6") + io = StringIO.new(<<~RUBY) + 1 + 2 + 3 + 4 + __END__ + 5 + 6 + RUBY result = Prism.parse_stream(io) assert result.success? assert_equal 2, result.value.statements.body.length - assert_equal "5 + 6", io.read + assert_equal "5 + 6\n", io.read end def test_false___END___in_string - io = StringIO.new("1 + 2\n3 + 4\n\"\n__END__\n\"\n5 + 6") + io = StringIO.new(<<~RUBY) + 1 + 2 + 3 + 4 + " + __END__ + " + 5 + 6 + RUBY result = Prism.parse_stream(io) assert result.success? @@ -47,7 +59,14 @@ def test_false___END___in_string end def test_false___END___in_regexp - io = StringIO.new("1 + 2\n3 + 4\n/\n__END__\n/\n5 + 6") + io = StringIO.new(<<~RUBY) + 1 + 2 + 3 + 4 + / + __END__ + / + 5 + 6 + RUBY result = Prism.parse_stream(io) assert result.success? @@ -55,7 +74,14 @@ def test_false___END___in_regexp end def test_false___END___in_list - io = StringIO.new("1 + 2\n3 + 4\n%w[\n__END__\n]\n5 + 6") + io = StringIO.new(<<~RUBY) + 1 + 2 + 3 + 4 + %w[ + __END__ + ] + 5 + 6 + RUBY result = Prism.parse_stream(io) assert result.success? @@ -63,7 +89,14 @@ def test_false___END___in_list end def test_false___END___in_heredoc - io = StringIO.new("1 + 2\n3 + 4\n<<-EOF\n__END__\nEOF\n5 + 6") + io = StringIO.new(<<~RUBY) + 1 + 2 + 3 + 4 + <<-EOF + __END__ + EOF + 5 + 6 + RUBY result = Prism.parse_stream(io) assert result.success? @@ -71,7 +104,11 @@ def test_false___END___in_heredoc end def test_nul_bytes - io = StringIO.new("1 # \0\0\0 \n2 # \0\0\0\n3") + io = StringIO.new(<<~RUBY) + 1 # \0\0\0\t + 2 # \0\0\0 + 3 + RUBY result = Prism.parse_stream(io) assert result.success? diff --git a/test/prism/api/parse_test.rb b/test/prism/api/parse_test.rb index bbf28201ff..c9a47c1a61 100644 --- a/test/prism/api/parse_test.rb +++ b/test/prism/api/parse_test.rb @@ -154,6 +154,10 @@ def test_version_current end end + def test_nearest + assert Prism.parse_success?("1 + 1", version: "nearest") + end + def test_scopes assert_kind_of Prism::CallNode, Prism.parse_statement("foo") assert_kind_of Prism::LocalVariableReadNode, Prism.parse_statement("foo", scopes: [[:foo]]) diff --git a/test/prism/encoding/regular_expression_encoding_test.rb b/test/prism/encoding/regular_expression_encoding_test.rb index e2daae1d7f..fdff1e3281 100644 --- a/test/prism/encoding/regular_expression_encoding_test.rb +++ b/test/prism/encoding/regular_expression_encoding_test.rb @@ -2,6 +2,7 @@ return unless defined?(RubyVM::InstructionSequence) return if RubyVM::InstructionSequence.compile("").to_a[4][:parser] == :prism +return if RUBY_VERSION < "3.2" require_relative "../test_helper" @@ -21,7 +22,7 @@ class RegularExpressionEncodingTest < TestCase ["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}" ] + regexp_sources = ["abc", "garçon", "\\x80", "gar\\xC3\\xA7on", "gar\\u{E7}on", "abc\\u{FFFFFF}", "\\x80\\u{80}", "\\p{L}" ] assert_regular_expression_encoding_flags( encoding, @@ -35,17 +36,15 @@ class RegularExpressionEncodingTest < TestCase 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 + encoding_errors = [ + "invalid multibyte char", "escaped non ASCII character in UTF-8 regexp", + "differs from source encoding", "incompatible character encoding", + "invalid multibyte escape", "UTF-8 character in non UTF-8 regexp", + "invalid Unicode range", "non escaped non ASCII character", + "invalid character property name", "invalid Unicode list", + ] expected = begin @@ -53,8 +52,6 @@ def assert_regular_expression_encoding_flags(encoding, regexps) 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 @@ -111,19 +108,6 @@ def assert_regular_expression_encoding_flags(encoding, regexps) 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.pop - actual.pop - end - end - assert_equal expected, actual end end diff --git a/test/prism/errors/do_not_allow_trailing_commas_in_method_parameters.txt b/test/prism/errors/3.3-4.0/do_not_allow_trailing_commas_in_method_parameters.txt similarity index 100% rename from test/prism/errors/do_not_allow_trailing_commas_in_method_parameters.txt rename to test/prism/errors/3.3-4.0/do_not_allow_trailing_commas_in_method_parameters.txt diff --git a/test/prism/errors/3.3-4.0/noblock.txt b/test/prism/errors/3.3-4.0/noblock.txt new file mode 100644 index 0000000000..07939041bb --- /dev/null +++ b/test/prism/errors/3.3-4.0/noblock.txt @@ -0,0 +1,6 @@ +def foo(&nil) + ^~~ unexpected 'nil'; expected a `)` to close the parameters + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it +end + diff --git a/test/prism/errors/4.1/do_not_allow_trailing_commas_after_terminating_arguments.txt b/test/prism/errors/4.1/do_not_allow_trailing_commas_after_terminating_arguments.txt new file mode 100644 index 0000000000..b3e06f4154 --- /dev/null +++ b/test/prism/errors/4.1/do_not_allow_trailing_commas_after_terminating_arguments.txt @@ -0,0 +1,6 @@ +def foo(a,b,...,);end + ^ unexpected `,` in parameters + +def foo(a,b,&block,);end + ^ unexpected `,` in parameters + diff --git a/test/prism/errors/4.1/multiple_blocks.txt b/test/prism/errors/4.1/multiple_blocks.txt new file mode 100644 index 0000000000..7e8433cf82 --- /dev/null +++ b/test/prism/errors/4.1/multiple_blocks.txt @@ -0,0 +1,12 @@ +def foo(&nil, &nil); end + ^ unexpected parameter order + ^~~~ multiple block parameters; only one block is allowed + +def foo(&foo, &nil); end + ^ unexpected parameter order + ^~~~ multiple block parameters; only one block is allowed + +def foo(&nil, &foo); end + ^ unexpected parameter order + ^~~~ multiple block parameters; only one block is allowed + diff --git a/test/prism/errors/command_call_in.txt b/test/prism/errors/command_call_in.txt index 2fdcf09738..2b7286abc3 100644 --- a/test/prism/errors/command_call_in.txt +++ b/test/prism/errors/command_call_in.txt @@ -2,4 +2,5 @@ foo 1 in a ^~ unexpected 'in', expecting end-of-input ^~ unexpected 'in', ignoring it a = foo 2 in b + ^~ unexpected 'in', expecting end-of-input diff --git a/test/prism/errors/command_call_in_2.txt b/test/prism/errors/command_call_in_2.txt new file mode 100644 index 0000000000..6676b1acba --- /dev/null +++ b/test/prism/errors/command_call_in_2.txt @@ -0,0 +1,4 @@ +a.b x in pattern + ^~ unexpected 'in', expecting end-of-input + ^~ unexpected 'in', ignoring it + diff --git a/test/prism/errors/command_call_in_3.txt b/test/prism/errors/command_call_in_3.txt new file mode 100644 index 0000000000..6fe026d7d3 --- /dev/null +++ b/test/prism/errors/command_call_in_3.txt @@ -0,0 +1,4 @@ +a.b x: in pattern + ^~ unexpected 'in', expecting end-of-input + ^~ unexpected 'in', ignoring it + diff --git a/test/prism/errors/command_call_in_4.txt b/test/prism/errors/command_call_in_4.txt new file mode 100644 index 0000000000..045afe6498 --- /dev/null +++ b/test/prism/errors/command_call_in_4.txt @@ -0,0 +1,4 @@ +a.b &x in pattern + ^~ unexpected 'in', expecting end-of-input + ^~ unexpected 'in', ignoring it + diff --git a/test/prism/errors/command_call_in_5.txt b/test/prism/errors/command_call_in_5.txt new file mode 100644 index 0000000000..be07287f81 --- /dev/null +++ b/test/prism/errors/command_call_in_5.txt @@ -0,0 +1,4 @@ +a.b *x => pattern + ^~ unexpected '=>', expecting end-of-input + ^~ unexpected '=>', ignoring it + diff --git a/test/prism/errors/command_call_in_6.txt b/test/prism/errors/command_call_in_6.txt new file mode 100644 index 0000000000..470f323872 --- /dev/null +++ b/test/prism/errors/command_call_in_6.txt @@ -0,0 +1,4 @@ +a.b x: => pattern + ^~ unexpected '=>', expecting end-of-input + ^~ unexpected '=>', ignoring it + diff --git a/test/prism/errors/command_call_in_7.txt b/test/prism/errors/command_call_in_7.txt new file mode 100644 index 0000000000..a8bea912b5 --- /dev/null +++ b/test/prism/errors/command_call_in_7.txt @@ -0,0 +1,4 @@ +a.b &x => pattern + ^~ unexpected '=>', expecting end-of-input + ^~ unexpected '=>', ignoring it + diff --git a/test/prism/errors/command_call_value_and.txt b/test/prism/errors/command_call_value_and.txt new file mode 100644 index 0000000000..a131aa5530 --- /dev/null +++ b/test/prism/errors/command_call_value_and.txt @@ -0,0 +1,3 @@ +a = b c and 1 + ^~~ unexpected 'and', expecting end-of-input + diff --git a/test/prism/errors/command_call_value_or.txt b/test/prism/errors/command_call_value_or.txt new file mode 100644 index 0000000000..cc75714166 --- /dev/null +++ b/test/prism/errors/command_call_value_or.txt @@ -0,0 +1,3 @@ +a = b c or 1 + ^~ unexpected 'or', expecting end-of-input + diff --git a/test/prism/errors/command_calls_34.txt b/test/prism/errors/command_calls_34.txt index ce62bc1492..bc0ea5e81c 100644 --- a/test/prism/errors/command_calls_34.txt +++ b/test/prism/errors/command_calls_34.txt @@ -1,12 +1,19 @@ foo(bar 1 do end, 2) - ^ invalid comma - ^ unexpected integer; expected a `)` to close the arguments - ^ unexpected integer, expecting end-of-input + ^~ unexpected 'do'; expected a `)` to close the arguments + ^~ unexpected 'do', expecting end-of-input + ^~ unexpected 'do', ignoring it + ^~~ unexpected 'end', ignoring it + ^ unexpected ',', ignoring it ^ unexpected ')', expecting end-of-input ^ unexpected ')', ignoring it foo(bar 1 do end,) - ^ invalid comma + ^~ unexpected 'do'; expected a `)` to close the arguments + ^~ unexpected 'do', expecting end-of-input + ^~ unexpected 'do', ignoring it + ^~~ unexpected 'end', ignoring it + ^ unexpected ',', ignoring it + ^ unexpected ')', ignoring it foo(1, bar 2 do end) ^ unexpected integer; expected a `)` to close the arguments diff --git a/test/prism/errors/command_calls_35.txt b/test/prism/errors/command_calls_35.txt index 45f569b117..bd72d1be56 100644 --- a/test/prism/errors/command_calls_35.txt +++ b/test/prism/errors/command_calls_35.txt @@ -14,7 +14,11 @@ p(p a, &block => value) ^ unexpected ')', ignoring it p(p a do end => value) - ^~ unexpected '=>'; expected a `)` to close the arguments + ^~ unexpected 'do'; expected a `)` to close the arguments + ^~ unexpected 'do', expecting end-of-input + ^~ unexpected 'do', ignoring it + ^~~ unexpected 'end', ignoring it + ^~ unexpected '=>', ignoring it ^ unexpected ')', expecting end-of-input ^ unexpected ')', ignoring it diff --git a/test/prism/errors/def_endless_do.txt b/test/prism/errors/def_endless_do.txt new file mode 100644 index 0000000000..d66b7086da --- /dev/null +++ b/test/prism/errors/def_endless_do.txt @@ -0,0 +1,6 @@ +def a = a b do 1 end + ^~ unexpected 'do', expecting end-of-input + ^~ unexpected 'do', ignoring it + ^~~ unexpected 'end', expecting end-of-input + ^~~ unexpected 'end', ignoring it + diff --git a/test/prism/errors/destroy_call_operator_write_arguments.txt b/test/prism/errors/destroy_call_operator_write_arguments.txt index c3c72f9226..b6933d61d1 100644 --- a/test/prism/errors/destroy_call_operator_write_arguments.txt +++ b/test/prism/errors/destroy_call_operator_write_arguments.txt @@ -2,9 +2,9 @@ t next&&do end&= ^~ unexpected 'do'; expected an expression after the operator ^~~~ unexpected void value expression ^~~~ unexpected void value expression -^~~~~~~~~~~~~~ unexpected write target - ^~ unexpected operator after a call with arguments - ^~ unexpected operator after a call with a block + ^~ unexpected '&=', expecting end-of-input + ^~ unexpected '&=', ignoring it + ^~~~ Invalid next ''while= ^~~~~ expected a predicate expression for the `while` statement ^ unexpected '='; target cannot be written 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 index df49557617..639dec3af2 100644 --- a/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt +++ b/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt @@ -1,3 +1,13 @@ a {|...|} - ^~~ unexpected ... when the parent method is not forwarding + ^~~ unexpected ... in block argument + +def foo(...) + a {|...|} + ^~~ unexpected ... in block argument +end + +def foo + a {|...|} + ^~~ unexpected ... in block argument +end 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 index c2405a5c66..03e17683e4 100644 --- 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 @@ -1,3 +1,13 @@ ->(...) {} - ^~~ unexpected ... when the parent method is not forwarding + ^~~ unexpected ... in lambda argument + +def foo(...) + ->(...) {} + ^~~ unexpected ... in lambda argument +end + +def foo + ->(...) {} + ^~~ unexpected ... in lambda argument +end diff --git a/test/prism/errors/match_predicate_after_rescue_with_dot_method_call.txt b/test/prism/errors/match_predicate_after_rescue_with_dot_method_call.txt index fead8aaf23..f599dc476b 100644 --- a/test/prism/errors/match_predicate_after_rescue_with_dot_method_call.txt +++ b/test/prism/errors/match_predicate_after_rescue_with_dot_method_call.txt @@ -1,3 +1,4 @@ 'a' rescue 2 in 3.upcase ^ unexpected '.', expecting end-of-input + ^ unexpected '.', ignoring it diff --git a/test/prism/errors/match_predicate_after_rescue_with_opreator.txt b/test/prism/errors/match_predicate_after_rescue_with_opreator.txt index b2363a544d..44a4ba8488 100644 --- a/test/prism/errors/match_predicate_after_rescue_with_opreator.txt +++ b/test/prism/errors/match_predicate_after_rescue_with_opreator.txt @@ -1,3 +1,4 @@ 1 rescue 2 in 3 << 4 ^~ unexpected <<, expecting end-of-input + ^~ unexpected <<, ignoring it diff --git a/test/prism/errors/match_required_after_rescue_with_dot_method_call.txt b/test/prism/errors/match_required_after_rescue_with_dot_method_call.txt index d72d72ce60..abcfaf094d 100644 --- a/test/prism/errors/match_required_after_rescue_with_dot_method_call.txt +++ b/test/prism/errors/match_required_after_rescue_with_dot_method_call.txt @@ -1,3 +1,4 @@ 1 rescue 2 => 3.inspect ^ unexpected '.', expecting end-of-input + ^ unexpected '.', ignoring it diff --git a/test/prism/errors/match_required_after_rescue_with_opreator.txt b/test/prism/errors/match_required_after_rescue_with_opreator.txt index 903e2ccc8e..5e6387ca4d 100644 --- a/test/prism/errors/match_required_after_rescue_with_opreator.txt +++ b/test/prism/errors/match_required_after_rescue_with_opreator.txt @@ -1,3 +1,4 @@ 1 rescue 2 => 3 ** 4 ^~ unexpected '**', expecting end-of-input + ^~ unexpected '**', ignoring it diff --git a/test/prism/errors/not_without_parens_assignment.txt b/test/prism/errors/not_without_parens_assignment.txt new file mode 100644 index 0000000000..32d58efedf --- /dev/null +++ b/test/prism/errors/not_without_parens_assignment.txt @@ -0,0 +1,4 @@ +x = not y + ^ expected a `(` after `not` + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/not_without_parens_call.txt b/test/prism/errors/not_without_parens_call.txt new file mode 100644 index 0000000000..a778193400 --- /dev/null +++ b/test/prism/errors/not_without_parens_call.txt @@ -0,0 +1,7 @@ +foo(not y) + ^ expected a `(` after `not` + ^ 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/not_without_parens_command.txt b/test/prism/errors/not_without_parens_command.txt new file mode 100644 index 0000000000..957a06f8f1 --- /dev/null +++ b/test/prism/errors/not_without_parens_command.txt @@ -0,0 +1,4 @@ +foo not y + ^ expected a `(` after `not` + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/not_without_parens_command_call.txt b/test/prism/errors/not_without_parens_command_call.txt new file mode 100644 index 0000000000..564833c7de --- /dev/null +++ b/test/prism/errors/not_without_parens_command_call.txt @@ -0,0 +1,4 @@ +a.b not y + ^ expected a `(` after `not` + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/not_without_parens_return.txt b/test/prism/errors/not_without_parens_return.txt new file mode 100644 index 0000000000..1c7edb6ff1 --- /dev/null +++ b/test/prism/errors/not_without_parens_return.txt @@ -0,0 +1,4 @@ +return not y + ^ expected a `(` after `not` + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/rescue_pattern.txt b/test/prism/errors/rescue_pattern.txt new file mode 100644 index 0000000000..c85feb27bd --- /dev/null +++ b/test/prism/errors/rescue_pattern.txt @@ -0,0 +1,4 @@ +a rescue b => c in d + ^~ unexpected 'in', expecting end-of-input + ^~ unexpected 'in', ignoring it + diff --git a/test/prism/errors/unterminated_heredoc_and_embexpr.txt b/test/prism/errors/unterminated_heredoc_and_embexpr.txt new file mode 100644 index 0000000000..bed7fcd24e --- /dev/null +++ b/test/prism/errors/unterminated_heredoc_and_embexpr.txt @@ -0,0 +1,11 @@ +< (&nil) {} diff --git a/test/prism/fixtures/4.1/trailing_comma_after_method_arguments.txt b/test/prism/fixtures/4.1/trailing_comma_after_method_arguments.txt new file mode 100644 index 0000000000..ef1385d973 --- /dev/null +++ b/test/prism/fixtures/4.1/trailing_comma_after_method_arguments.txt @@ -0,0 +1,15 @@ +def foo(a,b,c,);end + +def foo(a,b,*c,);end + +def foo(a,b,*,);end + +def foo(a,b,**c,);end + +def foo(a,b,**,);end + +def foo( + a, + b, + c, +);end diff --git a/test/prism/fixtures/and_or_with_suffix.txt b/test/prism/fixtures/and_or_with_suffix.txt new file mode 100644 index 0000000000..59ee4d0b88 --- /dev/null +++ b/test/prism/fixtures/and_or_with_suffix.txt @@ -0,0 +1,17 @@ +foo +and? + +foo +or? + +foo +and! + +foo +or! + +foo +andbar + +foo +orbar diff --git a/test/prism/fixtures/blocks.txt b/test/prism/fixtures/blocks.txt index e33d95c150..51ec84950c 100644 --- a/test/prism/fixtures/blocks.txt +++ b/test/prism/fixtures/blocks.txt @@ -52,3 +52,11 @@ foo lambda { | } foo do |bar,| end + +foo bar baz, qux do end + +foo.bar baz do end + +foo.bar baz do end.qux quux do end + +foo bar, baz do |x| x end diff --git a/test/prism/fixtures/case_in_in.txt b/test/prism/fixtures/case_in_in.txt new file mode 100644 index 0000000000..a5f9e4ec41 --- /dev/null +++ b/test/prism/fixtures/case_in_in.txt @@ -0,0 +1,4 @@ +case args +in [event] + context.event in ^event +end diff --git a/test/prism/fixtures/command_method_call_2.txt b/test/prism/fixtures/command_method_call_2.txt index 165c45987a..8bd40cff9e 100644 --- a/test/prism/fixtures/command_method_call_2.txt +++ b/test/prism/fixtures/command_method_call_2.txt @@ -1,3 +1 @@ -foo(bar baz do end) - foo(bar baz, bat) diff --git a/test/prism/fixtures/endless_methods.txt b/test/prism/fixtures/endless_methods.txt index 7eb3bf4318..6e0488a5ee 100644 --- a/test/prism/fixtures/endless_methods.txt +++ b/test/prism/fixtures/endless_methods.txt @@ -5,3 +5,7 @@ def bar = A "" def method = 1 + 2 + 3 x = def f = p 1 + +def foo = bar baz + +def foo = bar(baz) diff --git a/test/prism/fixtures/heredoc_dedent_line_continuation.txt b/test/prism/fixtures/heredoc_dedent_line_continuation.txt new file mode 100644 index 0000000000..661db490c7 --- /dev/null +++ b/test/prism/fixtures/heredoc_dedent_line_continuation.txt @@ -0,0 +1,5 @@ +<<~FOO + foo\ + \ + bar +FOO diff --git a/test/prism/fixtures/write_command_operator.txt b/test/prism/fixtures/write_command_operator.txt new file mode 100644 index 0000000000..d719d24f87 --- /dev/null +++ b/test/prism/fixtures/write_command_operator.txt @@ -0,0 +1,3 @@ +foo = 123 | '456' or return + +foo = 123 | '456' in BAR diff --git a/test/prism/fixtures_test.rb b/test/prism/fixtures_test.rb index 3a704b8389..dcbcb7c117 100644 --- a/test/prism/fixtures_test.rb +++ b/test/prism/fixtures_test.rb @@ -28,6 +28,8 @@ class FixturesTest < TestCase except << "command_method_call_2.txt" # https://bugs.ruby-lang.org/issues/21669 except << "4.1/void_value.txt" + # https://bugs.ruby-lang.org/issues/19107 + except << "4.1/trailing_comma_after_method_arguments.txt" Fixture.each_for_current_ruby(except: except) do |fixture| define_method(fixture.test_name) { assert_valid_syntax(fixture.read) } diff --git a/test/prism/lex_test.rb b/test/prism/lex_test.rb index 9a9f203c28..8ea7ce7e9b 100644 --- a/test/prism/lex_test.rb +++ b/test/prism/lex_test.rb @@ -48,11 +48,58 @@ def test_parse_lex_file end if RUBY_VERSION >= "3.3" - def test_lex_compare - prism = Prism.lex_compat(File.read(__FILE__), version: "current").value - ripper = Ripper.lex(File.read(__FILE__)) + def test_lex_compat + source = "foo bar" + prism = Prism.lex_compat(source, version: "current").value + ripper = Ripper.lex(source) assert_equal(ripper, prism) end end + + def test_lex_interpolation_unterminated + assert_equal( + %i[STRING_BEGIN EMBEXPR_BEGIN EOF], + token_types('"#{') + ) + + assert_equal( + %i[STRING_BEGIN EMBEXPR_BEGIN IGNORED_NEWLINE EOF], + token_types('"#{' + "\n") + ) + end + + def test_lex_interpolation_unterminated_with_content + # FIXME: Emits EOL twice. + assert_equal( + %i[STRING_BEGIN EMBEXPR_BEGIN CONSTANT EOF EOF], + token_types('"#{C') + ) + + assert_equal( + %i[STRING_BEGIN EMBEXPR_BEGIN CONSTANT NEWLINE EOF], + token_types('"#{C' + "\n") + ) + end + + def test_lex_heredoc_unterminated + code = <<~'RUBY'.strip + < ["), :continuable? + assert_predicate Prism.parse("case foo; when"), :continuable? + end + + def test_splat_and_block_pass + assert_predicate Prism.parse("[*"), :continuable? + assert_predicate Prism.parse("f(**"), :continuable? + assert_predicate Prism.parse("f(&"), :continuable? + end + + def test_default_parameter_value + assert_predicate Prism.parse("def f(x ="), :continuable? + end + + def test_line_continuation + assert_predicate Prism.parse("1 +\\"), :continuable? + assert_predicate Prism.parse("\"foo\" \\"), :continuable? + end + + def test_embedded_document + # Embedded document (=begin) truncated at various points. + assert_predicate Prism.parse("=b"), :continuable? + assert_predicate Prism.parse("=beg"), :continuable? + assert_predicate Prism.parse("=begin"), :continuable? + assert_predicate Prism.parse("foo\n=b"), :continuable? + end + end +end diff --git a/test/prism/result/source_location_test.rb b/test/prism/result/source_location_test.rb index 993150f581..dbda848211 100644 --- a/test/prism/result/source_location_test.rb +++ b/test/prism/result/source_location_test.rb @@ -650,6 +650,10 @@ def test_NilNode assert_location(NilNode, "nil") end + def test_NoBlockParameterNode + assert_location(NoBlockParameterNode, "def foo(&nil); end", 8...12) { |node| node.parameters.block } + end + def test_NoKeywordsParameterNode assert_location(NoKeywordsParameterNode, "def foo(**nil); end", 8...13) { |node| node.parameters.keyword_rest } end diff --git a/test/prism/ruby/parameters_signature_test.rb b/test/prism/ruby/parameters_signature_test.rb index ea1eea106b..5a225862c3 100644 --- a/test/prism/ruby/parameters_signature_test.rb +++ b/test/prism/ruby/parameters_signature_test.rb @@ -50,6 +50,11 @@ def test_nokey assert_parameters([[:nokey]], "**nil") end + def test_noblock + # FIXME: `compare: RUBY_VERSION >= "4.1"` once builds are available + assert_parameters([[:noblock]], "&nil", compare: false) + end + def test_keyrest_anonymous assert_parameters([[:keyrest, :**]], "**") end @@ -74,10 +79,11 @@ def test_forwarding private - def assert_parameters(expected, source) + def assert_parameters(expected, source, compare: true) # Compare against our expectation. assert_equal(expected, signature(source)) + return unless compare # Compare against Ruby's expectation. object = Object.new eval("def object.m(#{source}); end") diff --git a/test/prism/ruby/parser_test.rb b/test/prism/ruby/parser_test.rb index 55c12cab6f..ad9fa0c92c 100644 --- a/test/prism/ruby/parser_test.rb +++ b/test/prism/ruby/parser_test.rb @@ -187,13 +187,7 @@ def test_invalid_syntax end def test_it_block_parameter_syntax - it_fixture_path = Pathname(__dir__).join("../../../test/prism/fixtures/3.4/it.txt") - - buffer = Parser::Source::Buffer.new(it_fixture_path) - buffer.source = it_fixture_path.read - actual_ast = Prism::Translation::Parser34.new.tokenize(buffer)[0] - - it_block_parameter_sexp = parse_sexp { + assert_new_syntax("3.4/it.txt", Prism::Translation::Parser34) do s(:begin, s(:itblock, s(:send, nil, :x), :it, @@ -201,9 +195,20 @@ def test_it_block_parameter_syntax s(:itblock, s(:lambda), :it, s(:lvar, :it))) - } + end + end - assert_equal(it_block_parameter_sexp, actual_ast.to_sexp) + def test_nil_block_parameter_syntax + assert_new_syntax("4.1/noblock.txt", Prism::Translation::Parser41) do + s(:begin, + s(:def, :foo, + s(:args, + s(:blocknilarg)), nil), + s(:block, + s(:lambda), + s(:args, + s(:blocknilarg)), nil)) + end end private @@ -301,6 +306,16 @@ def assert_equal_comments(expected_comments, actual_comments) } end + def assert_new_syntax(path, parser, &sexp) + fixture_path = Pathname(__dir__).join("../../../test/prism/fixtures", path) + + buffer = Parser::Source::Buffer.new(fixture_path) + buffer.source = fixture_path.read + actual_ast = parser.new.tokenize(buffer)[0] + + assert_equal(parse_sexp(&sexp), actual_ast.to_sexp) + end + def parse_sexp(&block) Class.new { extend AST::Sexp }.instance_eval(&block).to_sexp end diff --git a/test/prism/ruby/ripper_test.rb b/test/prism/ruby/ripper_test.rb index 15f535f3d6..92aa1ad0b3 100644 --- a/test/prism/ruby/ripper_test.rb +++ b/test/prism/ruby/ripper_test.rb @@ -37,8 +37,17 @@ class RipperTest < TestCase ] end + if RUBY_VERSION.start_with?("4.") + incorrect += [ + # https://bugs.ruby-lang.org/issues/21945 + "and_or_with_suffix.txt", + ] + end + # https://bugs.ruby-lang.org/issues/21669 incorrect << "4.1/void_value.txt" + # https://bugs.ruby-lang.org/issues/19107 + incorrect << "4.1/trailing_comma_after_method_arguments.txt" # Skip these tests that we haven't implemented yet. omitted_sexp_raw = [ @@ -81,6 +90,16 @@ class RipperTest < TestCase define_method("#{fixture.test_name}_lex") { assert_ripper_lex(fixture.read) } end + def test_lex_ignored_missing_heredoc_end + ["", "-", "~"].each do |type| + source = "<<#{type}FOO\n" + assert_ripper_lex(source) + + source = "<<#{type}'FOO'\n" + assert_ripper_lex(source) + end + end + module Events attr_reader :events diff --git a/test/prism/ruby/ruby_parser_test.rb b/test/prism/ruby/ruby_parser_test.rb index 6e4ba8ce16..bc89bdae72 100644 --- a/test/prism/ruby/ruby_parser_test.rb +++ b/test/prism/ruby/ruby_parser_test.rb @@ -37,6 +37,7 @@ class RubyParserTest < TestCase "alias.txt", "dsym_str.txt", "dos_endings.txt", + "heredoc_dedent_line_continuation.txt", "heredoc_percent_q_newline_delimiter.txt", "heredocs_with_fake_newlines.txt", "heredocs_with_ignored_newlines.txt", @@ -85,16 +86,11 @@ class RubyParserTest < TestCase "3.3-4.0/void_value.txt", - "3.4/circular_parameters.txt", - - "4.0/endless_methods_command_call.txt", - "4.0/leading_logical.txt", - # https://bugs.ruby-lang.org/issues/21168#note-5 "command_method_call_2.txt", ] - Fixture.each(except: failures) do |fixture| + Fixture.each_for_version(version: "3.3", except: failures) do |fixture| define_method(fixture.test_name) do assert_ruby_parser(fixture, todos.include?(fixture.path)) end